PyTorch主要组成模块
关于深度学习的思考
完成机器学习任务的步骤:
- 需要对数据进行预处理(包括数据格式的统一和必要的数据变换);
- 划分训练集和测试集;
- 选择模型,并设定损失函数和优化方法以及对应的超参数;
- 用模型去拟合训练集数据,并在验证集/测试集上计算模型表现。
深度学习和机器学习的差异主要在代码实现上,
- 首先,由于深度学习所需的样本量很大,导致需要使用批(batch)训练等提高模型表现的策略,将每次训练读取固定数量的样本送入模型中训练;
- 其次在模型实现上,深度神经网络往往需要“逐层”搭建(如卷积层、池化层、批正则化层、LSTM层等),或者预先定义好可以实现特定功能的模块,再把这些模块组装起来。这种模型构建方式能够充分保证模型的灵活性,也对代码实现提出了新的要求。
- 损失函数和优化器的设定是要能够保证反向传播能够在用户自行定义的模型结构上实现的。
深度学习中训练和验证过程最大的特点在于读入数据是按批的,每次读入一个batch_size的数据就放入GPU中训练,然后将损失函数反向传播回网络最前面的层,同时使用优化器调整网络参数。这里会涉及到各个模块配合的问题,训练/验证后还需要根据设定好的指标计算模型表现。
经过以上步骤,一个深度学习任务就完成啦~
基本配置
对于一个Pytorch项目,我们需要导入一些Python常用的包来帮助我们快速实现功能。常见的包有os、numpy、pandas、matplotlib、seaborn和更上层的包cv2,数据分析和指标计算sklearn。此外还需要调用PyTorch自身一些模块便于灵活使用,比如torch、torch.nn、torch.utils.data.Dataset、torch.utils.data.DataLoader、torch.optimizer等。
其次,有几个超参数可以统一设置,方便后续调试时修改:
- batch size
- 初始学习率(初始)
- 训练次数(max_epochs)
- GPU配置
batch_size = 16 #批次的大小
lr = 1e-4 #优化器的学习率
max_epochs = 100 #训练次数
#GPU的设置有两种常见的方式
#方案一:使用os.environ,这种情况如果使用GPU不需要设置
os.environ['CUDA_VISIBLE_DEVICES'] = '0,1'
#方案二:使用“device”,后续对要使用GPU的变量用.to(device)即可
device = torch.device("cuda:1" if torch.cuda.is_available() else "cpu")
当然还会有一些其他模块或用户自定义模块会用到的参数,有需要也可以在一开始进行设置。
数据读入
PyTorch数据读入是通过Dataset+DataLoader的方式完成的,Dataset定义好数据的格式和数据变换形式,DataLoader用iterative的方式不断读入批次数据。
我们可以定义自己的Dataset类来实现灵活的数据读取,定义的类需要继承PyTorch自身的Dataset类。主要包含三个函数:
- init:用于向类中传入外部参数,并定义样本集
- getitem:用于逐个读取样本集合中的元素,可以进行一定的变换,并将返回训练/验证所需的数据
- len:用于返回数据集的样本数
下面以cifar10数据集为例给出构建Dataset类的方式:
import torch
from torchvision import datasets
train_data = datasets.ImageFolder(train_path, transform=data_transform)
val_data = datasets.ImageFolder(val_path, transform=data_transform)
这里使用了PyTorch自带的ImageFolder类的用于读取按一定结构存储的图片数据。(path对应图片存放的目录,目录下包含若干子目录,每个子目录对应属于同一个类的图片)
例子二
图片存放在一个文件夹,另外有一个csv文件给出了图片名称对应的标签。这种情况下需要自己来定义Dataset类:
class MyDataset(Dataset):
def __init__(self, data_dir, info_csv, image_list, transform=None):
'''
args:
data_dir: path to image directory
info_csv: path to the csv file containing image indexes with corresponding labels
image_list: path to the txt file contains image names to training/validation set
transform: optional transform to be applied on a sample
'''
label_info = pd.read_csv(info_csv)
image_file = open(image_list).readlines()
self.data_dir = data_dir
self.image_file = image_file
self.label_info = label_info
self.transform = transform
def __getitem__(self, index):
'''
args:
index: the index of item
returns:
image and its labels
'''
image_name = self.image_file[index].strip('\n')
raw_label = self.label_info.loc[self.label_info['Image_index'] == image_name]
label = raw_label.iloc[:,0]
image_name = os.path.join(self.data_dir, image_name)
image = Image.open(image_name).convert('RGB')
if self.transform is not None:
image = self.transform(image)
return image, label
def __len__(self):
return len(self.image_file)
构建好Dataset后,就可以使用DataLoader来按批次读入数据了,实现代码如下:
from torch.utils.data import DataLoader
train_loader = torch.utils.data.DataLoader(train_data, batch_size=batch_size, num_workers=4, shuffle=True, drop_last=True)
val_loader = torch.utils.data.DataLoader(val_data, batch_size=batch_size, num_workers=4, shuffle = False)
其中:
- batch_size 每次读入的样本数
- num_workers 有多少个进程用于读取数据
- shuffle 是否将读入的数据打乱
- drop_last 对于样本最后一部分没有达到批次数的样本,使其不再参与训练
PyTorch中的DataLoader的读取可以使用next和iter来完成
import matplotlib.pyplot as plt
images, labels = next(iter(val_loader))
print(images.shape)
plt.imshow(images[0].transpose(1,2,0))
plt.show()
参考链接:
https://datawhalechina.github.io/thorough-pytorch/第三章/index.html#