将Pytorch完成深度学习的步骤拆解为几个主要步骤
深度学习—>搭积木
1.基本配置
2.数据读入
3.模型构建
4.损失函数
5.优化器
6.训练与评估
实际的使用根据自身需求修改对应模块就可以了
数据简介:
10类图片
32*32px
导入必要的packages
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["CUDA_VISIBLE_DEVICES"]="0"
device=torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
#配置其他超参数
batch_size=256
num_workers=4#工作线程数
lr=1e-4
epochs=20
数据读入和加载
如何读取格式不定的本地数据:Dataset
init,getitem,len
如何将数据加载以供模型输入:DataLoader
batch_size,num_workers,shuffle,drop_last,pin_memory
代码演示
#首先设置数据变换
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格式数据,自行构建Dataset类
#csv数据下载链接:https://www.kaggle.com/zalando-research/fashionmnist
class FMDataset(Dataset):
def __init__(self,df,transfrom=None):
self.df=df
self.transform=transform
self.images=df.iloc[:,1:].values.astype(np.units)
self.labels=df.iloc[:,0].values
def __len__(self):
return len(self.images)
def __getitem__(self,idx):
image=self.image[idx].reshape(28,28,1)
label=int(self.labels[idx])
if self.transform is not None:
image=self.transfrom(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')
模型构建
神经网络的构造:基于nn.Module
-__init __, forward
神经网络是通过“层定义+层顺序“的方式构建起来的
神经网络常见层
-nn.Conv2d,nn.MaxPool2d,nn.Linear,nn.Relu,…
帮助文档自动弹出 比如你对nn.Conv2d的三个参数设置不理解 就可以如下
?nn.Conv2d()
由于任务简单,我么这里手搭一个CNN,而不考虑当下各种模型的复杂结构
模型构建完成后,将模型放到GPU上用于训练
代码演示
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()
# model = nn.DataParallel(model).cuda() # 多卡训练时的写法,之后的课程中会进一步讲解
设定损失函数
使用torch.nn模块自带的CrossEntropy损失
Pytorch会自动吧整型label转为one-hot型,用于计算CE Loss
这里需要确保label是从0开始的,同时模型不加softmax层(使用logits计算),这也说明了Pytorch训练中各个部分不是独立的,需要通盘考虑
torch.nn提供了多种预定义的损失函数
可以自己定义损失函数(二期)
根据实际需求选用对应的损失函数
损失函数常用操作
backward()
代码演示
criterion=nn.CrossEntropyLoss()
设定优化器
这里我么使用Adam优化器
优化器
torch.optim提供了多种预定义的优化器
可以自己定义优化器(二期)
根据实际需求选用对应损失函数
优化器常用操作:
step(),zero_grad(),load_state_dict()…
代码演示
optimizer=optim.Adam(model.parameters(),lr=0.01)
训练和测试(验证)
各自封装成函数,方便后续调用
关注两者主要区别
模型状态设置
是否需要初始化优化器
是否需要将loss传回到网络
是否需要每步更新optimizer
此外,对于测试或验证过程,可以计算分类准确率
模型训练和评估
模型状态设置
model.train(),model.eval()
训练流程:读取、转换、梯度清零、输入、计算损失、反向传播、参数更新
验证流程:读取、转换、输入、计算损失、计算指标
代码演示
def train(epoch):
model.train()
train_loss=0
#for i,(data,label) in enumerate(train_loader):
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:{}\t Training 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)
gpu_info=!invida-smi -i 0
gpu_info='\n'.join(gpu_info)
print(gpu_info)
模型保存
训练完成后,可以使用torch.save保存模型参数或整个模型,也可以在训练过程中保存模型
save_path="./FashionModel.pkl"
torch.save(model,save_path)