该篇文章是训练Transformer前的pytorch的知识补充。感谢博主莫凡Python的视频课程https://www.youtube.com/watch?v=lAaCeiqE6CE&feature=emb_title,其主页是:莫烦Python
建议直接观看该博主视频教程完成pytorch的知识补充。也可走马观花浏览我的文字记录。
接上篇文章,这是Pytorch知识补充的最后一篇文章。这几部分内容是之后训练Transformer及硬件设计所需要的,涵盖:
import torch
from torch.autograd import Variable
import torch.nn.functional as F
import matplotlib.pyplot as plt
#构建数据集
n_data = torch.ones(100,2)
x0 = torch.normal(2*n_data,0.6)
y0 = torch.zeros(100)
x1 = torch.normal(-2*n_data,0.6)
y1 = torch.ones(100)
x = torch.cat((x0,x1),0).type(torch.FloatTensor)#32bit float
y = torch.cat((y0,y1),).type(torch.LongTensor)#64bit int
x, y = Variable(x), Variable(y)
#第一种方法构建网络
class Net(torch.nn.Module):
def __init__(self,n_feature, n_hidden, n_output):
super(Net,self).__init__()
self.hidden= torch.nn.Linear(n_feature, n_hidden)
self.predict = torch.nn.Linear(n_hidden,n_output)
def forward(self,x):
x=F.relu(self.hidden(x))
x=self.predict(x)
return x
net2 = Net(2,10,2)
#第二种方法构建网络
net1 = torch.nn.Sequential(
torch.nn.Linear(2,10),
torch.nn.ReLU(),
torch.nn.Linear(10,2)
)
上述代码介绍了2种构建网络模型的方法,第一种是上篇文章介绍的Transformer硬件实现第二篇:Pytorch基础知识补充(1)_锤子与人的博客-CSDN博客
第二种方法利用torch.nn.Sequential()来构建。
optimizer=torch.optim.SGD(net1.parameters(),lr=0.02)
loss_func = torch.nn.CrossEntropyLoss()
#训练
for i in range(40):
out = net1(x)
loss = loss_func(out,y)
optimizer.zero_grad()
loss.backward()
optimizer.step()
#保存
torch.save(net1,'net.pkl')#entire net
torch.save(net1.state_dict(),'net_params.pkl') #parameters
#第一种提取方案
def restore_net():
net3 = torch.load('net.pkl')
out = net3(x)
#第二种提取方案
def restore_params():
net4 = torch.nn.Sequential(
torch.nn.Linear(2,10),
torch.nn.ReLU(),
torch.nn.Linear(10,2)
)
net4.load_state_dict(torch.load('net_params.pkl'))
out = net4(x)
第一种保存torch.save()函数将整个模型和参数保存下来。第二种只保存参数。同理也有两种提取方法如上。画图将训练时和保存提取后的结果对比,一致。
import torch
import torch.utils.data as Data
BATCH_SIZE = 8
x = torch.linspace(1, 10, 10)
y = torch.linspace(10, 1, 10)
torch_dataset = Data.TensorDataset(x,y)
loader = Data.DataLoader(
dataset=torch_dataset,
batch_size=BATCH_SIZE,
shuffle=True)
for epoch in range(3):
for step, (batch_x, batch_y) in enumerate(loader):
print('Epoch ', epoch, '| Step: ', step, '| batch x: ', batch_x.numpy(), '|batch y: ', batch_y.numpy())
由于数据量过大,无法将数据一次性全部训练,所以就选取批数据进行训练。方法如上,torch.utils.data.TensorDataset()函数是构建一个数据集,torch.utils.data.DataLoadar()函数构建一个迭代器,batch_size是每次取多少个数据出来。
opt_SGD = torch.optim.SGD(net_SGD.parameters(), lr=LR)
opt_Momentum = torch.optim.SGD(net_Momentum.parameters(), lr=LR, momentum=0.8)
opt_RMSprop = torch.optim.RMSprop(net_RMSprop.parameters(), lr=LR, alpha=0.9)
opt_Adam = torch.optim.Adam(net_Adam.parameters(), lr=LR, betas=(0.9, 0.99))
以上为四中优化器的使用方法,SGD是随机梯度下降,效果最差,torch.optim.SGD(momentum=)参数是momentum优化器,以及Adam优化器训练速度均比SGD好,RMSprop是二者结合,如下图效果更好。
BN目标将分散的数据统一规格。数据分布会对训练产生影响,如果输入差距太大,则输出差距过大,则激活后输出可能会进入激活函数的不敏感部分。Batch指批数据,BN放在激活函数前,将所有数据标准化到激活函数的敏感区。其过程为首先计算数据的平均值,然后计算数据方差,之后用数据减去均值后除方差的根号后,得到处理后的数据。该数据经过一个需训练的缩放系数来抵消一部分前面的计算的负优化。