use fixedbitset::FixedBitSet;
use crate::{
Classifier,
Sample,
};
pub struct NaiveAggregation<H> {
hypotheses: Vec<H>,
prediction: Vec<FixedBitSet>,
}
impl<H> NaiveAggregation<H>
where H: Classifier
{
#[inline(always)]
pub fn new(
hypotheses: Vec<H>,
sample: &Sample,
) -> Self
{
let targets = sample.target();
let n_hypotheses = hypotheses.len();
let n_pos = targets.iter()
.copied()
.filter(|y| *y > 0.0)
.count();
let mut prediction = Vec::with_capacity(n_pos);
let iter = targets.iter()
.copied()
.enumerate()
.filter_map(|(i, y)| if y > 0.0 { Some(i) } else { None });
for i in iter {
let mut bits = FixedBitSet::with_capacity(n_hypotheses);
hypotheses.iter()
.enumerate()
.for_each(|(t, h)| {
if h.predict(sample, i) > 0 {
bits.put(t);
}
});
prediction.push(bits);
}
Self { hypotheses, prediction }
}
}
impl<H> NaiveAggregation<H>
where H: Classifier + Clone
{
#[inline(always)]
pub fn from_slice(
hypotheses: &[H],
sample: &Sample,
) -> Self
{
let hypotheses = hypotheses.to_vec();
Self::new(hypotheses, sample)
}
}
impl<H> Classifier for NaiveAggregation<H>
where H: Classifier
{
fn confidence(&self, sample: &Sample, row: usize) -> f64 {
let n_hypotheses = self.hypotheses.len();
let mut bits = FixedBitSet::with_capacity(n_hypotheses);
self.hypotheses.iter()
.enumerate()
.for_each(|(t, h)| {
if h.predict(sample, row) == 1 {
bits.put(t);
}
});
if self.prediction.iter().any(|p| p.eq(&bits)) { 1.0 } else { -1.0 }
}
}