针对csv文件类型的深度学习全流程记录
前言
就像我之前的post里讲的那样,输入形式或者说处理对象的多样化是 ai 从业者面对的挑战之一。这篇文章,我将尽力解决存储在 csv 中的数据,涉及到读取、预处理、写入等环节。
读取
pd.read_csv('path')
预处理
一个 csv 文件,里面的值会是什么样呢?一种是数值形式,一种是文本形式。对于数值形式,有哪些处理方法呢?
缺失值处理:检查数据中是否存在缺失值(NaN 或空值),并根据实际情况进行处理。常见的方法包括删除带有缺失值的样本、用平均值或中位数填充缺失值,或使用插值方法进行填充。
特征缩放:对于数值型特征,进行特征缩放可以帮助模型更好地进行训练。常见的特征缩放方法包括标准化(将数据转换为均值为 0,方差为 1 的分布)、归一化(将数据缩放到 0 和 1 之间的范围)等。
异常值处理:检测和处理异常值可以提高模型的鲁棒性。可以使用统计方法(如均值加减三倍标准差)或基于分布的方法来检测异常值,并根据实际情况进行修正或删除。
离散化/分箱处理:将连续型的数值特征转化为离散型特征,可以在一定程度上提高模型的效果。可以使用等频分箱、等宽分箱等方法将数值范围划分为多个离散的区间,并将数值映射到对应的区间。
特征选择:根据数据的实际情况,选择对目标变量有更强相关性的数值特征进行训练。可以使用相关性分析、特征重要性评估等方法进行特征选择。
数据标准化:对于某些具有明确量纲的特征,例如日期、时间等,可以进行数据标准化,将其转换为合适的数值表示,便于模型理解和处理。
对于非数值型数据,可以采取以下预处理措施:
标签编码:对于具有顺序关系的分类变量,可以使用标签编码将其转换为数值表示。例如,将"低"、"中"、"高"转换为 0、1、2 等。
独热编码:对于没有顺序关系的分类变量,可以使用独热编码将其转换为多个二进制特征表示。独热编码将每个类别转换为一个独立的特征,并且只有一个特征的值为 1,其余特征的值都为 0。这可以避免模型将无序的类别变量视为有序的。
词袋模型/文本向量化:对于文本数据,可以使用词袋模型或文本向量化方法将文本转换为数值表示。词袋模型将文本视为单词的集合,并计算每个单词在文本中的出现频率或使用 TF-IDF 等方法进行加权。文本向量化方法(如 Word2Vec、GloVe 等)可以将单词嵌入到低维向量空间中,保留了单词之间的语义关系。
序列编码:对于具有顺序关系的序列数据,例如时间序列或序列文本,可以使用序列编码方法将其转换为数值表示。常见的序列编码方法包括循环神经网络(RNN)和长短期记忆网络(LSTM)等。
类别合并/分组:对于具有大量类别但类别之间相似度较高的非数值型数据,可以考虑将类别进行合并或分组,减少特征维度的同时保留信息。
异常值处理:对于非数值型数据,也可能存在异常值,例如错误的标签或不一致的类别。可以检测和处理这些异常值,例如进行纠正或删除。
标准化
numeric_features = all_features.dtypes[all_features.dtypes != 'object'].index
all_features[numeric_features] = all_features[numeric_features].apply(
lambda x: (x - x.mean()) / (x.std()))
数据集的制作
预处理好数据后,将数据转化为 tensor 格式。要将目前的 pd 表格数据转为 tensor,最简单的方法是 torch.tensor():
train_features = torch.tensor(all_features[:n_train].values, dtype=torch.float32)
这里不是采用继承 torch.utils.Dataset 类的写法,而是直接将 train_features 用一个函数制作数据集:
dataset = torch.utils.data.TensorDataset(*data)
最后包裹一层 DataLoader。
搭建网络
对于网络,可以不用类的写法,而是实现 nn.Sequential 函数:
net = nn.Sequential(
nn.Linear(in_features, 512),
nn.ReLU(),
nn.Dropout(0.2),
nn.Linear(512, 1),
)
这样,节省了不少代码。
损失和优化器
这里的损失采用了 MSE 函数,由于期望值较大(六位数),因此损失值较大,让我以为训练出错了。另外,如果用 SGD,损失将为 nan。改用 Adam 优化器才能正常训练。推测是因为 SGD 对学习率敏感,学习率不设置的很精确的话,训练直接失败。
完整流程
形成一种规范:代码开头,导入库后,跟着指定默认设备,和超参数。接着开始制作数据集,包括数据的预处理。然后定义网络结构、损失函数、优化器。然后是正式的训练代码。最后测试时,记得将 model 调至测试模式,使得 dropout 能正常工作。
总结
之前写 pytorch 的时候,写法很死板。经过这一次练习,接触到了新的写法,比如 dataset 部分和网络部分。