MLHW3-tips
徐徐 抱歉选手

Colab使用

Colab工作于Google Drive,创建完成colab notebook后可以根据修改-笔记本设置-硬件加速来选择GPU加速。

在shell指令前添加!就可以在Ipython中运行任何命令行指令。

可以把colab挂载到google drive从而就可以从云端硬盘中读取文件加载到Colab运行,但是每一次新建笔记本后都要配置挂载。

1
2
from google.colab import drive
drive.mount('/content/drive/')

更多参考

Python OS 文件/目录方法

读取某一个路径下的文件夹目录image_dir = sorted(os.listdir(path))

文件夹中的文件数目用(len(image_dir)表示。

遍历该文件夹下的每一个文件for i, file in enumerate(image_dir): img = cv2.imread(os.path.join(path, file))

合并路径os.path.join

定义数据预处理函数

数据预处理分训练集和测试集。使用包import torchvision.transforms as transforms

数据增强是为了防止过拟合的现象,用于数据较少的训练集。通常transforms.Compose将transforms组合在一起构成多次图形变化。

基本步骤

  • 将Tensor类转换为PILImage类transforms.ToPILImage(),
  • 开始多个图片的翻转、旋转等操作。此步骤对训练集不需要
  • 将PILImage类转换回Tensor类transforms.ToTensor()

自定义数据集

先用重写Dataset类对数据封装,重写初始化、长度和索引的函数,结合数据预处理的transform。再读入数据,用DataLoader类。

Dataset

一个自定义Datasets的基本框架,初始化放在__init__()中,其中__getitem__()__len__()两个方法是必须重写的。

基本结构如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class CustomDataset(data.Dataset):#需要继承data.Dataset
def __init__(self):
# TODO
# 1. Initialize file path or list of file names.
pass
def __getitem__(self, index):
# TODO
# 1. Read one data from file (e.g. using numpy.fromfile, PIL.Image.open).
# 2. Preprocess the data (e.g. torchvision.Transform).
# 3. Return a data pair (e.g. image and label).
#这里需要注意的是,第一步:read one data,是一个data
pass
def __len__(self):
# You should change 0 to the total size of your dataset.
return 0

DataLoader

实现分批次读取数据、随机读取数据、并行加载数据。

常用操作有:batch_size(每个batch的大小), shuffle(是否进行shuffle操作), num_workers(加载数据的时候使用几个子进程)。

Dataloader这个类并不需要我们自己设计代码,我们只需要利用DataLoader类读取我们设计好的Dataset子类即可:

1
2
loader = DataLoader(train_dataset, batch_size=16, num_workers=4, shuffle=True)
# 按照batch_size来返回特定数量的训练数据的tensor

自定义神经网络

Torch.nn是专门为神经网络设计的模块化接口,需要重新实现构造函数__init__构造函数和forward这两个方法。

自定义神经网络的模版

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Classifier(nn.Module): # 自定义神经网络需要继承nn.Module类
def __init__(self): # 一般把网络中具有可学习参数的层放在构造函数__init__()中
super(Classifier, self).__init__()

self.cnn = nn.Sequential(
# 这里用nn.Sequential将提供的各类函数包装起来,注意每次输入输出的维度
# 形成一个大的CNN模块
)
self.fullyconnected = nn.sequential(
# 这里是另外一个大的全链接层模块
)

def forward(self, x):
# 在forward中没有必要把细枝末节拼起来
# 只需要把每个大的模块拼接起来
# 同时也要注意输入输出
out = self.cnn(x)
out = out.view(out.size()[0], -1)
return self.fc(out)

技巧

一般把网络中具有可学习参数的层(如全连接层、卷积层等)放在构造函数init()中,当然也可以把不具有参数的层也放在里面。

一般把不具有可学习参数的层(如ReLU、dropout、BatchNormanation层)可放在构造函数中,也可不放在构造函数中,如果不放在构造函数init里面,则在forward方法里面可以使用nn.functional来代替。

forward方法是必须要重写的,它是实现模型的功能,实现各个层之间的连接关系的核心。

训练模型

定义参数如模型、损失函数、梯度下降的方法、epoch的次数。

1
2
3
4
model = Classifier().cuda()
loss = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.001)
num_epoch = 30

for循环每一个epoch,记录每一个epoch的时间,损失,正确率等都要清零。

训练每一笔data的for循环之前一定要开启model.train() 保证自动backpropagation且参数更新。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
for epoch in range(num_epoch):
epoch_start_time = time.time()
train_acc = 0.0
train_loss = 0.0
val_acc = 0.0
val_loss = 0.0

model.train()
for i, data in enumerate(train_loader):
optimizer.zero_grad() #
train_pred = model(data[0].cuda())
batch_loss = loss(train_pred, data[1].cuda())
batch_loss.backward()
optimizer.step()

train_acc += np.sum(np.argmax(train_pred.cpu().data.numpy(), axis=1) == data[1].numpy())
train_loss += batch_loss.item()

测试模型

测试每一笔validation set或者testing set的data之前一定要开启model.eval() 保证不会自动backpropagation参数更新。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
for epoch in range(num_epoch):
epoch_start_time = time.time()
train_acc = 0.0
train_loss = 0.0

model_best.train()
for i, data in enumerate(train_val_loader):
optimizer.zero_grad()
train_pred = model_best(data[0].cuda())
batch_loss = loss(train_pred, data[1].cuda())
batch_loss.backward()
optimizer.step()
train_acc += np.sum(np.argmax(train_pred.cpu().data.numpy(), axis=1) == data[1].numpy())
train_loss += batch_loss.item()

参考

MrSun Blog

pytorch教程之nn.Module类详解

  • 本文标题:MLHW3-tips
  • 本文作者:徐徐
  • 创建时间:2020-11-11 11:07:25
  • 本文链接:https://machacroissant.github.io/2020/11/11/MLHW3-tips/
  • 版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
 评论