深度学习之线性回归
python代码如下
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import numpy as np # 数据点 x = np.array([1, 2, 3, 4, 5]) # 输入向量x y = np.array([2, 4, 6, 8, 10]) # 目标输出向量y # 初始化权重和偏置 w = 0.0 # 权重初始值 b = 0.0 # 偏置初始值 # 设置学习率和迭代次数 learning_rate = 0.1 # 学习率 num_iterations = 1000 # 迭代次数 for i in range(num_iterations): # 前向传播:计算预测输出y_pred y_pred = w * x + b # 计算损失:均方误差 loss = np.mean((y - y_pred) ** 2) # 输出每100次迭代的损失值 if i % 100 == 0: print(f"迭代 {i},损失:{loss:.4f}") # 反向传播与梯度更新:更新权重w和偏置b dw = np.sum((y_pred - y) * x) / len(x) db = np.mean(y_pred - y) w -= learning_rate * dw b -= learning_rate * db print("\n优化后的权重和偏置:") print(f"w = {w}") print(f"b = {b}") # 使用训练好的参数预测新数据 x_new = 6 # 新数据点 y_new_pred = w * x_new + b # 计算预测值 print(f"\n对x = 6的预测值:{y_new_pred}")
运行结果
将上述线性回归的代码改写为使用PyTorch框架,我们需要定义张量(Tensor)来存储数据,使用PyTorch的自动微分(autograd)来计算梯度,并利用优化器(Optimizer)来更新权重和偏置。下面是一个简单的转换示例:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import torch import torch.optim as optim # 数据点 x = torch.tensor([1, 2, 3, 4, 5], dtype=torch.float32) # 输入向量x y = torch.tensor([2, 4, 6, 8, 10], dtype=torch.float32) # 目标输出向量y # 初始化权重和偏置为可学习参数(requires_grad=True使它们成为优化的目标) w = torch.tensor(0.0, requires_grad=True) b = torch.tensor(0.0, requires_grad=True) # 定义优化器,这里使用简单梯度下降SGD,学习率为0.1 optimizer = optim.SGD([w, b], lr=0.1) num_iterations = 1000 # 迭代次数 for i in range(num_iterations): # 前向传播:计算预测输出y_pred y_pred = w * x + b # 计算损失:均方误差 loss = torch.mean((y - y_pred)**2) # 梯度清零,这在每次反向传播之前都是必要的 optimizer.zero_grad() # 反向传播:自动计算损失关于w和b的梯度 loss.backward() # 更新权重和偏置 optimizer.step() # 输出每100次迭代的损失值 if i % 100 == 0: print(f"迭代 {i},损失:{loss.item():.4f}") # 优化后的权重和偏置 print("\n优化后的权重和偏置:") print(f"w = {w.item()}") print(f"b = {b.item()}") # 使用训练好的参数预测新数据 x_new = torch.tensor(6, dtype=torch.float32) # 新数据点 y_new_pred = w * x_new + b # 计算预测值 print(f"\n对x = 6的预测值:{y_new_pred.item()}")
运行结果发生了梯度爆炸
原因是学习率过大,把学习率降低为0.01即 optimizer = optim.SGD([w, b], lr=0.01)
运行结果
这两个代码都实现了线性回归运算,从pytorch深度学习代码中可以明显看到一个优势:自动微分。PyTorch内置了自动微分功能,能够自动计算梯度,极大简化了梯度计算和反向传播过程,使得开发者可以专注于模型的设计而非数学细节。
为了防止梯度爆炸,学习率还是0.1,可以换一个优化器,这里改为Adam (Adaptive Moment Estimation),目前非常流行的自适应学习率方法,结合了动量和RMSprop的优点,适用于多种任务。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
import torch import torch.optim as optim # 数据点 x = torch.tensor([1, 2, 3, 4, 5], dtype=torch.float32) # 输入向量x y = torch.tensor([2, 4, 6, 8, 10], dtype=torch.float32) # 目标输出向量y # 初始化权重和偏置为可学习参数(requires_grad=True使它们成为优化的目标) w = torch.tensor(0.0, requires_grad=True) b = torch.tensor(0.0, requires_grad=True) # 定义优化器,这里改为自适应学习率,学习率为0.1 optimizer = optim.Adam([w, b], lr=0.1) num_iterations = 5000 # 迭代次数 for i in range(num_iterations): # 前向传播:计算预测输出y_pred y_pred = w * x + b # 计算损失:均方误差 loss = torch.mean((y - y_pred)**2) # 梯度清零,这在每次反向传播之前都是必要的 optimizer.zero_grad() # 反向传播:自动计算损失关于w和b的梯度 loss.backward() # 更新权重和偏置 optimizer.step() # 输出每100次迭代的损失值 if i % 1000 == 0: print(f"迭代 {i},损失:{loss.item():.4f}") # 优化后的权重和偏置 print("\n优化后的权重和偏置:") print(f"w = {w.item()}") print(f"b = {b.item()}") # 使用训练好的参数预测新数据 x_new = torch.tensor(6, dtype=torch.float32) # 新数据点 y_new_pred = w * x_new + b # 计算预测值 print(f"\n对x = 6的预测值:{y_new_pred.item()}")
运行结果如下