use crate::learner::base::Interrupter;
use crate::metric::processor::{EventProcessorTraining, LearnerEvent, TrainingItem};
use crate::{
InferenceStep, Learner, LearningComponentsTypes, SupervisedTrainingEventProcessor, TrainLoader,
ValidLoader,
};
use burn_core::data::dataloader::Progress;
use burn_core::module::AutodiffModule;
use burn_optim::GradientsAccumulator;
#[derive(new)]
pub struct SingleDeviceValidEpoch<LC: LearningComponentsTypes> {
dataloader: ValidLoader<LC>,
}
#[derive(new)]
pub struct SingleDeviceTrainEpoch<LC: LearningComponentsTypes> {
dataloader: TrainLoader<LC>,
grad_accumulation: Option<usize>,
}
impl<LC: LearningComponentsTypes> SingleDeviceValidEpoch<LC> {
pub fn run(
&self,
learner: &Learner<LC>,
global_progress: &Progress,
processor: &mut SupervisedTrainingEventProcessor<LC>,
interrupter: &Interrupter,
) {
let epoch = global_progress.items_processed;
log::info!("Executing validation step for epoch {}", epoch);
let model = learner.model().valid();
let mut iterator = self.dataloader.iter();
let mut iteration = 0;
while let Some(item) = iterator.next() {
let progress = iterator.progress();
iteration += 1;
let item = model.step(item);
let item = TrainingItem::new(
item,
progress,
global_progress.clone(),
Some(iteration),
None,
);
processor.process_valid(LearnerEvent::ProcessedItem(item));
if interrupter.should_stop() {
break;
}
}
processor.process_valid(LearnerEvent::EndEpoch(epoch));
}
}
impl<LC: LearningComponentsTypes> SingleDeviceTrainEpoch<LC> {
pub fn run(
&self,
learner: &mut Learner<LC>,
global_progress: &Progress,
processor: &mut SupervisedTrainingEventProcessor<LC>,
interrupter: &Interrupter,
) {
let epoch = global_progress.items_processed;
log::info!("Executing training step for epoch {}", epoch,);
let mut iterator = self.dataloader.iter();
let mut iteration = 0;
let mut accumulator = GradientsAccumulator::new();
let mut accumulation_current = 0;
while let Some(item) = iterator.next() {
iteration += 1;
learner.lr_step();
log::info!("Iteration {iteration}");
let progress = iterator.progress();
let item = learner.train_step(item);
match self.grad_accumulation {
Some(accumulation) => {
accumulator.accumulate(&learner.model(), item.grads);
accumulation_current += 1;
if accumulation <= accumulation_current {
let grads = accumulator.grads();
learner.optimizer_step(grads);
accumulation_current = 0;
}
}
None => learner.optimizer_step(item.grads),
}
let item = TrainingItem::new(
item.item,
progress,
global_progress.clone(),
Some(iteration),
Some(learner.lr_current()),
);
processor.process_train(LearnerEvent::ProcessedItem(item));
if interrupter.should_stop() {
break;
}
}
processor.process_train(LearnerEvent::EndEpoch(epoch));
}
}