整体:https://blog.csdn.net/m0_37957160/article/details/120455082
1.for i in range(起始值,终点值,步长)
https://blog.csdn.net/xyz78911111/article/details/123326983
2.numpy.array(object, dtype=None),返回数组
https://blog.csdn.net/xyz78911111/article/details/123326983
3.x.reshape(-1,1),转换成矩阵,列
https://blog.csdn.net/qq_43511299/article/details/117259662
4.optimizer.zero_grad把梯度信息设置为0
以SGD为例,是算一个batch计算一次梯度,然后进行一次梯度更新。这里梯度值就是对应偏导数的计算结果。显然,我们进行下一次batch梯度计算的时候,前一个batch的梯度计算结果,没有保留的必要了。所以在下一次梯度更新的时候,先使用optimizer.zero_grad把梯度信息设置为0。
5.保存模型的几种方法
// 1
torch.save(model, 'mymodel.pt')
torch.load("mymodel.pt")
//2
torch.save(model.state_dict(), 'mymodel.pt')
model.load_state_dict(torch.load("mymodel.pt"))
//3
model = Net(), optimizer = optim.Adam(model.parameters(), lr=args.lr)
//创建一个字典,包含模型参数,优化器参数,epoch
state = {‘net’:model.state_dict(), ‘optimizer’:optimizer.state_dict(), ‘epoch’:epoch}
//保存
torch.save(state,"mymodel.pt")
//调用
checkpoint = torch.load("mymodel.pt")
model.load_state_dict(checkpoint[‘net’])
optimizer.load_state_dict(checkpoint[‘optimizer’])
start_epoch = checkpoint[‘epoch’] + 1
注意:在调用模型来预测或者测试时,必须按照原先保存的形式来调用,不然加载会出错。
建议:使用state_dict()模式保存model,torch.save(model.state_dict(),path),这样保存为字典模式,可以直接load。
6.CPU版本训练线性回归模型
import torch
import torch.nn as nn#nn模块就是torch.nn模块下有很多丰富的功能我们都可以去用
#准备(数据)
#构造一组输入数据X和其对应的标签y
import numpy as np
x_values=[i for i in range(11)]
x_train=np.array(x_values,dtype=np.float32)#x是ndarray的格式
x_train=x_train.reshape(-1,1)#把数据转化成矩阵的格式
x_train.shape
y_values=[2*i + 1 for i in x_values]#y=2x+1
y_train=np.array(y_values,dtype=np.float32)
y_train=y_train.reshape(-1,1)
y_train.shape
#准备模型
"""
有了x和y之后,构建线性回归模型,让模型学习一下这个w和b分别是多少就可以了。
无论构造一个多么复杂的类型,我都先把这个类构造出来(然后继承一下nn模块),nn模块下有一个Module模块
(Module模块的意思就是里边很多的东西都给我们实现好了,咱直接继承这个里边的,
相当于下边我只需要去写我这个线性回归模型用哪个层就得了,其他的事统统给他省略掉(人家都已经做好了我直接继承过来就得了))
"""
class LinearRegressionModel(nn.Module):
def __init__(self,input_dim,output_dim):
super(LinearRegressionModel,self).__init__()#由于类的继承导致可能覆盖同名的构造方法,导致只能使用子类的构造,
#而无法调用父类的构造方法。但其实可以使用super方法解决这个问题。
self.linear=nn.Linear(input_dim,output_dim)#这里直接使用全连接层(指定参数表示输入数据的维度、输出数据的维度)
'''
在构造函数里边只需要去写你用到了哪些层,(线性回归无非就是你给我x和y,我训练出w和b,使得wx+b跟y的值越接近越好,
这不就是一个全连接层嘛,nn模块中有很多个层,我们可以直接来做调用)
'''
#写一个前向传播函数
def forward(self,x):
out=self.linear(x)#在线性回归中,走法直接,直接走一个全连接层,把x输入进去,得到输出结果就完事了,对于线性回归就是wx+b
return out
#在自己定义的这个类当中, 我们自己去写一个模型,最基本的情况下我们写两个就足够了,
#第一个:就是构造函数当中,我们去写你用到了哪个层(比如有全连接层、池化层、卷积层等),你用到哪个层了你就在
#构造函数当中全指定出来.
#第二个:然后接下来我写一个前向传播,前向传播的意思就是我们不是用到了这么多个层嘛,那这些层你是怎么去用的,
#需要把这些数据由输入开始经过了哪些层,有输出结果,这条线穿起来,
#构建model
input_dim=1
output_dim=1#输入输出维度分别都是1
model=LinearRegressionModel(input_dim,output_dim)
model#打印model(按照网络从前到后怎么走的,把你刚才设计的流程打印出来)这个当中就是一个全连接层
#训练
"""
1、指定训练的次数;这里按照batch去做,一个batch就是全部数据,所以说一共迭代1000次(1000个epochs)
2、学习率;
3、指定优化器;这里使用SGD,在SGD中要告诉我优化什么东西,把模型当中涉及到的模型参数全部加进去,
一会去优化这些参数就可以了,再告诉我当前的学习率是多少。
4、定一个损失函数;损失函数是看任务去说的,一般分类任务就是交叉熵,回归任务常规条件下就是MSE损失函数
(算一下预测值和真实值之间的均方误差就完事了)
"""
epochs=1000
learning_rate=0.01
optimizer=torch.optim.SGD(model.parameters(),lr=learning_rate)
criterion=nn.MSELoss()
#训练
for epoch in range(epochs):#迭代1000次
epoch+=1
#注意转换成tensor
inputs=torch.from_numpy(x_train)#开始定义的x和y是ndarray格式,不能直接进行训练
labels=torch.from_numpy(y_train)
#梯度要清零每一次迭代(清零相当于在上一次的结果在这一次我都不需要去做了)
optimizer.zero_grad()#不清零的话每一次进行反向传播梯度都累加了
#前向传播
outputs=model(inputs)#刚才构建了一个model,model里边有一个前向传播,model里边我把实际的x传进去,他就是前向传播的结果
#计算损失
loss=criterion(outputs,labels)#现在手里有一个输出结果,还有一个标签,就可以计算损失函数
#反向传播
loss.backward()#计算完损失值再做一个反向传播
#(注意:做完反向传播之后,相当于他是把你的梯度给你求出来了,但是没有给你进行更新,
#各个需要求梯度的参数全部给你求出来了,但是此时没有做更新,更新操作需要自己来指定)
#更新权重参数
optimizer.step()#这个就是进行一次参数的更新,参数更新的时候他会基于你的学习率以及计算出来
#的梯度值自动的帮你完成这样反向传播的一个流程
if epoch % 50 == 0:
print('epoch{},loss{}'.format(epoch,loss.item()))
predicted=model(torch.from_numpy(x_train).requires_grad_()).data.numpy()#模型测试很简单有理数据之后,前向传播走一次就完事了
predicted#.data.numpy()表示把这个结果转化成numpy的格式,打印的就是ndarray的格式(因为后续画图有的地方需要传输ndarray的格式)
#保存模型
torch.save(model.state_dict(),'model.pkl')#保存模型实际上保存的是字典的文件,model.state_dict()就是模型的权重参数,
#把w和b保存下来,叫做model.pkl
#后边还可以动态的保存模型,边训练边测试,保存那些好的模型,不好的就不要
model.load_state_dict(torch.load('model.pkl'))#读取一下当前模型的权重参数,把当前的pkl读进来就行了
7.GPU训练线性回归模型
import torch
import torch.nn as nn
import numpy as np
class LinearRegressionModel(nn.Module):
def __init__(self,imput_dim,output_dim):
super(LinearRegressionModel,self).__init__()
self.linear=nn.Linear(input_dim,output_dim)
def forward(self,x):
out=self.linear(x)
return out
input_dim=1
output_dim=1
model=LinearRegressionModel(input_dim,output_dim)
device=torch.device("cuda:0"if torch.cuda.is_available() else "cpu")
#这里指定设备是cuda,做个判断当前cuda是否配置好了,如果说配置好了用cuda去跑,如果说没配置好咱用cpu去跑
#---------------第一个:把模型构建好传入到cuda当中
model.to(device)#把模型.to放到哪,如果配置好了GPU那就是放到了GPU,如果没有配置好那就是CPU。
criterion=nn.MSELoss()
learning_rate=0.01
optimizer=torch.optim.SGD(model.parameters(),lr=learning_rate)
epochs=1000
for epoch in range(epochs):#迭代1000次
epoch+=1
#-------------第二个:输入.to全部的传入到GPU当中
inputs=torch.from_numpy(x_train).to(device)
labels=torch.from_numpy(y_train).to(device)
optimizer.zero_grad()
outputs=model(inputs)
loss=criterion(outputs,labels)
loss.backward()
optimizer.step()
if epoch % 50 == 0:
print('epoch{},loss{}'.format(epoch,loss.item()))
8.item() 方法
item() 方法是用来将只有一个元素的numpy数组或tensor张量转化为标量的方法
9.矩阵乘法.matmul(M)
10.PATH.mkdir(parents = True,exist_ok = True)
mkdir这个函数是在pathlib.Path.mkdir这里,通过import pathlib导入;
pathlib的mkdir接收两个参数:
parents:如果父目录不存在,是否创建父目录。
exist_ok:只有在目录不存在时创建目录,目录已存在时不会抛出异常。
11.lamdba 匿名函数
比定义一个函数效率更高。
12.map函数
map是python内置函数,会根据提供的函数对指定的序列做映射。map()函数的格式是:
map(function,iterable,...)
(1)参数
function是一个函数名称,通过该函数对后续参数iterable进行处理
iterable是一个可迭代对象,比如:字符串、列表、字典、元组、集合等
(2)返回值
map函数通过将指定的function函数依次作用在给定序列iterable中的每一个元素上,得到一个新的list并返回。注意,map不改变原list,而是返回一个新list。
Python2.x 返回列表
Python3.x 返回生成器
- 什么时候用map函数?
当需要对序列进行某些操作或者处理,将其转换为新的列表时,用map函数是最合适不过了。当然,除了最基本的用法,map函数还有一些特殊的使用技巧,比如:可以进行类型转换(将元组或字符串转换为列表,因为map的返回值是列表),可以提取字典中的key等。