要实现这样一个简单的线性表示代码的书写,目标是通过随机生成的样本x和w_0和b_0,通过深度学习,尽可能得出正确的预设w和b。
代码如下:
(1)import torch //导入PyTorch库(深度学习框架)
(2)import matplotlib.pyplot as plt //导入可视化画图功能库
(3)import random //导入可使用随机操作的库,后面用于随机生成矩阵x
(4)def create_data(w,b,data_num):
// 定义了一个随机生成tensor的函数,其中w是一个4*1的矩阵,用来表示影响参数;b是一个误差参数,data_num是数据的数量
x=torch.normal(0,1,(data_num,len(w))
// torch.noraml()是随机生成tensor的库函数,参数0表示平均数,参数1表示标准差,(data_num,len(w))表示生成的tensor x的形状,因为后续计算得预测的y是矩阵x和矩阵w相乘,根据矩阵乘法的规则,x的长为data_num,宽为矩阵w的长度。
y=torch.matmul(x,w)+b
//torch.matmul()是矩阵相乘的函数,实现矩阵x和w相乘,最后加上误差b得到预测y
noise = torch.normal(0 , 0.01 ,y.shape)
// 考虑到真实情况有噪声干扰,所以随机生成一个平均值为0,标准差为0.01,形状和y相同的noise(因为要和y相加,所以形状和y相同)
y += noise
// 加上噪声
return x,y
//返回随机生成的x和对应的y
(5)num = 500
//设置随机生成的数据数量为500(即x是一个500*4的tensor)
(6)true_w = torch.tensor([8.1,2,2,4])
//设置真正正确的w,以便后续和学习结果对比(注意因为要进行深度学习,所以是tensor而不是简单矩阵)
(7)true_b =torch.tensor( 1.1)
//设置真正正确的b
(8)X,Y = create_data(true_w, true_b,num)
//调用之前定义的随机生成函数,生成x,并传入正确的w和b,根据随机生成的X和正确的w和b生成对应的y
(9)def data_provider(data, label, batchsize):
//每次访问这个函数就提供一批数据,data为x,label为y,batchsize是步长,也就是每次提供的长度
length = len(label)
//取得y的长度
indices = list(range(length))
//定义一个长度为0-500以内的列表
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
//按照步长长度,从之前随机生成的x(500*4)中随机选出长度为batchsize的数据x。最后一句yield是有存档点的return
(10)batchsize = 16
(11) def fun(x,w,b):
pred_y = torch.matmul(x,w)+b
return pred_y
//定义生成预测y值的函数并返回
(12)def maeLoss(pred_y,y):
return torch.sum(abs(pre_y-y))/len(y)
//定义loss值的计算公式,用预测值y和按照正确的w,b算出来的y作差并取绝对值再求平均值
(13)def sgd(paras, lr):
with torch.no_grad():
for para in paras:
para -= para.grad*lr
para.grad.zero_()
//定义了一个简单的梯度下降函数并更新预测的参数。lr为学习率。梯度下降更新参数的方法为,参数减去参数的梯度*学习率。最后每下降一次都将每一步使用过的梯度清零。
注:关于此函数第二行和最后一行的解释如下:
(14)lr = 0.03 // 设置学习率
(15) w_0 = torch.normal(0 , 0.01 , true_w.shape,requires_gred = True)
b_0 = torch.tensor(0.01 , requires_gred = True)
//随机生成参数w_0和b_0,并设置这两个参数需要计算梯度
(16)epochs = 50 //设置训练的轮数
(17)for epoch in epochs:
data_loss = 0
for batch_x,batch_y in data_provider(X,Y,batchsize):
pred_y = fun(batch_x,w_0,b_0)
//按照每次取出来的x,根据随机生成的w_0和b-0计算预测y的值
loss = maeLoss(pred_y , batch_y) //计算loss值
loss.backword() //梯度下降函数,自动完成对参数求偏导得梯度
sgd([w_0,b_0], lr) //更新参数
data_loss += loss //记录每一轮的loss值
(18)print("epoch %03d: loss: %.6f"%(epoch,data_loss)//打印每一轮的轮数和对应的loss值
(19)print("真实的函数值是",true_w, true_b)
print("训练得到的参数是",w_0,b_0)
(20) 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].detach().numpy() , Y.detach().numpy() ,1)
plt.show()
//可视化,注意张量网上不能直接调用可视化函数,需要拆卸下来;而且散点图是线性的,你只能每次取x的某一列来画图