之前实习的时候 PyTorch 用的非常多。PyTorch 的优势是非常灵活,语法非常 pythonic,很接近 NumPy。动态图的特性也让调试变得比 TensorFlow 轻松许多。 不过对于作业 / Kaggle 中相对简单的分类任务,Keras 还是我的第一选择:开箱即用,并且和 scikit-learn 有着类似的接口,因此只需少量的代码即可实现模型的训练和迭代。而在 PyTorch 中,很多相似的功能都需要自己手动多写几行代码,对我这个懒人不太友好。 在帮朋友解决问题的时候,发现对 PyTorch 有些生疏,而且官方的例子里并没有具体的例子讲述如何用 NumPy 的数据作为数据集,于是这里便记录一下,方便以后参考。
导入库
第一步是需要导入各种库
|
|
数据集加载
比较 tricky 的就是构建 PyTorch 中的 Dataset 和 DataLoader 了。虽然非常好用,比如可以自定义实现 DataLoader、Transform 等,但刚上手的时候容易出错。
在用 train_test_split 将 NumPy 数据集划分好后,第一步需要将它们转换为 PyTorch 中的 Tensor,之后用 TensorDataset
创建 Dataset
对象,最后用 DataLoader
创建数据集加载器,之后在训练中会需要用到。
|
|
构建模型
下面定义一个简单的 ConvNet
类,里面实现了一个两层的 CNN。在 __init__()
里定义一些层并实现了 forward()
前向传播。因为 PyTorch 是动态图计算,因此不需要手动定义反向传播的计算过程。
|
|
之后可以用 torch-summary 或 tensorwatch 输出模型每一层的参数:
|
|
可以得到如下的输出:
----------------------------------------------------------------
Layer (type) Output Shape Param #
================================================================
Conv1d-1 [-1, 16, 1024] 112
MaxPool1d-2 [-1, 16, 512] 0
Conv1d-3 [-1, 32, 512] 1,568
MaxPool1d-4 [-1, 32, 256] 0
Linear-5 [-1, 10] 81,930
================================================================
Total params: 83,610
Trainable params: 83,610
Non-trainable params: 0
----------------------------------------------------------------
Input size (MB): 0.01
Forward/backward pass size (MB): 0.38
Params size (MB): 0.32
Estimated Total Size (MB): 0.70
----------------------------------------------------------------
因为是多分类任务,所以使用了 torch.nn.CrossEntropyLoss(),需要注意的是其中包含了 Softmax
因此我们不需要在网络中手动实现。优化器选择了 torch.optim.Adam,并设置学习速率为常见的 0.001
。
|
|
训练
最后我们就能实现模型训练过程,最外面是循环 EPOCHS
次,每个 epoch
中定义累积的 running_loss
,前面定义的 train_loader
一次能够给出 BATCH_SIZE
的训练样本,在内循环中就能够得到训练数据并进行前向计算、计算 loss、计算梯度、优化器迭代更新整个模型的参数。
|
|
输出:
|
|
GPU 训练
如果要用 GPU 训练,需要指定 device,并且将模型以及每个 Batch 的数据都传到 GPU device 中,在上面的基础上改动或添加以下的代码:
|
|
PyTorch Recipes 里给出了更多常用的例子,包括 保存 / 读取模型、使用 Tensorboard 等,可以进一步参考。