Pytorch学习笔记
2020.6
写在前面
稍微得空,整理或者说记录一下pytorch学习过程中的心得与体会。小白的学习笔记,大神请慎入!
本文暂时只记录了部分常用函数,若需要更具体说明,请访问pytorch官网或者阅读中文文档。
本文主要讲解pytorch完成深度学习的步骤和程序实现,对一些原理不会过多深入,若需学习原理,请参考其他理论性教材,如斯坦福大学公开课等。
关于yaml文件参数设置
其实这一点无关pytorch,甚至无关深度学习。我们在较大一些的工程项目中,可能经常会存在较大的参数量,如果任由其渗透在工程文件的边边角角,我们修改参数时需要各个文件寻找,很有可能发生遗漏,甚至可能会一不小心造成误操作,改动了某个参数引发一些潜在的bug,这是非常危险的。为了有效避免这种情况,我们习惯性地将必要调整的参数整合在一个文件中,在这个文件中统一进行修改,甚至可以通过选择读取不同文件的不同参数完成不同的任务。那么,关于参数的读取,就是本节的内容。
关于YAML
YAML 是专门用来写配置文件的语言,非常简洁和强大,远比 JSON 格式方便。(摘自阮一峰先生的博客)
其基本规则如下:
大小写敏感
严格缩进表示层级关系
缩进时不允许使用tab,只允许使用空格(这一点存疑,来自网络,不过个人使用tab好像也可以)
缩进的空格数不重要,主要相同层级的元素左对齐即可
‘#’表示注释,注释该行(同python)
示例:
common: workers: 4 batch_size: 32
python文件中参数的获取
引入必要的包
import argparse # 命令行参数解析包
import yaml # yaml文件解析包
核心语句示例
parser = argparse.ArgumentParser() # 创建对象
parser.add_argument('--config', default='config.yaml', type=str) # 添加参数
args = parser.parse_args() # 解析添加的参数
参数的读取与打印示例
with open(args.config) as f:
config = yaml.load(f)
print("\n**************************")
for k, v in config['common'].items():
setattr(args, k, v)
print('\n[%s]:'%(k), v)
print("\n**************************\n")
batch_size = args.batch_size # 通过这种方式获取参数
命令行调用示例
python train.py --config config.yaml
pytorch与其他数据互转
pytorch与numpy数据互转
import torch
torch_data = torch.from_numpy(numpy_data)
numpy_data = torch_data.numpy()
pytorch与python普通类型数据互转
import torch
tensor = torch.FloatTensor(data)
pytorch定义variable计算梯度
import torch
variable = Variable(tensor, requires_grad=True)
v_out = torch.mean(variable*variable)
v_out.backward()
pytorch激活函数
import torch.nn.functional as F
torch.relu()
torch.sigmoid()
torch.tanh()
F.softplus()
torch.softmax()
pytorch损失函数
loss_func = nn.CrossEntropyLoss()
loss_func = nn.MSELoss()
……
pytorch优化器
import torch
opt_SGD = torch.optim.SGD(net.parameters(), lr=LR)
opt_Momentum = torch.optim.SGD(net.parameters(), lr=LR, momentum=0.8)
opt_RMSprop = torch.optim.RMSprop(net.parameters(), lr=LR, alpha=0.9)
opt_Adam = torch.optim.Adam(net.parameters(), lr=LR, betas=(0.9, 0.99))
……
pytorch网络常用到的基本模块
torch.nn.Linear(in_features, out_features, bias=True)
torch.nn.Conv1d(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True)
torch.nn.Conv2d(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True) # padding=(kernel_size-1)/2 if stride=1 --> 卷积后尺寸不变化
torch.nn.Conv3d(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True)
torch.nn.ReLU()
torch.nn.Dropout(p=0.5, inplace=False)
……
pytorch定义网络基本步骤
import torch
import torch.nn.functional as F
# way1
class Net(torch.nn.Module): # 自己定义的网络都需要继承Module类,并实现init方法和forward方法
def __init__(self, n_feature, n_hidden, n_output):
super(Net, self).__init__()
self.hidden = torch.nn.Linear(n_feature, n_hidden)
self.out = torch.nn.Linear(n_hidden, n_output)
def forward(self, x):
x = F.relu(self.hidden(x))
x = self.out(x)
return x
net = Net(1, 10, 1)
net(x)
# way2
net = torch.nn.Sequential(
torch.nn.Linear(1, 10),
torch.nn.ReLU(),
torch.nn.Linear(10, 1)
)
net(x)
# way3 整合以上两种方法,推荐
class Net(nn.Module):
def __init__(self):
super(CNN, self).__init__()
self.net1 = torch.nn.Sequential(
torch.nn.Linear(1, 10),
torch.nn.ReLU(),
torch.nn.Linear(10, 1)
)
def forward(self, x):
output = self.net1(x)
return output
net = Net()
net(x)
pytorch训练(反向传播)步骤
optimizer = torch.optim.SGD(net.parameters(), lr=learning_rate) # 优化器,里面存放网络参数和梯度
loss_func = torch.nn.CrossEntropyLoss() # 定义使用的损失函数模型
for _ in range(train_step):
out = net(x) # 网络预测值
loss = loss_func(out,y) # 预测值与真实值计算损失函数,返回关于网络参数的函数
optimizer.zero_grad() # 清除梯度
loss.backward() # 反向传播,计算梯度
optimizer.step() # 参数调整,完成一步优化
pytorch网络的保存
# 2 ways to save the net
torch.save(net, 'net.pkl') # save entire net
torch.save(net.state_dict(), 'net_params.pkl') # save only the parameters
pytorch网络的恢复
def restore_net(): # restore entire net
net = torch.load('net.pkl')
prediction = net(x)
def restore_params(): # restore only the parameters
net = torch.nn.Sequential(
torch.nn.Linear(1, 10),
torch.nn.ReLU(),
torch.nn.Linear(10, 1)
) # 先搭建网络
net.load_state_dict(torch.load('net_params.pkl')) # 再恢复参数
prediction = net(x)
pytorch批量训练
import torch
import torch.utils.data as Data
torch_dataset = Data.TensorDataset(input_tensor, lable_tensor)
loader = Data.DataLoader(
dataset=torch_dataset, # 数据集
batch_size=BATCH_SIZE, # mini batch size
shuffle=True, # 是否打乱数据集
num_workers=workers,
)
for epoch in range(3): # 训练完整训练集的次数
for step, (batch_x, batch_y) in enumerate(loader):
# train your data...
pytorch使用GPU加速
# 测试集
test_x = test_data.test_data.cuda()
test_y = test_data.test_labels.cuda()
# net
net.cuda()
# train
for epoch in range(EPOCH):
for step, (x, y) in enumerate(train_loader):
x = x.cuda()
y = y.cuda()
# prediction
pred_y = net(test_x).cuda().data
pytorch实现一个简单的CNN网络示例
(源码来自莫烦python)
import torch
import torch.nn as nn
import torch.utils.data as Data
import torchvision
import os
EPOCH = 1 # 训练多少遍完整的训练集
BATCH_SIZE = 50
LR = 0.001 # learning rate
############# train data and test data start ###########
train_data = torchvision.datasets.MNIST(
root='./mnist/',
train=True,
transform=torchvision.transforms.ToTensor(),
download=False,
)
train_loader = Data.DataLoader(dataset=train_data, batch_size=BATCH_SIZE, shuffle=True)
# pick 2000 samples to speed up testing
test_data = torchvision.datasets.MNIST(root='./mnist/', train=False)
test_x = torch.unsqueeze(test_data.test_data, dim=1).type(torch.FloatTensor)[:2000]/255.
test_y = test_data.test_labels[:2000]
############# train data and test data end #############
# Network
class CNN(nn.Module):
def __init__(self):
super(CNN, self).__init__()
self.conv1 = nn.Sequential( # input shape (1, 28, 28)
nn.Conv2d(
in_channels=1, # input height
out_channels=16, # n_filters
kernel_size=5, # filter size
stride=1, # filter movement/step
padding=2, # if want same width and length of this image after Conv2d, padding=(kernel_size-1)/2 if stride=1
), # output shape (16, 28, 28)
nn.ReLU(), # activation
nn.MaxPool2d(kernel_size=2), # choose max value in 2x2 area, output shape (16, 14, 14)
)
self.conv2 = nn.Sequential( # input shape (16, 14, 14)
nn.Conv2d(16, 32, 5, 1, 2), # output shape (32, 14, 14)
nn.ReLU(), # activation
nn.MaxPool2d(2), # output shape (32, 7, 7)
)
self.out = nn.Linear(32 * 7 * 7, 10) # fully connected layer, output 10 classes
def forward(self, x):
x = self.conv1(x)
x = self.conv2(x)
x = x.view(x.size(0), -1) # flatten the output of conv2 to (batch_size, 32 * 7 * 7)
output = self.out(x)
return output
cnn = CNN()
optimizer = torch.optim.Adam(cnn.parameters(), lr=LR) # optimize all cnn parameters
loss_func = nn.CrossEntropyLoss() # the target label is not one-hotted
for epoch in range(EPOCH):
for step, (b_x, b_y) in enumerate(train_loader):
output = cnn(b_x) # cnn output
loss = loss_func(output, b_y) # cross entropy loss
optimizer.zero_grad() # clear gradients for this training step
loss.backward() # backpropagation, compute gradients
optimizer.step() # apply gradients
if step % 50 == 0:
test_output = cnn(test_x)
pred_y = torch.max(test_output, 1)[1].data.numpy()
accuracy = float((pred_y == test_y.data.numpy()).astype(int).sum()) / float(test_y.size(0))
print('Epoch: ', epoch, '| train loss: %.4f' % loss.data.numpy(), '| test accuracy: %.2f' % accuracy)
一些注意点(持续更新)
nn.CrossEntropyLoss()的真实标签不是不同类标签的概率,而是真实标签的索引。这与tensorflow是有所不同的。
通过cv2.imread()获取的图片通道顺序与卷积的矩阵形状顺序不一致,需要对获取的数据进行reshape(C,h,w)。
Last updated