提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
深入浅出pytorch第三期
pytorch构建深度学习模型分为基本配置,数据读取,模型构建,模型训练,模型评估
一、pytorch基本配置
一般是设备选择和超参数设置
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
#os.environ['CUDA_VISIBLE_DEVICES'] = '0,1' //0,1代表设备号
n_gpu = torch.cuda.device_count()
batch_size = 16
lr = 1e-4
max_epochs = 100
model.to(device)
if n_gpu > 1:
model = torch.nn.DataParallel(model)
二、数据读入
首先要把数据转换为datset
- init: 定义自己的数据集
- getitem: 根据索引index, 返回dataset[index],dataset在__init__中已经定义
- len: 用于返回数据集的样本数
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)
data = MyDataset(data_dir, info_csv, image_list,transform=None)#初始化类,设置数据集所在路径以及变换
dataloader = DataLoader(data,batch_size=128,shuffle=True)#使用DataLoader加载数据,batch_size每个batch的sample数,shuffle=True时打乱数据集
三、模型构建
init:定义网络各个层
forward:定义网络的整个结构
import torch
import torch.nn as nn
import torch.nn.functional as F
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
# 输入图像channel:1;输出channel:6;5x5卷积核
self.conv1 = nn.Conv2d(1, 6, 5)
self.conv2 = nn.Conv2d(6, 16, 5)
# an affine operation: y = Wx + b
self.fc1 = nn.Linear(16 * 5 * 5, 120)
self.fc2 = nn.Linear(120, 84)
self.fc3 = nn.Linear(84, 10)
def forward(self, x):
# 2x2 Max pooling
x = F.max_pool2d(F.relu(self.conv1(x)), (2, 2))
# 如果是方阵,则可以只使用一个数字进行定义
x = F.max_pool2d(F.relu(self.conv2(x)), 2)
x = x.view(-1, self.num_flat_features(x))
x = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
x = self.fc3(x)
return x
def num_flat_features(self, x):
size = x.size()[1:] # 除去批处理维度的其他所有维度
num_features = 1
for s in size:
num_features *= s
return num_features
net = Net()
print(net)
四、模型训练与评估
训练
model=Net()
optimizer=torch.optim.SGD(net.parameters(),lr=lr)#定义优化器
criterion= nn.MSELoss()#定义损失函数
def train(epoch):#进入当前epoch
model.train()#模型进入训练状态,那么模型的参数应该支持反向传播的修改
train_loss = 0
for data, label in dataloader:#读取数据
if torch.cuda.is_available():
data, label = data.cuda(), label.cuda()#将数据放入GPU
optimizer.zero_grad()#将优化器的梯度会变成0(之前也讲过每次backward梯度都会累加)
output = model(data)#得到模型输出
loss = criterion(label, output)# 损失函数,计算损失
loss.backward()#反向传播
optimizer.step()#更新模型参数
train_loss += loss.item()*data.size(0)#计算训练集的损失
train_loss = train_loss/len(train_loader.dataset)#平均loss
print('Epoch: {} \tTraining Loss: {:.6f}'.format(epoch, train_loss))
评估
def val(epoch):
model.eval()#验证/测试状态,则不应该修改模型参数
val_loss = 0
with torch.no_grad():
for data, label in val_loader:
data, label = data.cuda(), label.cuda()
output = model(data)
preds = torch.argmax(output, 1)
loss = criterion(output, label)
val_loss += loss.item()*data.size(0)
running_accu += torch.sum(preds == label.data)
val_loss = val_loss/len(val_loader.dataset)
print('Epoch: {} \tTraining Loss: {:.6f}'.format(epoch, val_loss))