import torch
import matplotlib.pyplot as plt # 画图的
import random #随机
该代码为所需调用的包
def create_data(w, b, data_num): #生成数据
x = torch.normal(0, 1, (data_num, len(w)))
y = torch.matmul(x, w) + b #matmul表示矩阵相乘
noise = torch.normal(0, 0.01, y.shape) #噪声要加到y上
y += noise
return x, y
生成数据:
参考图:
- 作用:通过默认的w和b生成x和y
- 输入数据:参数向量w和b,data_num为需要生成多少组数据(上面矩阵的长)
- 注解:normal表示正太:前两个数字为期望和方差,后两个数据为要生成矩阵的行和列;noise为增加噪声
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)
该代码为初始化默认参数调用函数创建数据
tensor为张量的意思
plt.scatter(X[:, 3], Y, 1)
plt.show()
该代码作用为画图
第一行作用是定义二位散点图,x轴为X第三列,y轴为Y,点的大小为1
第二行为绘制图像
def data_provider(data, label, batchsize): #每次访问这个函数, 就能提供一批数据
length = len(label)
indices = list(range(length))
#我不能按顺序取 把数据打乱
random.shuffle(indices)
for each in range(0, length, batchsize):
get_indices = indices[each: each+batchsize]
get_data = data[get_indices]
get_label = label[get_indices]
yield get_data,get_label #有存档点的return
batchsize = 16
# for batch_x, batch_y in data_provider(X, Y, batchsize):
# print(batch_x, batch_y)
# break
作用:每次访问这个函数提供一批数据:
输入:data为训练数据,label为标签数据,batchsize为每批数据量
代码简要解析:生成与数据长度相同的下表,随机打乱后分批输出
random.shuffle为随机打乱的函数。
yield为有存档点的return
def fun(x, w, b):
pred_y = torch.matmul(x, w) + b
return pred_y
def maeLoss(pre_y, y):
return torch.sum(abs(pre_y-y))/len(y)
def sgd(paras, lr): #随机梯度下降,更新参数
with torch.no_grad(): #属于这句代码的部分,不计算梯度
for para in paras:
para -= para.grad * lr #不能写成 para = para - para.grad*lr
para.grad.zero_() #使用过的梯度,归0
fun函数:通过训练数据计算预测的y值
maeLoss函数:计算一组数据的loss
sgd函数:对一组数据进行梯度下降
注释:
with torch.no_grad(): #属于这句代码的部分,不计算梯度
据李哥说明:梯度是自动存在参数中的,在参数计算时会梯度也会自动计算。从上述代码中可以看到:参数在乘学习率和减去自身梯度时梯度都会更新,因此要加上以上代码进行避免干扰。
lr:为学习率
lr = 0.03
w_0 = torch.normal(0, 0.01, true_w.shape, requires_grad=True) #这个w需要计算梯度
b_0 = torch.tensor(0.01, requires_grad=True)
print(w_0, b_0)
以真实参数的排列形状定义默认初始参数w_0,b_0,两个参数均要求梯度
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)
loss = maeLoss(pred_y, batch_y)
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)
作用:训练50轮,每训练一轮打印一次loss
注释:loss.backward为loss回传(虽然在这里只有一层没有什么作用)
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)
plt.show()
作用:画图
注释:用numpy处理不了张量,因此先要将数据转化为矩阵