每个人都可以轻松地将数据放入任何模型机器学习或深度学习框架中。但是遵循最佳实践技巧可能有助于提升工作效率。以下是常见的一些方法。
数据预处理
模型训练
调试
生产
处理原始数据(Process Your Own Data)
因为消费者可能不知道开展数据处理和特征工程,所以数据分析师需要在模型内进行数据预处理。
因此,建议在代码中嵌入数据预处理,而不是要求客户机进行预处理。
使用张量(Use Tensor)
张量是一个N维数组,用于多维计算。它比使用Python字典或数组要快,深度学习框架(例如PyTorch或TensorFlow)的对象数据格式是tensor。
数据扩充(Data Augmentation)
缺少标记数据是从业者通常面临的挑战之一。迁移学习是克服这一问题的途径之一,计算机视觉从业者可以考虑使用ResNet,自然语言处理从业者可以考虑BERT。另一方面,可以生成合成数据以增加标记数据。albumentations和imgaug可以生成图像数据,而nlpaug可以生成文本数据。
如果你了解你的数据,你应该量身设计数据扩充方法。请记住,数据科学的黄金法则是garbage in garbage out。
数据采样(Sampling Same Data)
大多数情况下,我们希望随机抽取数据,以保持样本数据在训练集、测试集和验证集之间的概率分布是一致的。同时,也希望保持这种“随机”行为,使得我们可以在不同的时刻获得相同的训练集、测试集和验证集。
import torch
import numpy as np
import random
seed = 1234
random.seed(seed)
np.random.seed(seed)
torch.manual_seed(seed)
torch.cuda.manual_seed(seed)
存储中间状态(Saving Intermediate Checkpoint)
只是在训练完成后保存模型,通常具有以下几个缺点:
理想情况下,我们可以连续性存储模型(例如,在每个epoch之后保存模型),但它需要大量的存储。事实上,我们建议只保留最好的模型(或最好的三个模型)和最后一个模型。
虚拟周期(Virtual Epoch)
Epoch是模型训练中一个非常常见的参数。如果初始化不正确,可能会影响模型性能。
例如,如果我们有100万条记录,我们设置了5个epoch,那么总共有500万条的训练数据。三周后,我们又得到了50万条记录。如果我们使用相同的epoch进行模型训练,总训练数据将达到750万。问题是:
建议用虚拟epoch代替原始静态epoch。虚拟epoch可以根据训练数据的大小、期望epoch、批大小来计算得到。
通常的静态epoch如下:
#original
num_data = 1000 * 1000
batch_size = 100
num_step = 14 * 1000 * 1000
num_checkpoint = 20
steps_per_epoch = num_step//num_checkpoint
#TensorFlow/ Keras
model.fit(x, epoch=num_checkpoint, steps_per_epoch=steps_per_epoch,
batch_size=batch_size
)
而虚拟epoch如下:
num_data = 1000 * 1000
num_total_data = 14 * 1000 * 1000
batch_size = 100
num_checkpoint = 20
steps_per_epoch = num_total_data // (batch_size*num_checkpoint)
#TensorFlow/ Keras
model.fit(x, epoch=num_checkpoint, steps_per_epoch=steps_per_epoch,
batch_size=batch_size
)
简化原则(Simple is Beauty)
从业者通常打算使用最先进的模型来构建初始模型。事实上,我们建议建立一个足够简单的模型作为基线模型。原因是:
以下是一些建议的不同领域的基线模型:
简化问题(Simplifying Problem)
有时,分类问题包括100万个数据和1000个类别。当模型性能低于理想值时,很难调试模型。糟糕的性能可能是由模型复杂性、数据质量或bug造成的。因此,建议简化问题,这样我们就可以保证它是无缺陷的。我们可以利用过度拟合问题来实现这一目标。
一开始,不需要对1000个类别进行分类,可以先对10个类别进行抽样,每个类别有100个数据,并训练模型。通过使用相同的训练数据集(或子集)作为评估数据集,能够过度拟合模型并获得良好的结果(例如,80甚至90+的精确度)。在这一基础上进行模型开发能够减少bug的出现。
使用评估模式(Using Eval Mode for Training)
如果评估模式的精度在前几个epoch中没有变化,通常可能是忘记在评估后重置为“训练”模式。
在Pytorch中,需要在训练和评估阶段转换训练模式以及评估模式。如果启用训练模式,批标准化、dropout或其他参数将受到影响。有时,数据分析师可能会在评估模式后忘记启用训练模式。
model = MyModel() # Default mode is training mode
for e in range(epoch):
# mode.train() # forget to enable train mode
logits = model(x_train)
loss = loss_func(logits, y_train)
model.zero_grad()
loss.backward()
optimizer.step()
mode.eval() # enable eval mode
with torch.no_grad():
eval_preds = model(x_val)
数据转换(Data Shifting)
当训练数据集与评估/测试数据集存在显著差异时,需要进行数据转换。在计算机视觉任务中,可能大部分训练数据是白天的图片,而测试数据是夜间的图片。
如果发现训练损失/准确度和测试损失/准确度之间存在很大差异,可以从两个数据集中随机抽取一些样本进行检查。为了解决这个问题,可以考虑如下方法:
欠拟合问题(Addressing Underfitting)
欠拟合是指训练误差大于期望误差。换言之,模型无法达到预期的性能。造成大误差的因素很多。要解决这个问题,可以从一个更简单的模型或者方法开始,看看它是否可以解决。
过拟合问题(Addressing Overfitting)
除了欠拟合,你还可能面临着过拟合的问题。过度拟合意味着你的模型太适合你的训练集,而对其他数据没有足够的适用性。换句话说,训练集准确性比验证集准确性要好。考虑以下解决方法:
元数据联系(Meta Data Association)
在模型推出后,需要检查一些例外数据。一种方法是生成ID并将添加到数据库中。然而,它伴随着几个问题,也增加了故障排除的难度。以下是一些缺点:
为了克服这个问题,预测结果应该直接与使用者的关键数据相关联。
转换为推理模型(Switch to Inference Mode)
使用Pytorch时,在将模型部署到生产环境中时,需要注意几个设置。前面提到了Pytorch中的eval,它使这些层(如Dropout、BatchNorm)在推理模式下工作,例如在推理阶段内不应用任何Dropout操作。它不仅能加快你的进程,而且能把所有的信息输入神经网络。
mode.eval() # enable eval mode
with torch.no_grad():
eval_preds = model(x_val)
计算成本(Scalling Cost)
当尝试扩展API以处理更大的数据量时,有时可能会考虑使用GPU。的确,GPU虚拟机比CPU贵得多。然而,GPU带来了一些优势,例如计算时间更少,并且需要较少的VM来维持相同的服务级别。数据分析师应该试着评估一下GPU是否能节省一些钱。
无状态化(Stateless)
试着使你的API无状态化,这样你的API服务可以很容易地调整。无状态意味着不在API服务器(内存或本地存储)中保存任何中间结果。只需保持API服务器的简单性,并将结果返回给客户端,而无需在内存或本地存储中存储任何内容。
批处理(Batch Process)
预测一组数据通常比逐个预测更快。大多数现代机器学习或深度学习框架优化了预测性能(在速度方面)。你可能会注意到,切换到批处理模式预测对于效率有很大的改进。
使用C++
虽然Python是机器学习领域中的主流语言,但与其他编程语言(如C++)相比,Python可能太慢了。如果希望低延迟的计算推理时间,可以考虑使用TorchScript。一般的方案是,你仍然可以在Python中训练你的模型,但是通过使用它生成C++兼容的模型。
作者:Edward Ma
deephub翻译组:Oliver Lee