问题定义与数据集创建
为了定义问题,需要准备---输入数据和问题类型。
在获得了输入并确定了问题的类型后,就可以开始使用以下假设来构建模型:
- 数据中隐藏的模式有助于将输入映射到输出;
- 我们拥有的数据足以让模型进行学习;
- 未来或未知的数据将接近历史数据所描述的模式。
成功的衡量标准
成功的衡量标准将直接取决于业务目标。例如,当试图预测风车何时会发生下一次机器故障时,我们会对模型能够预测到故障的次数更感兴趣。简单地使用准确率可能是错误的度量,因为大多数时候模型在机器不出现故障时预测都正确,因为这是最常见的输出。假设得到了98%的准确率,但模型每次预测故障时都是错误的,这样的模型在现实世界中可能没有任何用处。选择正确的成功度量标准对于业务问题至关重要。通常这类问题具有不平衡的数据集。
对于平衡分类问题,其中所有的类别都具有相似的准确率,ROC和AUC是常见的度量。对于不平衡的数据集,可以使用查准率(precision)和查全率(recall)。对于排名问题,可以使用平均精度均值(Mean Average Precision,MAP)。
评估协议
决定好如何评估当前的进展后,重要的事情就是如何评估数据集。可以从评估进展的3种不同方式中进行选择。
- 保留验证集:这是最常用的,尤其是当有足够的数据时。
- K折交叉验证:当数据有限时,这个策略有助于对数据的不同部分进行评估,从而有助于更好地了解性能。
- 迭代K折验证:想进一步提升模型的性能时,这种方法会有所帮助。
准备数据
通过向量化将不同格式的可用数据转换成张量,并确保所有特征进行了伸缩和归一化处理。
模型基线
创建一个非常简单的模型来打破基线分数。在之前的狗猫分类示例中,基线准确度应该是0.5,我们的简单模型应该能够超过这个分数。如果无法超过基线分数,则输入数据可能不包含进行必要预测所需的必要信息。记住,不要在这一步引入任何正则化或dropout。
要使模型工作,必须要做出3个重要的选择。
- 最后一层的选择:对于回归问题,应该是生成标量值作为输出的线性层。对于向量回归问题,应是生成多个标量输出的相同线性层。对于边界框问题,输出的是4 个值。对于二分类问题,通常使用 sigmoid,对于多类别分类问题,则为 softmax。
- 损失函数的选择:问题的类型将有助于决定损失函数。对于回归问题,如预测房价,我们使用均方误差(Mean Squared Error,MSE),对于分类问题,使用分类交叉熵。
- 优化:选择正确的优化算法及其中的一些超参数是相当棘手的,我们可以通过试验找出。对于大多数用例,Adam或RMSprop优化算法效果更好。
|-------|---------|-----------------------|
| 问题类型 | 激活函数 | 损失函数 |
| 二分类 | sigmoid | nn.CrossEntropyLoss() |
| 多类别分类 | softmax | nn.CrossEntropyLoss() |
| 多标签分类 | sigmoid | nn.CrossEntropyLoss() |
| 回归 | | MSE |
| 向量回归 | | MSE |
大到过拟合的模型
一旦模型具有了足够的容量来超越基线分数,就要增加基线容量。增加架构能力的一些简单技巧如下:
- 为现有架构中添加更多层;
- 为已存在的层加入更多权重;
- 训练更多轮数。
我们通常将模型训练足够的轮数,当训练准确率还在提高但验证准确性却停止增加并且可能开始下降时停止训练,这就是模型开始过拟合的地方。到达这个阶段后,就需要应用正则化技术。
请记住,层的数量、大小和训练轮数可能会因问题而异。较小的架构可以用于简单的分类问题,但是对于面部识别等复杂问题,模型架构要有足够的表示能力,并且模型要比简单的分类问题训练更长的时间。
应用正则化
可对下面这些用于正则化模型的参数进行调整。
- 添加dopout
- 尝试不同的架构
- 添加L1或L2正则化
- 尝试不同的学习率
- 添加更多特征或更多数据
我们将使用验证数据集来调整所有上述的超参数。在不断地迭代和调整超参数的同时,可能会遇到数据泄露的问题。因此,应确保有用于测试的保留数据。如果模型在测试数据集上的性能相比训练集和验证集要好,那么我们的模型很有可能在未知的数据上表现良好。但是,如果模型在测试数据上表现不佳,但是在验证和训练数据上表现很好那么验证数据很可能不是对真实世界数据集的良好表示。在这样的情况下,可以使用K折验证或迭代K折验证数据集。
学习率选择策略
-
StepLR: 这个调度器有两个重要的参数。第一个参数是步长,它表示学习率多少轮改变一次,第二个参数是gamma,它决定学习率必须改变多少。对学习率0.01来说,在步长10和gamma为0.1的情况下,学习率每10轮以gamma的倍数变化。也就是说,对于前10轮,学习率变为0.001,并且在接下来的10轮,变成 0.0001。下面的代码解释了 StepLR 的实现。
pythonscheduler=StepLR(optimizer,step size=30,gamma=0.1) for epoch in range(100): scheduler.step() train(...) validate(...)
-
MultiStepLR: MultiStepLR与StepLR的工作方式类似,只不过步长不是规则间断的,步长以列表的形式给出。例如,给出的步长列表为10、15、30,并且对于每个步长,学习率要乘上gamma值。下面的代码演示了MultistepLR的实现。
pythonscheduler =MultiSteplR(optimizer,milestones=[30,80],gamma=0.1) for epoch in range(100): scheduler.step() train(...) validate(...)
-
**ExponentialLR:**每一轮都将学习率乘上gamma值。
-
**ReduceLROnPlateau:**这是常用的学习率策略之一。应用本策略时,当特定的度量指标,如训练损失、验证损失或准确率不再变化时,学习率就会改变。通用实践是将学习率的原始值降低为原来的 1/2~1/10。ReduceLRInplateau的实现如下所示。
pythonoptimizer = torch.optim.SGD(model.parameters(),lr=0 .l,momentum=0.9) scheduler =ReduceLR0nPlateau(optimizer,'min') for epoch in range(l0): train(...) val loss =validate(...) # Note that step should be called after validate() scheduler.step(val loss)