
回归(Linear Regression)是一种基本的统计学习方法,它用于建立两个或多个变量之间的关系。
回归问题与分类问题的区别:
线性回归的目标是找到一条最佳拟合直线,以最小化预测值与实际值之间的差距(误差)。
线性回归在机器学习和数据分析中被广泛使用,它可以用于预测、分类和特征选择等任务。它的应用领域包括金融、经济学、社会科学、医学和工程学等领域。
训练的过程中要避免过拟合现象,可采用一些方法如早停法、正则化等来缓解。
本例定义一个 y=5∗x+2y=5*x+2y=5∗x+2 的线性函数,并适当添加噪声点:
np.random.seed(0)
x_train = np.random.rand(100, 1)y_train = 5 * x_train + 2 + 0.2 * np.random.randn(100, 1)
x_test = np.random.rand(20, 1)
y_test = 5 * x_test + 2 + 0.2 * np.random.randn(20, 1)
x_train_tensor = torch.from_numpy(x_train).float()
y_train_tensor = torch.from_numpy(y_train).float()
x_test_tensor = torch.from_numpy(x_test).float()
y_test_tensor = torch.from_numpy(y_test).float()
为了实现线性回归,我们定义只有一个层的神经网络LinearRegression,在类中定义了一个全连接层linear,这个层的输入和输出都是1维的。
在前向传播方法中,输入x被传入全连接层中进行计算,得到模型的输出out,然后将其返回。
模型的输出out就是输入x的线性变换结果,具体的计算公式为 y=Wx+by = Wx + by=Wx+b,其中WWW是全连接层的权重,bbb是偏置,由于输入和输出都是1维的,因此WWW也是一个1维的向量,bbb是一个标量。
# 定义模型
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
线性回归使用均方误差损失函数。
均方误差损失函数,又称为平方损失函数,是一种用于回归问题的损失函数,计算预测值与真实值之间差异的平方和。在训练过程中,通过不断调整模型参数,最小化损失函数,使得模型能够更好地拟合训练数据。
均方误差损失函数容易受到噪声的影响,不适用于离群点数据。
criterion = nn.MSELoss()
这里使用了 torch.optim.SGD优化器,即随机梯度下降优化器(Stochastic Gradient Descent Optimizer),其通过对模型参数的梯度进行迭代更新,来最小化损失函数。
SGD是深度学习中最常用的优化器之一,也是最基础的优化器之一。
lr 表示学习率,它控制了优化器每次更新参数的步长大小。
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
这里重点是反向传播。
通过计算损失函数对模型参数的梯度,可以确定当前参数下损失函数变化最快的方向,然后将参数朝着这个方向更新,以期望能够使损失函数的值减小。
计算反向传播的一般步骤是:
在每次计算梯度时,要注意梯度的值会累加到模型参数的梯度值中,因此需要在每个batch或每个epoch开始之前将模型参数的梯度值清零。如果不清零,梯度值会一直累加并影响到后续梯度的计算,导致训练出现问题。
# 训练模型
num_epochs = 1000
for epoch in range(num_epochs):# 前向传播y_pred = model(x_train_tensor)# 计算损失loss = criterion(y_pred, y_train_tensor)# 反向传播和优化# 清除所有模型参数的梯度值optimizer.zero_grad()# 计算损失函数对模型参数的梯度loss.backward()# 根据计算出的梯度更新模型参数optimizer.step()# 每隔50个epoch输出一次信息if (epoch + 1) % 50 == 0:print('Epoch[{}/{}], loss: {:.6f}'.format(epoch + 1, num_epochs, loss.item()))
查看损失:
在PyTorch中,损失函数计算的结果一般会返回一个tensor,这个tensor里面存储的是所有样本的损失值,如果要在训练过程中及时查看损失函数的值,需要将这个tensor转换成Python标量(即一个float数值),通过调用item()方法实现。这样得到的就是单个数值,便于进行打印输出、可视化等操作。
# 测试模型
model.eval()
with torch.no_grad():y_pred_train = model(x_train_tensor)y_pred_test = model(x_test_tensor)
train_loss = criterion(y_pred_train, y_train_tensor).item()
test_loss = criterion(y_pred_test, y_test_tensor).item()
print(f'Train loss: {train_loss:.6f}, Test loss: {test_loss:.6f}')
# 预测结果
x_new_tensor = torch.Tensor([[0.2], [0.4], [0.6]])
y_new_tensor = model(x_new_tensor).detach().numpy()
print(f'Prediction for x_new_tensor: {y_new_tensor}')
可视化时,把预测结果转换成 numpy 数组,并且使用 detach() 方法将其与计算图分离,即使其不参与反向传播;最后使用matplotlib绘制函数。
# 可视化结果
model.eval()
y_pred = model(x_train_tensor).detach().numpy()
plt.plot(x_train_tensor.numpy(), y_train_tensor.numpy(), 'ro', label='Original data')
plt.plot(x_train_tensor.numpy(), y_pred, label='Fitted line')
plt.legend()
plt.show()
import torch
import torch.nn as nn
import numpy as np
import matplotlib.pyplot as plt# 生成随机数据
np.random.seed(0)
x_train = np.random.rand(100, 1)
y_train = 5 * x_train + 2 + 0.2 * np.random.randn(100, 1)
x_test = np.random.rand(20, 1)
y_test = 5 * x_test + 2 + 0.2 * np.random.randn(20, 1)# 转换为张量
x_train_tensor = torch.from_numpy(x_train).float()
y_train_tensor = torch.from_numpy(y_train).float()
x_test_tensor = torch.from_numpy(x_test).float()
y_test_tensor = torch.from_numpy(y_test).float()# 定义模型
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 outmodel = LinearRegression()# 定义损失函数和优化器
criterion = nn.MSELoss()
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)# 训练模型
num_epochs = 1000
for epoch in range(num_epochs):# 前向传播y_pred = model(x_train_tensor)# 计算损失loss = criterion(y_pred, y_train_tensor)# 反向传播和优化optimizer.zero_grad()loss.backward()optimizer.step()# 每隔50个epoch输出一次信息if (epoch + 1) % 50 == 0:print('Epoch[{}/{}], loss: {:.6f}'.format(epoch + 1, num_epochs, loss.item()))# 测试模型
model.eval()
with torch.no_grad():y_pred_train = model(x_train_tensor)y_pred_test = model(x_test_tensor)
train_loss = criterion(y_pred_train, y_train_tensor).item()
test_loss = criterion(y_pred_test, y_test_tensor).item()
print(f'Train loss: {train_loss:.6f}, Test loss: {test_loss:.6f}')# 预测结果
x_new_tensor = torch.Tensor([[0.2], [0.4], [0.6]])
y_new_tensor = model(x_new_tensor).detach().numpy()
print(f'Prediction for x_new_tensor: {y_new_tensor}')# 可视化结果
model.eval()
y_pred = model(x_train_tensor).detach().numpy()
plt.plot(x_train_tensor.numpy(), y_train_tensor.numpy(), 'ro', label='Original data')
plt.plot(x_train_tensor.numpy(), y_pred, label='Fitted line')
plt.legend()
plt.show()
可视化结果:

上一篇:网络编程UDP TCP