import torch
import matplotlib.pyplot as plt
Python 中用于导入 matplotlib 库并将其 pyplot 模块简称为 plt 的常见语句。matplotlib 是一个功能强大的绘图库,而 pyplot 是其提供的一个基于状态机的接口,用于创建各种类型的可视化图表
y = x * w + b
def create_data(w, b, data_num): #生成数据
x = torch.normal(0, 1, (data_num, len(w))) #长度是数据数量,w多长,x多宽
y = torch.matmul(x, w) + b #matmul表示矩阵相乘
noise = torch.normal(0, 0.01, y.shape) #噪声加到y上 不可能那么准.通过这种方式,对原始数据 y 添加了随机噪声,模拟了数据在实际场景中可能受到的噪声干扰
y += noise
return x, y
num = 500 #生成500个数据
true_w = torch.tensor([8.1, 2, 2, 4]) #torch.tensor() 函数用于从 Python 列表创建一个 PyTorch 张量。在这个例子中,列表 [8.1, 2, 2, 4] 被转换为一个张量。
true_b = torch.tensor(1.1)
X, Y = create_data(true_w, true_b, num)
plt.scatter(X[:, 3], Y, 1) #画散点图 大小为1 标签Y 只取第三列 y:500*1
plt.show()
def data_provider(data, label, batchsize): #每次访问这个函数,就能提供一批数据 500个数据,16个数据取一次loss
length = len(label)
indices = list(range(length)) #indices变为0-500的列表
#我不能按顺序取 把数据打乱,原来indices[0]=0现在indices[0]=随机数
random.shuffle((indices))
for each in range(0, length, batchsize):
get_indices = indices[each: each+batchsize] #0-15 16-31
get_data = data[get_indices]
get_label = label[get_indices]
yield get_data, get_label #有存档点的return each,0,16,32
以上,为取数据
def fun(x, w, b): #定义一个模型
pred_y = torch.matmul(x, w) + b
return pred_y #pred_y 就是模型对输入 x 的预测输出
def maeLoss(pred_y, y): #用于计算平均绝对误差(Mean Absolute Error,MAE)损失
return torch.sum(abs(pred_y-y))/len(y) #得到平均loss
#梯度下降:参数减去参数的梯度乘以学习率
def sgd(paras, lr): #随机梯度下降,更新参数
with torch.no_grad(): #张量网上,所有的计算都会计算梯度.但不是所有梯度都是我们想要的,梯度更新回传时不需要更新梯度,输入这句代码的部分,不计算梯度
for para in paras:
para -= para.grad* lr #不能写成para= para - para.
para.grad.zero_() #在完成一次参数更新后,需要将参数的梯度清零。这是因为在 PyTorch 中,梯度是累加的,如果不清零,在下一次反向传播时,新计算的梯度会与之前的梯度累加,导致错误的更新。
lr = 0.3
w_0 = torch.normal(0, 0.01, true_w.shape, requires_grad=True) #这个w需要计算梯度
b_0 = torch.tensor(0.01, requires_grad=True)
epochs = 50
for epoch in range(epochs):
data_loss = 0
for batch_x, batch_y in data_provider(X, Y, batchsize):
pred_y = fun(batch_x, w_0, b_0) #得出预测的y
loss = maeLoss(pred_y, batch_y) #batch_y是真实的y
loss.backward() #调用 loss.backward() 进行反向传播。这一步会计算损失函数关于模型参数的梯度
sgd([w_0, b_0], lr)
data_loss += loss
print("epoch %03d:loss: %.6f"%(epoch, data_loss))
print("真实的函数值是", true_w, true_b)
print("训练得到的参数值是", w_0, b_0)
idx = 3 #定义变量 idx 为 3,用于后续从数据集中选择特定的列。
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) #detach() 方法将张量从计算图中分离,避免在转换为 numpy 数组时因计算图的存在引发问题,numpy() 方法将 torch.Tensor 转换为 numpy.ndarray,这部分数据作为线图的 x 轴数据。
plt.show()
标签:表示,loss,get,梯度,代码,torch,indices,线性,data
From: https://www.cnblogs.com/jyp02/p/18661716