import torch
import matplotlib.pyplot as plt #画图
import random #生成随机数
w--权值
b--附加值
data_num --有多少个参考项
拟设数据:x为方差为0[数都一样],均值为1,行列为data_num *len(w)的矩阵
def create_data(w,b,data_num): #y = b + [w1 w2 w3 w4][x1 x2 x3 x4]
x = torch.normal(0,1,(data_num,len(w))) #0为方差,1为均值,后面为矩阵行列500*4
y = torch.matmul(x,w) + b
#noise为方差为0,均值为1,与y同型的矩阵,用来表误差
noise = torch.normal(0,0.01,y.shape) #与y同型
y += noise
return x,y
用真实值得到X,Y
num = 500
#必须是张量tensor才能运算
true_w = torch.tensor([8.1,2,2,4]) #真实值
true_b = torch.tensor(1.1) #真实值
X,Y = create_data(true_w,true_b,num) #x是500*4,y是500*1
#用来划散点图的,scatter为
plt.scatter(X[:,0],Y,1) #x拟设全部维中的第1列
plt.show()
data就是x,label就是y,batchisize就是loss的平均量,
输出结果为随机的关于x,关于y的一笔数据
#每次访问就提供一笔数据
def data_provider(data,label,batchisize):
length = len(label) #长度
indices = list(range(length)) #转成列表 range表示生成0-500的数
random.shuffle(indices) #打乱列表
for each in range(0,length,batchisize): #从0到length,步长为batchisize,each为变量
get_indices = indices[each:each+batchisize] #取each到each+batchisize列表的下标
get_data = data[get_indices] #取下标中的数据
get_label = label[get_indices]
yield get_data,get_label #有存档点的return
用batch_x和batch_y来遍历由X,Y组成的数据,,得到关于X,Y的随机数据
batchsize = 16 #每步走16
for batch_x,batch_y in data_provider(X,Y,batchsize):
print(batch_x,batch_y)
break
def fun(x,w,b): #做函数
pred_y = torch.matmul(x,w) + b #预测值pred_y
return pred_y
def maeLoss(pred_y,y): #做loss
loss = torch.sum(abs(pred_y - y)) / len(y)
return loss
(梯度相当于导数)
paras--
lr--学习率
def sgd(paras,lr):#梯度下降
with torch.no_grad(): #接下来的计算不算梯度
for para in paras:
para -= para.grad*lr
para.grad.zero_() #把梯度归0
#拟设一个学习率
lr = 0.03
#声明两个随机的w,b来训练
w_0 = torch.normal(0,0.01,true_w.shape,requires_grad=True) #计算梯度
b_0 = torch.tensor(0.01,requires_grad=True)
print(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):
#用fun函数得到的预测值
pred = fun(batch_x,w_0,b_0)
#计算loss
loss = maeLoss(pred,batch_y)
#梯度回传,能将所有梯度传回去
loss.backward()
#w_0,b_0 相当于全部参数进行训练
sgd([w_0,b_0],lr)
data_loss += loss
#03d表三位整数,
print("epoch %03d:loss:%.6f"%(epoch,data_loss))
print("原来的函数值:",true_w,true_b)
print(w_0,b_0)
打印直线
idx = 2
#全部从张量上放下
plt.plot(X[:,idx].detach().numpy(),X[:,idx].detach().numpy()*w_0[idx].detach().numpy()+b_0.detach().numpy(),label="pred")
plt.scatter(X[:,idx],Y,1)
plt.show()