下面我会给出一份“pytorch实现梯度下降和反向传播图文详细讲解”的攻略,希望可以帮助到您。
1. 概述
梯度下降是深度学习中常用的优化算法之一,用于更新模型参数从而使得损失函数尽可能小。而反向传播是计算梯度的一种常用方法,用于计算神经网络中所有参数的梯度。本攻略将详细介绍如何使用PyTorch实现梯度下降和反向传播。
2. 梯度下降
在PyTorch中,我们可以使用 torch.optim
模块来实现梯度下降。该模块提供了一系列优化算法,如SGD、Adam、RMSprop等。
以SGD为例,我们可以按照以下步骤来实现梯度下降:
- 定义模型:在 PyTorch 中,我们可以通过继承
nn.Module
类来定义自己的模型。
import torch.nn as nn
class MyModel(nn.Module):
def __init__(self):
super(MyModel, self).__init__()
self.linear = nn.Linear(1, 1)
def forward(self, x):
y_pred = self.linear(x)
return y_pred
- 定义损失函数:我们需要定义一个损失函数来衡量预测值和实际值之间的误差。
import torch.nn as nn
criterion = nn.MSELoss()
- 定义优化器:我们需要定义一个优化器来更新模型的参数。
import torch.optim as optim
optimizer = optim.SGD(model.parameters(), lr=0.01)
- 训练模型:最后,我们可以使用以下代码来进行模型的训练。
for epoch in range(100):
# Forward pass
y_pred = model(x_data)
# Compute loss
loss = criterion(y_pred, y_data)
# Zero gradients
optimizer.zero_grad()
# Backward pass
loss.backward()
# Update parameters
optimizer.step()
注意,我们首先要将梯度清零,然后进行反向传播(调用 backward()
),最后根据计算出的梯度更新模型参数(调用 step()
)。
3. 反向传播
反向传播算法是计算神经网络中参数梯度的一种常用方法,其实现包括以下步骤:
- 前向传播:计算所有的中间变量和输出结果。
y_pred = model(x_data)
- 计算损失:利用损失函数计算模型的输出与真实标签的差距。
loss = criterion(y_pred, y_data)
- 清空梯度:PyTorch中每个Tensor都会自动积累梯度,所以每次使用完所有参数后需将梯度清零。
optimizer.zero_grad()
- 计算梯度:调用反向传播算法计算梯度。
loss.backward()
- 优化参数:利用优化器对参数进行更新。
optimizer.step()
至此,我们完成了一次反向传播的过程。
4. 示例说明
下面,以线性回归为例,展示如何使用PyTorch实现梯度下降和反向传播。
4.1. 梯度下降
import torch
import torch.nn as nn
import torch.optim as optim
import matplotlib.pyplot as plt
# Generate data
x = torch.randn(100, 1) * 10
y = x + torch.randn(100, 1)
# Define model
class LinearRegression(nn.Module):
def __init__(self):
super(LinearRegression, self).__init__()
self.linear = nn.Linear(1, 1)
def forward(self, x):
out = self.linear(x)
return out
model = LinearRegression()
# Define loss function and optimizer
criterion = nn.MSELoss()
optimizer = optim.SGD(model.parameters(), lr=0.01)
# Train model
epochs = 100
for epoch in range(epochs):
# Forward pass
y_pred = model(x)
# Compute loss
loss = criterion(y_pred, y)
# Zero gradients
optimizer.zero_grad()
# Backward pass
loss.backward()
# Update parameters
optimizer.step()
# Print loss
if epoch%10==0:
print('Epoch [{}/{}], Loss: {:.4f}'.format(epoch+1, epochs, loss.item()))
# Plot data and model
plt.scatter(x.detach().numpy(), y.detach().numpy())
plt.plot(x.detach().numpy(), y_pred.detach().numpy(), 'r')
plt.show()
4.2. 反向传播
import torch
import torch.nn as nn
import torch.optim as optim
import matplotlib.pyplot as plt
# Generate data
x = torch.randn(100, 1) * 10
y = x + torch.randn(100, 1)
# Define model
class LinearRegression(nn.Module):
def __init__(self):
super(LinearRegression, self).__init__()
self.linear = nn.Linear(1, 1)
def forward(self, x):
out = self.linear(x)
return out
model = LinearRegression()
# Define loss function and optimizer
criterion = nn.MSELoss()
optimizer = optim.SGD(model.parameters(), lr=0.01)
# Train model with backward()
epochs = 100
for epoch in range(epochs):
# Forward pass
y_pred = model(x)
# Compute loss
loss = criterion(y_pred, y)
# Zero gradients
optimizer.zero_grad()
# Backward pass
loss.backward()
# Update parameters
optimizer.step()
# Print loss
if epoch%10==0:
print('Epoch [{}/{}], Loss: {:.4f}'.format(epoch+1, epochs, loss.item()))
# Train model with manual compute gradients
for epoch in range(epochs):
# Forward pass
y_pred = model(x)
# Compute loss
loss = criterion(y_pred, y)
# Zero gradients
model.zero_grad()
# Manual compute gradients
dloss_dy_pred = 2*(y_pred-y)
dy_pred_dw = x
dy_pred_db = 1
dloss_dw = dloss_dy_pred*dy_pred_dw
dloss_db = dloss_dy_pred*dy_pred_db
# Backward pass
model.linear.weight.grad = dloss_dw.mean()
model.linear.bias.grad = dloss_db.mean()
# Update parameters
model.linear.weight.data -= 0.01*model.linear.weight.grad
model.linear.bias.data -= 0.01*model.linear.bias.grad
# Print loss
if epoch%10==0:
print('Epoch [{}/{}], Loss: {:.4f}'.format(epoch+1, epochs, loss.item()))
# Plot data and model
plt.scatter(x.detach().numpy(), y.detach().numpy())
plt.plot(x.detach().numpy(), y_pred.detach().numpy(), 'r')
plt.show()
在上述代码中,我们首先使用 loss.backward()
来计算梯度,然后使用 optimizer.step()
来更新模型参数;接着,我们手工计算梯度,使用梯度下降来更新模型。最后,我们可以通过绘图来展示模型的拟合效果。
以上就是关于PyTorch实现梯度下降和反向传播的详细攻略,希望能对您有所帮助。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:pytorch实现梯度下降和反向传播图文详细讲解 - Python技术站