接续上一篇的optimizer的学习。
代码和上一篇文章的一样,如下:
import torch
import numpy as np
import torch.nn as nn
X = torch.tensor([1, 2, 3, 4], dtype=torch.float32)
Y = torch.tensor([2, 4, 6, 8], dtype=torch.float32)
w2 = torch.tensor(0.0, requires_grad=True)
def forward(_x):
return w2* _x
learning_rate = 0.01
n_iter = 100 # 循环次数
loss =nn.MSELoss()
optimizer =torch.optim.SGD([w2],lr=learning_rate)
for epoch in range(n_iter):
y_pred = forward(X)#
l = loss(Y, y_pred)
l.backward() #执行完反向传播后,w2里就已经有w2.grad了
optimizer.step() #optimizer初始化时就接收了w2,现在w2有了grad,就可以执行step进行优化了,优化时会使用w2的梯度grad属性和学习率learning_rate
optimizer.zero_grad() #梯度清零
if epoch % 1 == 0:
print(f'epoch {epoch+1}:w2= {w2:.3f} ,loss = {l:.8f}')
print(f'f(5)={forward(5):.3f}')
可以看到,我们这里引用增加了一个import torch.nn as nn。
这里只是简单的使用了nn.MSELoss(),我们就不用手写这个计算平均值的步骤了。
然后我们定义了一个optimizer,接收了两个参数,一个是权重w2,一个是学习率learning_rate。
这里我们的传递的是一个Tensors数组,而不是w2。
上篇文章已经介绍的w是根据梯度x.grad生成的,所以,按理应该是一个跟x同类型的矩阵,这里[w2]跟x不同型,但这里他只是一个数,这是因为计算时,会自动把这种一个数的矩阵变形为跟x同型的矩阵。
正确的写法应该是下面这样。
import torch
import numpy as np
import torch.nn as nn
X = torch.tensor([1, 2, 3, 4], dtype=torch.float32)
Y = torch.tensor([2, 4, 6, 8], dtype=torch.float32)
w2 = torch.tensor([0.0,0.0,0.0,0.0], requires_grad=True)
def forward(_x):
return w2* _x #如果w2不是1个元素或者4个元素,这里就无法相乘
learning_rate = 0.01
n_iter = 100 # 循环次数
loss =nn.MSELoss()
optimizer =torch.optim.SGD([w2],lr=learning_rate)
for epoch in range(n_iter):
y_pred = forward(X)#
l = loss(Y, y_pred)
l.backward()
optimizer.step()
optimizer.zero_grad()
if epoch % 1 == 0:
print(f'epoch {epoch+1}:w21= {w2[0]:.3f} w22= {w2[1]:.3f} ,loss = {l:.8f}')
回忆一下前面将的青蛙例子,我们重新叙述一下这个计算逻辑,首先我们有个y,这个是我们的目标,然后有个x,这个是我们的输入数据。然后通过w和b这俩参数,结合公式y=wx+b,一次一次的尝试求出w和b,然后通过求出的w和b修正x,然后我们得到了一个新的矩阵——修正x;我们令y_predict=x修正矩阵,就形成了x通过变化得到了预测y,即y_predict。然后我们就可以比较y和y_predict了。
torch.nn 是 PyTorch 的一个核心模块,专门用于构建和训练神经网络。这个模块提供了各种类和函数,使你可以方便地定义神经网络模型、实现前向传播和反向传播、定义损失函数,以及进行参数优化等任务。
torch.nn.Linear的概念是PyTorch 中用于实现线性变换(全连接层)的模块。这里我们先无视他的定义。
先看几个变量的含义。
X.shape:返回的是一个 torch.Size 对象 形状信息分别是 行数(样本数)和列数(特征数),这里特别注意样本和特征这俩词,这是俩干扰我们学习非常狠的名词。
nn.Linear(input_size, output_size):这是实例化Linear,入参是俩数,分别叫做input_size, output_size,这俩参数的含义如下。
input_size:是输入特征的数量,也就是每个输入样本的维度。
output_size:是输出特征的数量,也就是模型希望输出的特征维度。
input_size:表示输入数据 X 的列数。
output_size:表示模型预测输出 y_predict 的列数。
注:这里要把反人类的定义多看几遍,因为,如果你学习人工智能,你会在各种视频和文章中看到别人用反人类定义来描述操作与问题。如果不能理解,就只能等着被恶心吧。
这里,我们可以稍微思考一下,就可以根据input_size和output_size的分别传入推测出一个结论,那就是我们可以输入3 * 3的矩阵x,然后利用torch.nn这个库,输出成4 * 4的矩阵,然后再和4 * 4矩阵y比较。
不过Linear的话,要求输入和输出矩阵的维度必须匹配,所以,这里我们是不用这么做的,不过稍微联想一下即可得出结论,多层神经网络或其他层(如卷积层)肯定可以做这样复杂的映射。
Linear使用代码如下:
import torch
import numpy as np
import torch.nn as nn
X = torch.tensor([[1], [2], [3], [4]], dtype=torch.float32)
Y = torch.tensor([[2], [4], [6], [8]], dtype=torch.float32)
n_samples, n_features = X.shape # x是4行1列矩阵,这里返回4和1
print("n_samples", n_samples, "n_features", n_features)
input_size = n_features
output_size = n_features
model = nn.Linear(input_size, output_size)
learning_rate = 0.01
n_iter = 100 # 循环次数
loss = nn.MSELoss()
[w, b]= model.parameters()
optimizer = torch.optim.SGD([w, b], lr=learning_rate)
for epoch in range(n_iter):
y_pred = model(X) # 这里的 model(X) 调用的是 model 的 forward 方法
l = loss(Y, y_pred)
l.backward()
optimizer.step()
optimizer.zero_grad()
if epoch % 1 == 0:
[w, b] = model.parameters()
print(f'epoch {epoch+1}:w2= {w[0][0].item():.3f} ,loss = {l:.8f}')
如上代码,我们使用model = nn.Linear(input_size, output_size)定义了一个线性模型对象。
然后使用 torch.optim.SGD时,传入了model.parameters()的返回值。
model.parameters()的返回值就是w和b。model.parameters()在被调用后,会在内部创建一个w和一个b。
权重矩阵 w:形状为 [output_size, input_size]。
偏置向量 b:形状为 [output_size]。
然后我们使用model(x)调用这个实例,这里Linear类里应该是实现了__call__方法,所以类的实例可以像函数一样被调用。
这里我们传递了x,有了x它就可以前向传播了,即,model(x)里我们传递了x,同时触发了前向传播。
所以,model(x)的返回值是一个预测的y值。
然后我们使用我们通过nn.MSELoss()定义的[标量函数/损失函数]来进行计算标量。
然后这个标量就可以使用反向传播了。
然后,我们就得到了模型参数w和b的值了。
nn.Module 是 PyTorch 中所有神经网络模块的基类。所有的神经网络层(如线性层、卷积层、LSTM 等)都继承自这个类。
通过继承 nn.Module,可以定义自己的网络层或模型,并利用 PyTorch 的自动微分功能来进行训练。
nn.Linear 是 nn.Module 的子类,是一个特定的神经网络层类,继承自 nn.Module。它实现了一个最简单的线性变换层,也叫全连接层。
通过继承 nn.Module,nn.Linear 能够利用 nn.Module 提供的所有功能,比如注册参数、前向传播、保存和加载模型等。
结构如下:
# nn.Module
# |
# |-- nn.Linear
# |-- nn.Conv2d
# |-- nn.RNN
# |-- (Other Modules)
下面自定义一个类,继承Module实现Linear的代码:
X = torch.tensor([[1], [2], [3], [4]], dtype=torch.float32) # 4行1列矩阵
Y = torch.tensor([[2], [4], [6], [8]], dtype=torch.float32)
n_samples, n_features = X.shape
print("n_samples", n_samples, "n_features", n_features)
input_size = n_features
output_size = n_features
# model = nn.Linear(input_size, output_size)
class LinearRegression(nn.Module):
def __init__(self, input_dim, output_dim):
super(LinearRegression,self).__init__()
# define layers
self.lin = nn.Linear(input_dim, output_dim)
def forward(self, x):return self.lin(x)
model =LinearRegression(input_size, output_size)
learning_rate = 0.01
n_iter = 100 # 循环次数
loss = nn.MSELoss()
[w, b]= model.parameters()
optimizer = torch.optim.SGD([w, b], lr=learning_rate)
for epoch in range(n_iter):
y_pred = model(X)
l = loss(Y, y_pred)
l.backward()
optimizer.step()
optimizer.zero_grad() # 梯度清零
if epoch % 1 == 0:
[w, b] = model.parameters()
print(f'epoch {epoch+1}:w2= {w[0][0].item():.3f} ,loss = {l:.8f}')
传送门:
零基础学习人工智能—Python—Pytorch学习(一)
零基础学习人工智能—Python—Pytorch学习(二)
零基础学习人工智能—Python—Pytorch学习(三)
零基础学习人工智能—Python—Pytorch学习(四)
学习就先到这。
注:此文章为原创,任何形式的转载都请联系作者获得授权并注明出处!
若您觉得这篇文章还不错,请点击下方的【推荐】,非常感谢!