pytorch笔记:⼀些常见操作,构建全连接神经⽹络,验证操作,评估模式
⽂章⽬录
Pytorch是神经⽹络届的numpy,numpy会把array放到CPU中加速计算,torch会把tensor放到GPU中加速计算。torch和numpy 有很多⽤法是⼀样的,只不过numpy的⽅法接受的是array或者matrix,torch接受的是tensor。
按照官⽹安装,⼀般是两⾏命令,第⼀⾏装的是pytorch的主模块,第⼆⾏安装的torchvision,会包含⼀些数据库,例如图⽚数据库,还有⼀些预先训练好的模型,例如VGG,ResNet,在写神经⽹络模型时,可以直接照搬⾥⾯的模板。
在使⽤之前需要导⼊库,⼀般有
import torch
from torch import nn # 这个库⽤于构建神经⽹络的结构,neural networks的缩写
# ⾥⾯包括线性层,卷积层,循环神经⽹络单元等,当然也包括很多的激活函数
from torch import optim # 优化⽅法,MSE,交叉熵等
from torch.utils.data import DataLoader # ⽤于mini-batch SGD的喂数据的类
还有⼀些类可以根据需要选择是否导⼊
from torch.autograd import Variable # 变量类,以前需要把tensor类型变成variable类型才可以反向传播
# 现在版本⼀般合并了tensor类型和variable类型,直接⽤tensor类型就可以反向传播
from collections import OrderedDict # 字典⼀般没有先后顺序,OrderedDict ⽤以⽣成有先后顺序的字典
from torch.utils.data.sampler import SubsetRandomSampler # ⼿动抽样的类,根据需要选择是否导⼊这个库
我们可以通过下⾯的⽅法,查看pytorch的版本,以及是否⽀持使⽤GPU加速
print(torch.__version__)
print(torch.cuda.is_available())
可以通过下⾯的⽅法查看可以使⽤多少GPU
print(torch.cuda.device_count())
⽣成tensor
使⽤pytorch时,要注意三种⼤的数据类型,⼀是传统python的List和numpy的nd.array,⼆是pytorch中的tensor,三是pytorch 中的variable;早期版本,我们需要沿着这条线,从传统python数据结构转换到tensor,在从tensor转换到variable,只有variable才可以进⾏反向传播,但是较新的版本的pytorch合并了tensor和variable的功能(variable类仍然存在,仍可以按照⽼版代码写),不需要转换variable,只需要把tensor的requires_grad参数设置为True,如果requires_grad=Fasle时不需要更新梯度, 适⽤于冻结某些层的梯度。
# 法⼀:从numpy库⽣成模板
data = [1,2,3,4]
data = np.array(data)
tensor = torch.from_numpy(data) # 默认⽣成torch.int
data = [1.,2,3,4]
data = np.array(data)
tensor = torch.from_numpy(data) # 默认⽣成torch.float64
## 同样也可以把tensor转换成numpy形式
data2 = tensor.numpy()
# 法⼆:利⽤pytorch的⼀些函数,这些函数⼀般和numpy中的类似
tensor = s(1, requires_grad=True) # 对应numpy中的np.zeros()
# requires_grad=True表⽰tensor写⼊计算图,进⾏梯度反向传播
tensor = torch.linspace(-5,5,200) # 对应numpy中的np.linspace()
tensor = torch.add(tensor,tensor) # 对应numpy中的np.add()
tensor = an(tensor) # 对应numpy中的np.mean()
# 法三:当然也可以直接转换成FloatTensor等tensor形式
tensor = torch.FloatTensor([[1,2],[3,4]]) # 直接把list转化成浮点形式的tensor
格式转换
data = [1,2,3,4]
data = np.array(data)
tensor = torch.from_numpy(data) # 默认⽣成torch.int
tensor = pe(torch.float) # 转化为torch.float32
tensor = pe(torch.float64) # 转化为torch.float64
tensor = pe(torch.float16) # 转化为torch.float16
tensor = pe(torch.int8) # 转化为torch.int8
设置requires_grad参数
# ⽣成tensor变量时就设置requires_grad
tensor = s(1, requires_grad=True) # ⽣成时默认requires_grad参数是False,除⾮声明requires_grad=True
# 单个tensor变量改变requires_grad
tensor = torch.FloatTensor([[1,2],[3,4]]) # ⽣成时默认requires_grad参数是False,torch.FloatTensor没有requires_grad参数
# 或者
# 整个模型改变requires_grad
for param in model.parameters():
注意:只有浮点类型⽀持backword⾃动求导,且求导,只能是【标量】对标量,或者【标量】对向量/矩阵求导!,⼀般loss函数求出来的就是⼀个标量。如果⾃变量是向量、矩阵、张量等,需要定义backword()中的gradients参数。
构建全连接神经⽹络
在PyTorch中,所有的neural network module都是Module的⼦类,在Modules中可以包含其它的Modules。
构建全连接神经⽹络模型
# 搭建神经⽹络
class Module): # 标准模板
def __init__(self, n_features, n_hidden, n_output): # 标准模板,定义⽣成模型时传⼊的参数
super(Net, self).__init__() # 标准模板
self.hidden = Linear(n_features, n_hidden) # 全连接层,输⼊n_features, 输出n_hidden
linspace numpy
self.predict = Linear(n_hidden, n_output) # 全连接层,输⼊n_hidden, 输出n_output
def forward(self, x): # 标准模板,定义前向传播, self⼀定要有, x是输⼊模型的数据
self.x = x
self.x = F.relu(self.hidden(self.x))
self.x = self.predict(self.x)
return self.x
选择损失函数
# 回归⼀般⽤MSE
loss_func = MSELoss()
# 分类⼀般⽤交叉熵
loss_func = CrossEntropyLoss()
选择优化⽅法
如果没有特殊的选择,就选择Adam,Adam可以适⽤于⼤多数的场景。
opt = torch.optim.Adam(net.parameters(), lr = 0.2)
pytorch中,学习率可以动态更新,例如在迭代了75%的epoch时,把学习率缩⼩为原来的⼗分之⼀
lr_new = 0.001 # 新定义的学习率
for param_group in opt.param_groups:
param_group['lr'] = lr_new
反向传播
<_grad() # 标准流程,梯度清零,猜测是因为要根据batch中的所有数据的梯度求平均,
# 所以每个参数位置都有batch个梯度,在进⼊下⼀个batch循环前,要清零
loss.backward() # 标准流程,反向传播计算梯度,进⾏⼀次反向传播,计算图就会被销毁,如果不想让计算图销毁,可以retain_graph=True
opt.step() # 标准流程,更新所有参数
# backward只把梯度传给每个变量,优化器再根据梯度来优化这些变量的值
批训练操作
⽣成dataloader:
# 批数据训练
BATCH_SIZE = 10
torch_dataset = Data.TensorDataset(x,y) # 这⼀步是把x,y融合在⼀起,
# 当然可以不做这⼀步,dataloader中的dataset传⼊list,list的size是 <N,2,x.size以及y.size>
# 依次为list类型,list或tuple类型,ndarray,⽽不是全ndarray
# 这样的输⼊有效避免了特征和标签数据量不匹配⽣成ndarray.object,使得dataloader报错。
loader = Data.DataLoader(
dataset = torch_dataset,
batch_size = BATCH_SIZE,
shuffle = True, # 是否打乱数据
)
当然dataloader可以传⼊sampler参数(⼀个列表),⾃定义从数据集中提取样本的顺序。如果指定sampler,则忽略shuffle参数。 使⽤dataloader时,利⽤了python的enumerate
for epoch in range(10):
for step, (batch_x, batch_y) in enumerate(loader):
pred = net(batch_x)
loss = loss_func(pred, batch_y)
<_grad()
loss.backward()
opt.step()
GPU加速
先定义使⽤哪个GPU或CPU,默认GPU是从零开始编号,也就是说,如果设置torch.device(“cuda:3”),就使⽤了第4块显卡。
device = torch.device("cuda:3" if torch.cuda.is_available() else "cpu")
print(device)
# 输出:
# device(type='cuda', index=3)
pytorch中想要使⽤GPU加速,只需把模型、数据后⾯加上" .to(device) "即可,优化⽅法和损失函数加不加都可以。注意这个时候数据类型已经不同,如果CPU下数据类型是torch.FloatTensor,GPU模式下数据类型就变成了torch.cuda.FloatTensor。
print(torch.FloatTensor([1.])) # 输出:tensor([1.])
print(torch.FloatTensor([1.]).to(device)) # 输出:tensor([1.], device='cuda:3')
在变回numpy前,需要⽤.cpu()切回CPU模式
print(torch.FloatTensor([1.]).to(device).cpu()) # 输出:tensor([1.])
print(torch.FloatTensor([1.]).to(device).cpu().numpy()) # 输出:[1.]
保存和读取模式
保存
# 保存
# 法⼀,保存整个神经⽹络
torch.save(net, 'net.pkl')
# 法⼆,保存神经⽹络的参数
torch.save(net.state_dict(), 'net_para.pkl')
# 以元祖形式保存,可以保存更多的东西
torch.save({'epoch': i, 'model': model, 'train_loss': train_loss,
'valid_loss': valid_loss}, model_filename + '.model')
提取
# 提取
# 存储⽅法⼀对应的读取,整个神经⽹络
net2 = torch.load('net.pkl')
prediction = net2(x)
# 存储⽅法⼆对应的读取,神经⽹络的参数,需要先搭建神经⽹络,然后把参数放进去 # 这⾥是⼀种快速搭建法
net3 = Sequential(
)
net3.load_state_dict(torch.load('net_para.pkl'))
prediction = net3(x)
# 元祖对应读取
best_model = torch.load(model_filename + '.model').get('model')
所有代码
# 初始化数据
x = torch.unsqueeze(torch.linspace(-1, 1, 100), dim=1) # x data (tensor), shape=(100, 1)
# 注意这⾥x不需要requires_grad=True,如果设置为True,就会放到计算图中,⼀次backward后就会销毁 # 第⼆次循环的backward就会报错
y = x.pow(2) + 0.2*torch.rand(x.size()) # noisy y data (tensor), shape=(100, 1)
# 同样,这⾥y也不需要requires_grad=True
# 批数据训练
BATCH_SIZE = 10
torch_dataset = Data.TensorDataset(x,y) # 这⼀步是把x,y融合在⼀起,
loader = Data.DataLoader(
dataset = torch_dataset,
batch_size = BATCH_SIZE,
shuffle = True, # 是否打乱数据
)
# 搭建神经⽹络
class Module):
def __init__(self, n_features, n_hidden, n_output):
super(Net, self).__init__()
self.hidden = Linear(n_features, n_hidden)
self.predict = Linear(n_hidden, n_output)
def forward(self, x):
self.x = x
self.x = F.relu(self.hidden(self.x))
self.x = self.predict(self.x)
return self.x
# 实例化
net = Net(1,10,1)
# 训练模式
# 优化⽅法和损失函数
loss_func = MSELoss()
opt = torch.optim.Adam(net.parameters(), lr = 0.2)
# 迭代训练
for epoch in range(10):
total_train_loss = 0
for step, (batch_x, batch_y) in enumerate(loader):
pred = net(batch_x)
loss = loss_func(pred, batch_y)
total_train_loss += loss.item()
<_grad()
loss.backward()
opt.step()
print('epoch:', epoch, 'total_train_loss:', total_train_loss)
快速搭建模型与添加模型结构
快速搭建模型
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论