Learner, Metrics, Callbacks

处理训练循环的基本类

您可能想直接跳转到 Learner 的定义。

Utils function


replacing_yield

 replacing_yield (o, attr, val)

临时替换属性的上下文管理器

class _A:
    def __init__(self, a): self.a = a
    @contextmanager
    def a_changed(self, v): return replacing_yield(self, 'a', v)

a = _A(42)
with a.a_changed(32):
    test_eq(a.a, 32)
test_eq(a.a, 42)

mk_metric

 mk_metric (m)

m 转换为 AvgMetric,除非它已经是 Metric

有关更多信息,请参阅下面的 Metric 类。


save_model

 save_model (file, model, opt, with_opt=True, pickle_protocol=2,
             **torch_save_kwargs)

model 保存到 file,同时保存 opt(如果可用,并且 with_opt 为 True)

file 可以是一个 Path 对象、一个字符串或一个打开的文件对象。pickle_protocoltorch_save_kwargs 会传递给 torch.save


load_model

 load_model (file, model, opt, with_opt=True, device=None, strict=True,
             **torch_load_kwargs)

file 加载 model,同时加载 opt(如果可用,并且 with_opt 为 True)

file 可以是一个 Path 对象、一个字符串或一个打开的文件对象。如果传递了 device,模型会加载到该设备上,否则加载到 CPU 上。

如果 strictTrue,文件必须完全包含 model 中每个参数键的权重;如果 strictFalse,则只加载保存的模型中存在的键到 model 中。

您可以通过 torch_load_kwargs 将其他 kwargs 传递给 torch.load

自 PyTorch 2.5 和 fastai 2.7.19 起,load_model 使用 PyTorch 的安全序列化进行模型加载。


SkipToEpoch

 SkipToEpoch (epoch:int)

跳过训练直到 epoch


Learner

 Learner (dls:fastai.data.core.DataLoaders, model:Callable,
          loss_func:Optional[Callable]=None, opt_func:fastai.optimizer.Opt
          imizer|fastai.optimizer.OptimWrapper=<function Adam>,
          lr:float|slice=0.001, splitter:Callable=<function
          trainable_params>, cbs:fastai.callback.core.Callback|collections
          .abc.MutableSequence|None=None, metrics:Union[Callable,collectio
          ns.abc.MutableSequence,NoneType]=None,
          path:str|pathlib.Path|None=None,
          model_dir:str|pathlib.Path='models', wd:float|int|None=None,
          wd_bn_bias:bool=False, train_bn:bool=True, moms:tuple=(0.95,
          0.85, 0.95), default_cbs:bool=True)

model、一些 dlsloss_func 组合在一起以处理训练

类型 默认 详情
dls DataLoaders 包含 fastai 或 PyTorch DataLoaderDataLoaders
model 可调用 用于训练或推理的 PyTorch 模型
loss_func 可选 None 损失函数。默认为 dls 中的损失函数
opt_func fastai.optimizer.Optimizer | fastai.optimizer.OptimWrapper Adam 用于训练的优化函数
lr float | slice 0.001 默认学习率
splitter 可调用 trainable_params 将模型分割成参数组。默认为一个参数组
cbs fastai.callback.core.Callback | collections.abc.MutableSequence | None None 要添加到 LearnerCallback
metrics Union None 要在验证集上计算的 Metric
path str | pathlib.Path | None None 保存、加载和导出模型的父目录。默认为 dlspath
model_dir str | pathlib.Path models 保存和加载模型的子目录
wd float | int | None None 默认权重衰减
wd_bn_bias bool False 对归一化和偏置参数应用权重衰减
train_bn bool True 训练冻结的归一化层
moms tuple (0.95, 0.85, 0.95) 调度器的默认动量
default_cbs bool True 包含默认的 Callback

调用 Learner.fit 时,将使用 opt_func 创建优化器,lr 作为默认学习率。splitter 是一个函数,它接受 self.model 并返回一个参数组列表(如果没有不同的参数组,则只返回一个参数组)。默认是 trainable_params,它返回模型的所有可训练参数。

cbs 是一个或一个列表的 Callback,用于传递给 LearnerCallback 用于训练循环的每次调整。每个 Callback 都注册为 Learner 的属性(使用驼峰命名法)。创建时,defaults.callbacksTrainEvalCallbackRecorderProgressCallback)中的所有回调都会与 Learner 关联。

metrics 是一个可选的度量列表,可以是函数或 Metric(见下文)。

pathmodel_dir 用于保存和/或加载模型。通常 path 会从 dls 推断,但您可以覆盖它或将 Path 对象传递给 model_dir。请确保您可以在 path/model_dir 中写入!

wd 是训练模型时使用的默认权重衰减;momsLearner.fit_one_cycle 中使用的默认动量。wd_bn_bias 控制是否对 BatchNorm 层和偏置应用权重衰减。

最后,train_bn 控制是否即使根据 splitter 应该冻结 BatchNorm 层,它们也会被训练。我们的经验性实验表明,对于迁移学习中的这些层来说,这是最好的行为。

PyTorch 互操作

Learner 的大多数参数可以使用常规的 PyTorch 功能,尽管使用纯 fastai 对象体验会更顺畅,并且您将能够使用库的全部功能。预期是即使您没有端到端使用 fastai,训练循环也能顺利工作。您可能会失去的是解释对象或显示功能。下面的列表解释了如何对所有参数使用纯 PyTorch 对象以及您可能会失去什么。

最重要的是 opt_func。如果您不使用 fastai 优化器,您需要编写一个函数,将您的 PyTorch 优化器包装在一个 OptimWrapper 中。有关更多详情,请参阅优化器模块。这是为了确保库的调度器/冻结 API 与您的代码一起工作。

  • dls 是一个 DataLoaders 对象,您可以从标准的 PyTorch dataloaders 创建它。通过这样做,您将失去所有显示功能,如 show_batch/show_results。您可以查看数据块 API中级数据 API 教程来学习如何使用 fastai 收集数据!
  • model 是一个标准的 PyTorch 模型。您可以使用任何您喜欢的模型,只需确保它接受您的 DataLoaders 中输入数量并返回与目标数量相同的输出。
  • loss_func 可以是您喜欢的任何损失函数。如果您想使用 Learn.predictLearn.get_preds,它需要是 fastai 的损失函数之一,否则您将必须实现特殊方法(有关更多详情,请参阅 BaseLoss 文档之后)。

训练循环

现在让我们看看 Learner 类实现的主要功能:训练循环。


Learner.fit

 Learner.fit (n_epoch, lr=None, wd=None, cbs=None, reset_opt=False,
              start_epoch=0)

使用 cbs 训练 self.modeln_epoch 个周期。可选地 reset_opt

如果提供了 lrwd,则使用它们,否则使用 Learnerlrwd 属性给出的默认值。

所有示例都使用 synth_learner,这是一个训练线性回归模型的简单 Learner

#Training a few epochs should make the model better
learn = synth_learner(lr=0.1)
learn(_before_epoch)
learn.model = learn.model.cpu()
xb,yb = learn.dls.one_batch()
init_loss = learn.loss_func(learn.model(xb), yb)
learn.fit(10)
xb,yb = learn.dls.one_batch()
final_loss = learn.loss_func(learn.model(xb), yb)
assert final_loss < init_loss, (final_loss,init_loss)

Learner.one_batch

 Learner.one_batch (i, b)

在批次 (xb,yb) 上训练或评估 self.model

这是一个由 Learner.fit 调用的内部方法。如果传递了 i,则是该迭代在该周期中的索引。在训练模式下,它对批次执行完整的训练步骤(计算预测、损失、梯度,更新模型参数并清零梯度)。在验证模式下,它停止在损失计算处。训练或验证由 TrainEvalCallback 通过 training 属性内部控制。

不返回任何内容,但 Learnerxypredloss 属性会设置适当的值

b = learn.dls.one_batch()
learn.one_batch(0, b)
test_eq(learn.x, b[0])
test_eq(learn.y, b[1])
out = learn.model(learn.x)
test_eq(learn.pred, out)
test_eq(learn.loss, learn.loss_func(out, b[1]))

Learner.all_batches

 Learner.all_batches ()

self.dl 的所有批次上训练或评估 self.model


Learner.create_opt

 Learner.create_opt ()

使用默认超参数创建优化器

此方法在内部调用以创建优化器,然后通过您传递给 Learner.fit 或您的特定调度器(请参阅 callback.schedule)来调整超参数。

learn = synth_learner(n_train=5, cbs=VerboseCallback())
assert learn.opt is None
learn.create_opt()
assert learn.opt is not None
test_eq(learn.opt.hypers[0]['lr'], learn.lr)
after_create
learn = synth_learner(n_train=5, cbs=VerboseCallback(), opt_func=partial(OptimWrapper, opt=torch.optim.Adam))
assert learn.opt is None
learn.create_opt()
assert learn.opt is not None
test_eq(learn.opt.hypers[0]['lr'], learn.lr)
after_create
wrapper_lr = 1
learn = synth_learner(n_train=5, cbs=VerboseCallback(), opt_func=partial(OptimWrapper, opt=torch.optim.Adam, lr=wrapper_lr))
assert learn.opt is None
learn.create_opt()
assert learn.opt is not None
test_eq(learn.opt.hypers[0]['lr'], wrapper_lr)
after_create

Callback 处理

我们这里只描述与 Callback 相关的基本功能。要了解有关 Callback 以及如何编写它们的更多信息,请查看 callback.core 模块文档。

首先看看 Callback 如何成为 Learner 的属性

#Test init with callbacks
class TstCallback(Callback):
    def batch_begin(self): self.learn.a = self.a + 1

tst_learn = synth_learner()
test_eq(len(tst_learn.cbs), 1)
assert hasattr(tst_learn, ('train_eval'))

tst_learn = synth_learner(cbs=TstCallback())
test_eq(len(tst_learn.cbs), 2)
assert hasattr(tst_learn, ('tst'))

Learner.__call__

 Learner.__call__ (event_name)

调用 self.cbs 中所有 Callbackevent_name

这是内部调用 Callback 的方式。例如,VerboseCallback 只打印事件名称(对调试很有用)

learn = synth_learner(cbs=VerboseCallback())
learn('after_fit')
after_create
after_fit

Learner.add_cb

 Learner.add_cb (cb)

cb 添加到 Callback 列表中并注册 self 为它们的 Learner

learn = synth_learner()
learn.add_cb(TestTrainEvalCallback())
test_eq(len(learn.cbs), 2)
assert isinstance(learn.cbs[1], TestTrainEvalCallback)
test_eq(learn.train_eval.learn, learn)

Learner.add_cbs

 Learner.add_cbs (cbs)

cbs 添加到 Callback 列表中并注册 self 为它们的 Learner

learn.add_cbs([TestTrainEvalCallback(), TestTrainEvalCallback()])
test_eq(len(learn.cbs), 4)

Learner.added_cbs

 Learner.added_cbs (cbs)
learn = synth_learner()
test_eq(len(learn.cbs), 1)
with learn.added_cbs(TestTrainEvalCallback()):
    test_eq(len(learn.cbs), 2)

Learner.ordered_cbs

 Learner.ordered_cbs (event)

训练循环中 eventCallback 列表,按顺序排列

顺序是指使用 Callback 的内部顺序(有关其工作原理的更多信息,请参阅 callback.core)。

learn = synth_learner()
learn.add_cb(TestTrainEvalCallback())
learn.ordered_cbs('before_fit')
[TrainEvalCallback, TestTrainEvalCallback]

Learner.remove_cb

 Learner.remove_cb (cb)

Callback 列表中删除 cb 并取消注册 self 为它们的 Learner

learn = synth_learner()
learn.add_cb(TestTrainEvalCallback())
cb = learn.cbs[1]
learn.remove_cb(learn.cbs[1])
test_eq(len(learn.cbs), 1)
assert cb.learn is None
assert not getattr(learn,'test_train_eval',None)

cb 可以是要删除的 Callback 类(在这种情况下,会删除该回调的所有实例)。

learn = synth_learner()
learn.add_cbs([TestTrainEvalCallback(), TestTrainEvalCallback()])
learn.remove_cb(TestTrainEvalCallback)
test_eq(len(learn.cbs), 1)
assert not getattr(learn,'test_train_eval',None)

Learner.remove_cbs

 Learner.remove_cbs (cbs)

Callback 列表中删除 cbs 并取消注册 self 为它们的 Learner

cbs 的元素可以是回调类型,也可以是 Learner 的实际回调。

learn = synth_learner()
learn.add_cbs([TestTrainEvalCallback() for _ in range(3)])
cb = learn.cbs[1]
learn.remove_cbs(learn.cbs[1:])
test_eq(len(learn.cbs), 1)

Learner.removed_cbs

 Learner.removed_cbs (cbs)

cbs 的元素可以是回调类型,也可以是 Learner 的实际回调。

learn = synth_learner()
learn.add_cb(TestTrainEvalCallback())
with learn.removed_cbs(learn.cbs[1]):
    test_eq(len(learn.cbs), 1)
test_eq(len(learn.cbs), 2)

Learner.show_training_loop

 Learner.show_training_loop ()

显示训练循环中的每个步骤

在每一步中,回调按顺序显示,这有助于调试。

learn = synth_learner()
learn.show_training_loop()
Start Fit
   - before_fit     : [TrainEvalCallback]
  Start Epoch Loop
     - before_epoch   : []
    Start Train
       - before_train   : [TrainEvalCallback]
      Start Batch Loop
         - before_batch   : []
         - after_pred     : []
         - after_loss     : []
         - before_backward: []
         - before_step    : []
         - after_step     : []
         - after_cancel_batch: []
         - after_batch    : [TrainEvalCallback]
      End Batch Loop
    End Train
     - after_cancel_train: []
     - after_train    : []
    Start Valid
       - before_validate: [TrainEvalCallback]
      Start Batch Loop
         - **CBs same as train batch**: []
      End Batch Loop
    End Valid
     - after_cancel_validate: []
     - after_validate : []
  End Epoch Loop
   - after_cancel_epoch: []
   - after_epoch    : []
End Fit
 - after_cancel_fit: []
 - after_fit      : []

before_batch_cb

 before_batch_cb (f)

创建 before_batch 事件的 Callback 的快捷方式,它接受并返回 xb,yb

为了更改传递给模型的数据,您通常会希望连接到 before_batch 事件,如下所示

class TstCallback(Callback):
    def before_batch(self):
        self.learn.xb = self.xb + 1000
        self.learn.yb = self.yb - 1000

由于这种情况非常常见,我们提供了 before_batch_cb 装饰器以使其更容易。

@before_batch_cb
def cb(self, xb, yb): return xb+1000,yb-1000

序列化


Learner.save

 Learner.save (file, with_opt=True, pickle_protocol=2)

将模型和优化器状态(如果 with_opt 为 True)保存到 self.path/self.model_dir/file

file 可以是一个 Path、一个 string 或一个缓冲区。pickle_protocol 会传递给 torch.save


Learner.load

 Learner.load (file, device=None, with_opt=True, strict=True)

使用 deviceself.path/self.model_dir/file 加载模型和优化器状态(如果 with_opt 为 True)

file 可以是一个 Path、一个 string 或一个缓冲区。使用 device 将模型/优化器状态加载到与其保存时不同的设备上。

自 PyTorch 2.5 和 fastai 2.7.19 起,Learner.load 使用 PyTorch 的安全序列化进行模型加载。

with tempfile.TemporaryDirectory() as d:
    learn = synth_learner(path=d)
    learn.fit(1)
    
    #Test save created a file
    learn.save('tmp')
    assert (Path(d)/'models/tmp.pth').exists()
    
    #Test load did load the model
    learn1 = synth_learner(path=d)
    learn1 = learn1.load('tmp')
    test_eq(learn.a, learn1.a)
    test_eq(learn.b, learn1.b)
    test_eq(learn.opt.state_dict(), learn1.opt.state_dict())

Learner.export

 Learner.export (fname='export.pkl', pickle_module=<module 'cloudpickle'
                 from '/home/runner/.local/lib/python3.12/site-
                 packages/cloudpickle/__init__.py'>, pickle_protocol=2)

导出 self 的内容,但不包含 items 和优化器状态,用于推理

使用 pickle_protocolLearner 保存到 self.path/fname。请注意,Python 中的序列化保存的是函数名,而不是代码本身。因此,您用于模型、数据转换、损失函数等的任何自定义代码都应该放在一个模块中,您在导出前在训练环境中导入它,并在加载前在部署环境中导入它。


load_learner

 load_learner (fname, cpu=True, pickle_module=<module 'pickle' from
               '/usr/lib/python3.12/pickle.py'>)

加载 fname 中的 Learner 对象,默认将其放在 cpu

重要

load_learner 使用 Python 不安全的 pickle 模块。恶意构造的 pickle 数据在加载时可以执行任意代码。切勿对不受信任或可能受损的来源使用 load_learner仅加载您完全信任的文件。”

如果您只需要加载模型权重和优化器状态,请改用安全的 Learner.load

警告

load_learner 要求您的所有自定义代码与导出 Learner 时完全位于同一位置(主脚本或您从中导入的模块)。


Learner.to_detach

 Learner.to_detach (b, cpu=True, gather=True)

如果 self.dl 提供 .to_detach 函数,则调用 to_detach,否则调用全局 to_detach

fastai 提供 to_detach,它默认分离 tensor 梯度,并在分布式数据并行 (DDP) 模式下运行时从所有 ranks 收集 (调用 maybe_gather) tensors。

在 DDP 模式下运行时,所有 ranks 需要具有相同的批次大小,DistributedDL 负责根据需要填充批次;然而,当收集所有 tensors(例如用于计算指标、推理等)时,我们需要丢弃填充项。DistributedDL 提供了一个方法 to_detach,可以适当地移除填充。

调用 learner 的 to_detach 方法会尝试在 learner 最后使用的 DataLoader dl 中查找 to_detach 方法,如果找到则使用该方法,否则将使用普通的 to_detach


Metric

 Metric ()

定义度量的蓝图

度量可以是简单的平均值(如准确率),但有时它们的计算稍微复杂一些,不能跨批次平均(如精确率或召回率),这就是为什么我们需要一个特殊的类来处理它们。对于可以计算为批次平均值的简单函数,我们可以使用 AvgMetric 类,否则您需要实现以下方法。

注意

如果您的 Metric 状态依赖于 tensors,请不要忘记将其存储在 CPU 上,以避免任何潜在的内存泄漏。


Metric.reset

 Metric.reset ()

重置内部状态以准备新计算


Metric.accumulate

 Metric.accumulate (learn)

使用 learn 更新新结果的状态


Metric.value

 Metric.value ()

Metric.name

 Metric.name ()

AvgMetric

 AvgMetric (func)

考虑潜在不同的批次大小来平均 func 的值

learn = synth_learner()
tst = AvgMetric(lambda x,y: (x-y).abs().mean())
t,u = torch.randn(100),torch.randn(100)
tst.reset()
for i in range(0,100,25): 
    learn.pred,learn.yb = t[i:i+25],(u[i:i+25],)
    tst.accumulate(learn)
test_close(tst.value, (t-u).abs().mean())

AvgLoss

 AvgLoss ()

考虑潜在不同的批次大小来平均损失

tst = AvgLoss()
t = torch.randn(100)
tst.reset()
for i in range(0,100,25): 
    learn.yb,learn.loss = t[i:i+25],t[i:i+25].mean()
    tst.accumulate(learn)
test_close(tst.value, t.mean())

AvgSmoothLoss

 AvgSmoothLoss (beta=0.98)

损失的平滑平均值(使用 beta 进行指数加权)

tst = AvgSmoothLoss()
t = torch.randn(100)
tst.reset()
val = tensor(0.)
for i in range(4): 
    learn.loss = t[i*25:(i+1)*25].mean()
    tst.accumulate(learn)
    val = val*0.98 + t[i*25:(i+1)*25].mean()*(1-0.98)
    test_close(val/(1-0.98**(i+1)), tst.value)

ValueMetric

 ValueMetric (func, metric_name=None)

用于包含预先计算的度量值(例如在 Callback 中计算并由 func 返回)

def metric_value_fn(): return 5e-3

vm = ValueMetric(metric_value_fn, 'custom_value_metric')
test_eq(vm.value, 5e-3)
test_eq(vm.name, 'custom_value_metric')

vm = ValueMetric(metric_value_fn)
test_eq(vm.name, 'metric_value_fn')

Recorder –


Recorder

 Recorder (add_time=True, train_metrics=False, valid_metrics=True,
           beta=0.98)

在训练期间记录统计信息(学习率、损失和度量)的 Callback

默认情况下,度量仅在验证集上计算,尽管可以通过调整 train_metricsvalid_metrics 来更改。beta 是用于计算损失的指数加权平均值(它为 Learner 提供 smooth_loss 属性)的权重。

Learnerlogger 属性决定了这些度量的处理方式。默认情况下,它只打印它们

#Test printed output
def tst_metric(out, targ): return F.mse_loss(out, targ)
learn = synth_learner(n_train=5, metrics=tst_metric, default_cbs=False, cbs=[TrainEvalCallback, Recorder])
# pat = r"[tensor\(\d.\d*\), tensor\(\d.\d*\), tensor\(\d.\d*\), 'dd:dd']"
pat = r"\[\d, \d+.\d+, \d+.\d+, \d+.\d+, '\d\d:\d\d'\]"
test_stdout(lambda: learn.fit(1), pat, regex=True)

内部


Recorder.before_fit

 Recorder.before_fit ()

准备训练状态


Recorder.before_epoch

 Recorder.before_epoch ()

如果 self.add_time=True,则设置计时器


Recorder.before_validate

 Recorder.before_validate ()

重置损失和度量状态


Recorder.after_batch

 Recorder.after_batch ()

更新所有度量并在训练中记录学习率和平滑损失


Recorder.after_epoch

 Recorder.after_epoch ()

存储并记录损失/度量值

绘图工具


Recorder.plot_loss

 Recorder.plot_loss (skip_start=5, with_valid=True, log=False,
                     show_epochs=False, ax=None)

skip_start 开始绘制损失。可选地,log=True 用于对数轴,show_epochs=True 用于指示周期,以及要绘制在的 matplotlib 轴 ax


CastToTensor

 CastToTensor (after_create=None, before_fit=None, before_epoch=None,
               before_train=None, before_batch=None, after_pred=None,
               after_loss=None, before_backward=None,
               after_cancel_backward=None, after_backward=None,
               before_step=None, after_cancel_step=None, after_step=None,
               after_cancel_batch=None, after_batch=None,
               after_cancel_train=None, after_train=None,
               before_validate=None, after_cancel_validate=None,
               after_validate=None, after_cancel_epoch=None,
               after_epoch=None, after_cancel_fit=None, after_fit=None)

将子类化的 Tensor 转换为 Tensor

PyTorch 中的一个 bug 的变通方案,其中子类化的 tensors(如 TensorBase)在传递给模型时训练速度比 Tensor 慢约 20%。默认添加到 Learner

CastToTensor 的顺序紧接在 MixedPrecision 之前,因此使用 fastai 的 tensor 子类的回调仍然可以使用它们。

如果输入不是子类化的 tensor 或 tensors 的元组,您可能需要在 Learner 执行正向传播之前,通过您自己的回调或在 dataloader 中将 Learner.xbLearner.yb 中的输入转换为 Tensor

如果 CastToTensor 变通方案干扰了自定义代码,可以将其移除

learn = Learner(...)
learn.remove_cb(CastToTensor)

如果移除了 CastToTensor,您应该验证您的输入类型为 Tensor,或者通过自定义回调或 dataloader 实现转换为 Tensor 的操作。

推理函数


Learner.validate

 Learner.validate (ds_idx=1, dl=None, cbs=None)

使用潜在的新 cbsdl 进行验证。

#Test result
learn = synth_learner(n_train=5, metrics=tst_metric)
res = learn.validate()
test_eq(res[0], res[1])
x,y = learn.dls.valid_ds.tensors
test_close(res[0], F.mse_loss(learn.model(x), y), 1e-3)

Learner.get_preds

 Learner.get_preds (ds_idx:int=1, dl=None, with_input:bool=False,
                    with_decoded:bool=False, with_loss:bool=False,
                    act=None, inner:bool=False, reorder:bool=True,
                    cbs:Callback|MutableSequence|None=None,
                    save_preds:Path=None, save_targs:Path=None,
                    with_preds:bool=True, with_targs:bool=True,
                    concat_dim:int=0, pickle_protocol:int=2)

获取 ds_idx-th dbunchset 或 dl 上的预测和目标,可选地包含 with_inputwith_loss

类型 默认 详情
ds_idx int 1 如果 dl 为 None,用于预测的 DataLoader。0:训练。1:验证
dl NoneType None 如果为 None,用于预测的 DataLoader,默认为 ds_idx=1
with_input bool False 返回包含输入的预测
with_decoded bool False 返回解码后的预测
with_loss bool False 返回包含每个 item 损失的预测
act NoneType None 对预测应用激活函数,默认为 self.loss_func 的激活函数
inner bool False 如果为 False,则创建进度条、显示日志、使用临时 cbs
reorder bool True 如果适用,根据数据集索引重新排序预测
cbs Callback | MutableSequence | None None 预测期间应用的临时 Callback
save_preds Path None 保存预测的路径
save_targs Path None 保存目标的路径
with_preds bool True 是否返回预测
with_targs bool True 是否返回目标
concat_dim int 0 连接返回 tensors 的维度
pickle_protocol int 2 用于保存预测和目标的 Pickle 协议
返回值 tuple

with_decoded 还会使用损失函数的 decodes 函数(如果存在)返回解码后的预测。例如,fastai 的 CrossEntropyFlat 在其 decodes 中取预测的 argmax。

根据 Learnerloss_func 属性,将自动选择一个激活函数,以便预测具有意义。例如,如果损失函数是交叉熵的一种情况,将应用 softmax;如果损失函数是带有 logits 的二元交叉熵,将应用 sigmoid。如果您想确保应用某个特定的激活函数,可以使用 act 参数传递它。

当您的预测过大无法全部放入内存时,应该使用 save_predssave_targs。提供一个 Path 对象,指向将保存预测和目标的文件夹。

concat_dim 是批次维度,所有 tensors 将在该维度上连接。

inner 是一个内部属性,它告诉 get_preds 它是在另一个训练循环内部被调用的,以避免递归错误。

注意

如果您想在自定义损失函数上使用 with_loss=True 选项,请确保您已经实现了一个支持 'none' 的 reduction 属性。

#Test result
learn = synth_learner(n_train=5, metrics=tst_metric)
preds,targs = learn.get_preds()
x,y = learn.dls.valid_ds.tensors
test_eq(targs, y)
test_close(preds, learn.model(x))

preds,targs = learn.get_preds(act = torch.sigmoid)
test_eq(targs, y)
test_close(preds, torch.sigmoid(learn.model(x)))

Learner.predict

 Learner.predict (item, rm_type_tfms=None, with_input=False)

item 进行预测,完全解码,损失函数解码和概率

它返回一个包含三个元素的元组,逆序如下: - 模型的预测,可能经过损失函数的激活函数(如果存在) - 解码后的预测,使用其潜在的 decodes 方法 - 完全解码后的预测,使用构建 Datasets/DataLoaders 使用的转换

rm_type_tfms 是一个已弃用的参数,不应使用,并将在未来版本中移除。with_input 将解码后的输入添加到结果中。

class _FakeLossFunc(Module):
    reduction = 'none'
    def forward(self, x, y): return F.mse_loss(x,y)
    def activation(self, x): return x+1
    def decodes(self, x):    return 2*x

class _Add1(Transform):
    def encodes(self, x): return x+1
    def decodes(self, x): return x-1
    
learn = synth_learner(n_train=5)
dl = TfmdDL(Datasets(torch.arange(50), tfms = [L(), [_Add1()]]))
learn.dls = DataLoaders(dl, dl)
learn.loss_func = _FakeLossFunc()

inp = tensor([2.])
out = learn.model(inp).detach()+1  #applying model + activation
dec = 2*out                        #decodes from loss function
full_dec = dec-1                   #decodes from _Add1
test_eq(learn.predict(inp), [full_dec,dec,out])
test_eq(learn.predict(inp, with_input=True), [inp,full_dec,dec,out])

Learner.show_results

 Learner.show_results (ds_idx=1, dl=None, max_n=9, shuffle=True, **kwargs)

显示 ds_idx-th 数据集或 dl 上的一些预测

将显示 max_n 个样本(除非 ds_idxdl 的批次大小小于 max_n,在这种情况下,它将显示尽可能多的样本),并打乱数据,除非您将该标志设置为 falsekwargs 取决于应用。

我们无法在我们的合成 Learner 上显示示例,但请查看所有初学者教程,它们将向您展示此方法在不同应用中的工作原理。

本节的最后几个函数用于内部推理,但对您来说可能不太有用。


Learner.no_logging

 Learner.no_logging ()
learn = synth_learner(n_train=5, metrics=tst_metric)
with learn.no_logging():
    test_stdout(lambda: learn.fit(1), '')
test_eq(learn.logger, print)

Learner.loss_not_reduced

 Learner.loss_not_reduced ()

这要求您的损失函数要么有一个 reduction 属性,要么有一个 reduction 参数(就像所有 fastai 和 PyTorch 损失函数一样)。

迁移学习


Learner.unfreeze

 Learner.unfreeze ()

解冻整个模型


Learner.freeze

 Learner.freeze ()

冻结到最后一个参数组


Learner.freeze_to

 Learner.freeze_to (n)

冻结直到 n 的参数组

TTA


Learner.tta

 Learner.tta (ds_idx=1, dl=None, n=4, item_tfms=None, batch_tfms=None,
              beta=0.25, use_max=False)

使用测试时间增强返回 ds_idx 数据集或 dl 上的预测

实际上,我们使用训练集的变换获取预测 n 次并求平均值。最终预测是该平均值乘以 (1-beta) + 使用数据集变换获得的预测乘以 beta。将 beta 设置为 None 以获得预测和 tta 结果的元组。您也可以通过设置 use_max=True 来使用所有预测的最大值而不是平均值。

如果您想使用新的变换,可以使用 item_tfmsbatch_tfms 进行传递。