六月份组队学习【深入浅出PyTorch】Task02打卡笔记
时间:2022-11-30 06:00:00
本次吃瓜教程是Datawhale组织团队学习 。
学习资料由开源学习组织Datawhale提供。
开源贡献:李嘉琪、牛志康、刘洋、陈安东、陈玉立、刘兴、郭棉升、乔斌、匡俊伟
笔记的分来自网络检索。如果有侵权联系,可以删除
本研究的对象:
具有高数、线代、概率论的基础,具有一定的机器学习和深度学习基础,熟悉常见概念Python。
内容说明:PyTorch理论与实践结合,由基础知识到项目实战。
学习周期:14天
教程链接:https://datawhalechina.github.io/thorough-pytorch/index.html
B站视频:BV1L44y1472Z
学习者手册:https://mp.weixin.qq.com/s/pwWg0w1DL2C1i_Hs3SZedg
Task02学习内容
- 第三章PyTorch模块的主要组成
-
- 3.1PyTorch的介绍
- 第四章PyTorch基础实战
-
- FashionMNIST时装分类
-
- **配置训练环境和超参数**
- 读入和加载数据
- 验证数据
- 建立训练模型
- 设置损失函数
- 训练和测试
- 模型保存
- 小结
第三章PyTorch模块的主要组成
3.1PyTorch的介绍
第四章PyTorch基础实战
FashionMNIST时装分类
任务内容:
对10类时尚图像进行分类,使用FashionMNIST数据集https://github.com/zalandoresearch/fashion-mnist/tree/master/data/fashion 。下图给出了FashionMNIST几个样本图中的数据,每个小图对应一个样本。
FashionMNIST数据集中包含已经预先划分好的训练集和测试集,其中训练集共60,000张图像,测试集共10,000张图像。每张图像均为单通道黑白图像,大小为28*28pixel,属于10个类别。
让我们逐步实现第三章各部分的内容,完成整个深度学习过程。
import os import numpy as np import pandas as pd import torch import torch.nn as nn import torch.optim as optim from torch.utils.data import Dataset,DataLoader
配置训练环境和超参数
# 配置GPU,这里有两种方式 ## 方案一:使用os.environ os.environ['CUDA_VISIBLE_DEVICES'] = '0' # 方案二:使用“device后续使用GPU的变量用.to(device)即可 device = torch.device("cuda:1" if torch.cuda.is_available() else "cpu") ## 配置其他超参数,如batch_size, num_workers, learning rate, 以及总的epochs batch_size = 256 num_workers = 0 # 对于Windows用户,这里应设置为0,否则会出现多线程错误 lr = 1e-4 epochs = 20
读入和加载数据
教程中有两种方法:
- 下载并使用PyTorch内置数据集
- 从网站下载csv格式存储的数据读入并转换为预期格式
第一种数据读取方法只适用于常见的数据集,如MNIST,CIFAR10等,PyTorch官方提供数据下载。这种方法通常适用于快速测试(例如在测试下进行测试)idea在MNIST数据集是否有效)
第二种数据读取方法需要自己构建Dataset,这对于PyTorch在自己的工作中应用是非常重要的
同时,还需要对数据进行必要的更改。例如,图片需要统一的大小,以便后续能够输入网络训练;需要将数据格式转为Tensor类,等等。 这些变换可以很方便地借助torchvision包来完成,这是PyTorch官方用于图像处理的工具库。
# 首先设置数据变换
from torchvision import transforms
image_size = 28
data_transform = transforms.Compose
([
transforms.ToPILImage(), # 这一步取决于后续的数据读取方式,如果使用内置数据集则不需要
transforms.Resize(image_size),
transforms.ToTensor()
])
## 读取方式一:使用torchvision自带数据集,下载可能需要一段时间
from torchvision import datasets
train_data = datasets.FashionMNIST(root='./', train=True, download=True, transform=data_transform)
test_data = datasets.FashionMNIST(root='./', train=False, download=True, transform=data_transform)
csv数据下载链接:https://www.kaggle.com/zalando-research/fashionmnist
# 读取方式二:读入csv格式的数据,自行构建Dataset类
class FMDataset(Dataset):
def __init__(self, df, transform=None):
self.df = df
self.transform = transform
self.images = df.iloc[:,1:].values.astype(np.uint8)
self.labels = df.iloc[:, 0].values
def __len__(self):
return len(self.images)
def __getitem__(self, idx):
image = self.images[idx].reshape(28,28,1)
label = int(self.labels[idx])
if self.transform is not None:
image = self.transform(image)
else:
image = torch.tensor(image/255., dtype=torch.float)
label = torch.tensor(label, dtype=
torch.long)
return image, label
train_df = pd.read_csv("./FashionMNIST/fashion-mnist_train.csv")
test_df = pd.read_csv("./FashionMNIST/fashion-mnist_test.csv")
train_data = FMDataset(train_df, data_transform)
test_data = FMDataset(test_df, data_transform)
在构建训练和测试数据集完成后,需要定义DataLoader类,以便在训练和测试时加载数据
train_loader = DataLoader(train_data, batch_size=batch_size, shuffle=True, num_workers=num_workers, drop_last=True)
test_loader = DataLoader(test_data, batch_size=batch_size, shuffle=False, num_workers=num_workers)
验证数据
读入后,我们可以做一些数据可视化操作,主要是验证我们读入的数据是否正确
import matplotlib.pyplot as plt
image, label = next(iter(train_loader))
print(image.shape, label.shape)
plt.imshow(image[0][0], cmap="gray")
torch.Size([256, 1, 28, 28]) torch.Size([256])
<matplotlib.image.AxesImage at 0x7f19a043cc10>
搭建训练模型
教程中采用了CNN作为训练模型,因此也参考教程来进行流程的基础实战
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.conv = nn.Sequential(
nn.Conv2d(1, 32, 5),
nn.ReLU(),
nn.MaxPool2d(2, stride=2),
nn.Dropout(0.3),
nn.Conv2d(32, 64, 5),
nn.ReLU(),
nn.MaxPool2d(2, stride=2),
nn.Dropout(0.3)
)
self.fc = nn.Sequential(
nn.Linear(64*4*4, 512),
nn.ReLU(),
nn.Linear(512, 10)
)
def forward(self, x):
x = self.conv(x)
x = x.view(-1, 64*4*4)
x = self.fc(x)
# x = nn.functional.normalize(x)
return x
model = Net()
model = model.cuda()
设定损失函数
教程中使用torch.nn模块自带的CrossEntropy损失
PyTorch会自动把整数型的label转为one-hot型,用于计算CE loss
这里需要确保label是从0开始的,同时模型不加softmax层(使用logits计算),这也说明了PyTorch训练中各个部分不是独立的,需要通盘考虑
criterion = nn.CrossEntropyLoss()
?nn.CrossEntropyLoss # 这里方便看一下weighting等策略
optimizer = optim.Adam(model.parameters(), lr=0.001)
训练和测试
def train(epoch):
model.train()
train_loss = 0
for data, label in train_loader:
data, label = data.cuda(), label.cuda()
optimizer.zero_grad()
output = model(data)
loss = criterion(output, label)
loss.backward()
optimizer.step()
train_loss += loss.item()*data.size(0)
train_loss = train_loss/len(train_loader.dataset)
print('Epoch: {} \tTraining Loss: {:.6f}'.format(epoch, train_loss))
def val(epoch):
model.eval()
val_loss = 0
gt_labels = []
pred_labels = []
with torch.no_grad():
for data, label in test_loader:
data, label = data.cuda(), label.cuda()
output = model(data)
preds = torch.argmax(output, 1)
gt_labels.append(label.cpu().data.numpy())
pred_labels.append(preds.cpu().data.numpy())
loss = criterion(output, label)
val_loss += loss.item()*data.size(0)
val_loss = val_loss/len(test_loader.dataset)
gt_labels, pred_labels = np.concatenate(gt_labels), np.concatenate(pred_labels)
acc = np.sum(gt_labels==pred_labels)/len(pred_labels)
print('Epoch: {} \tValidation Loss: {:.6f}, Accuracy: {:6f}'.format(epoch, val_loss, acc))
for epoch in range(1, epochs+1):
train(epoch)
val(epoch)
模型保存
在训练完成后,通过torch.save保存模型参数或者整个模型,也可以在训练过程中保存模型
save_path = "./FahionModel.pkl"
torch.save(model, save_path)
小结
本次打卡重点是先跟着教程中的示范先走一遍,慢慢把自己新学的东西消化消化。感谢牛志康开辟者提供的jupyternotebook使用教程!