1. 数据生成
Python复制
def create_data(w, b, data_num): # 生成数据
x = torch.normal(0, 1, (data_num, len(w))) # 生成特征数据
y = torch.matmul(x, w) + b # 计算目标值 y = wx + b
noise = torch.normal(0, 0.01, y.shape) # 添加噪声
y = y + noise
return x, y
-
功能:生成用于线性回归的训练数据。
-
参数:
-
w
:权重向量。 -
b
:偏置项。 -
data_num
:数据点的数量。
-
-
过程:
-
使用
torch.normal(0, 1, (data_num, len(w)))
生成随机特征数据x
,形状为(data_num, len(w))
。 -
计算目标值
y = wx + b
,其中torch.matmul(x, w)
是矩阵乘法。 -
添加噪声
torch.normal(0, 0.01, y.shape)
,使数据更接近真实情况。
-
-
返回值:特征数据
x
和目标值y
。
2. 数据可视化
Python复制
num = 500
true_w = torch.tensor([8.1, 2, 2, 4])
true_b = torch.tensor(1.1)
X, Y = create_data(true_w, true_b, num)
plt.scatter(X[:, 3].numpy(), Y.numpy(), 1)
plt.show()
-
功能:可视化生成的数据。
-
过程:
-
定义真实的权重
true_w
和偏置true_b
。 -
调用
create_data
函数生成数据。 -
使用
plt.scatter
绘制第 4 个特征(X[:, 3]
)与目标值Y
的散点图。
-
3. 数据提供器
Python复制
def data_provider(data, label, batch_size): # 生成数据
length = len(label)
indices = list(range(length))
random.shuffle(indices)
for each in range(0, length, batch_size):
get_indices = indices[each:each + batch_size]
get_data = data[get_indices]
get_label = label[get_indices]
yield get_data, get_label # 有存档点的 return
-
功能:将数据分批提供给训练过程。
-
参数:
-
data
:特征数据。 -
label
:目标值。 -
batch_size
:每批数据的大小。
-
-
过程:
-
获取数据长度
length
。 -
生成索引列表
indices
并打乱顺序。 -
按
batch_size
分批提取数据和标签。
-
-
返回值:生成器,每次返回一批数据和标签。
4. 模型函数
Python复制
def fun(x, w, b):
pred_y = torch.matmul(x, w) + b
return pred_y
-
功能:计算模型的预测值。
-
参数:
-
x
:输入特征。 -
w
:权重向量。 -
b
:偏置项。
-
-
过程:计算预测值
pred_y = wx + b
。
5. 损失函数
Python复制
def maeLoss(y_pred, y):
loss = torch.abs(y_pred - y)
return loss.mean()
-
功能:计算平均绝对误差(MAE)损失。
-
参数:
-
y_pred
:预测值。 -
y
:真实值。
-
-
过程:计算预测值与真实值的绝对差,并取平均值。
6. 随机梯度下降
Python复制
def sgd(paras, lr): # 随机梯度下降
with torch.no_grad(): # 不记录梯度
for param in paras:
param -= lr * param.grad # 更新参数
param.grad.zero_() # 梯度清零
-
功能:实现随机梯度下降算法。
-
参数:
-
paras
:需要更新的参数列表。 -
lr
:学习率。
-
-
过程:
-
使用
torch.no_grad()
禁用梯度计算。 -
遍历参数列表,更新参数值。
-
清零梯度。
-
7. 模型训练
Python复制
lr = 0.01
w_0 = torch.normal(0, 0.01, true_w.shape, requires_grad=True)
b_0 = torch.tensor(0.01, requires_grad=True)
epochs = 50
batch_size = 16
for epoch in range(epochs):
data_loss = 0
for batch_x, batch_y in data_provider(X, Y, batch_size):
pred_y = fun(batch_x, w_0, b_0)
loss = maeLoss(pred_y, batch_y)
loss.backward()
sgd([w_0, b_0], lr)
data_loss += loss
print("epoch:", epoch, "loss:", data_loss)
-
功能:训练线性回归模型。
-
过程:
-
初始化权重
w_0
和偏置b_0
,并设置requires_grad=True
以启用梯度计算。 -
设置学习率
lr
和训练轮数epochs
。 -
遍历每个 epoch:
-
使用
data_provider
提供数据批次。 -
计算预测值
pred_y
。 -
计算损失
loss
。 -
反向传播计算梯度。
-
使用
sgd
更新参数。 -
累加损失值并打印。
-
-
8. 结果输出
Python复制
print("真实的函数值是", true_w, true_b)
print("预测的函数值是", w_0, b_0)
-
功能:输出真实的权重和偏置,以及训练后的预测值。
9. 结果可视化
Python复制
idx = 0
plt.plot(X[:, idx].detach().numpy(), X[:, idx].detach().numpy() * w_0[idx].detach().numpy() + b_0.detach().numpy())
plt.scatter(X[:, idx], Y, 1)
plt.show()
-
功能:绘制训练后的线性拟合线和数据点。
-
问题:代码中存在错误,
w_0
是一维张量,不能使用w_0[idx]
。正确的做法是直接使用w_0
和b_0
。 -
修正代码:
Python复制
idx = 0
plt.plot(X[:, idx].detach().numpy(), fun(X, w_0, b_0).detach().numpy(), label='Linear Fit')
plt.scatter(X[:, idx], Y, 1, label='Data Points')
plt.legend()
plt.show()
-
修正后的功能:
-
使用
fun(X, w_0, b_0)
计算预测值。 -
绘制预测线和数据点。
-
总结
这段代码实现了一个完整的线性回归流程,包括数据生成、模型训练、损失计算和结果可视化。修正后的代码可以正确运行并展示训练后的线性拟合效果。