%matplotlib inline
import torch
import numpy as np
import matplotlib.pyplot as plt
首先设置真实权重true_w=[2,-3.4],偏置为4.2,以此来生成线性回归的数据集,当然我们可以自己构造数据集,但为了在简单和方便理解的基础上,我们自己构造了一个线性的数据集,不仅可以帮助大家更好的理解,也可以更加方便的训练,更加方便入门。
true_w=torch.tensor([2,-3.4]) # 真实权重
true_b=4.2 # 真实偏置
num_samples = 1000 # 样本数
再接着书写获取数据集的函数
def datasets(w,b,num_samples):
features = torch.normal(0,1,(num_samples,len(w)))# 创建x值
labels = torch.matmul(features,w) + b # 生成y值
labels += torch.normal(0,0.01,labels.shape) # 加上噪音
labels = labels.unsqueeze(1) # 将一维转换为2维
return features,labels # 返回相应的值
定义本文所需要的数据集
features,labels = datasets(true_w,true_b,num_samples)
features.shape,labels.shape # 打印一下输入和输出的维度
接下来就是读取数据,我们设置小批量读取数据,即并不是以此把所有的数据喂给机器直接进行训练,而是小批次的为机器提供数据。
def data_iter(batch_size,features,labels):
index = np.arange(num_samples) # 设置一个新的索引
np.random.shuffle(index) # 打乱索引
for i in range(0,num_samples,batch_size):
batch_index = torch.LongTensor(index[i:min(i+batch_size,num_samples)])
# yield features.index_select(0,batch_index),labels.index_select(0,batch_index) 注意此处的"0"指的是第0维,pytorch中的dim和numpy中的axes一致
yield features[batch_index],labels[batch_index]
上面给出了两种返回数据的方式,都可以返回数据,尤其需要注意一下labels.index_select(0,batch_size)为第0维的数据,并不是从0开始索引,如果你之前熟悉numpy的话,其实本质上就和axes一个道理。
接下来就是随机初始化模型的参数,采用normal函数来随机初始化权重。
w = torch.normal(0,0.01,(2,1),requires_grad=True)
b = torch.zeros(1,requires_grad=True)
注意一下,需要设置梯度,为了利用pytorch的反向传播。
def LinReg(X,w,b):
return torch.mm(X,w) + b
主要利用了torch.mm函数实现矩阵的相乘,当然也可以采用torch.matmul,都是可以的,但要注意二者的区别。
def loss_fun(y_hat,y):
return (y_hat-y.reshape(y_hat.shape))**2/2
此处采用最小二乘损失
def SGD(params,lr,batch_size):
for param in params:
with torch.no_grad():
param.data -=lr*param.grad/batch_size
param.grad.zero_() # 设置梯度清零,注意此处也可以不进行梯度清零,可以写在训练函数中,其实是一致的
注意一下,后面的梯度清零,可以在此处设置,也可以在训练函数处设置,基本上没有什么差别。
epoches = 3 # 设置训练轮次
batch_size=10 # 设置一个批次训练的样本数
lr=0.01 # 学习率的设置
for epoch in range(epoches):
for X,y in data_iter(batch_size,features,labels):
loss=loss_fun(LinReg(X,w,b),y) # 计算损失
loss.sum().backward() # 反向传播
SGD([w,b],lr,batch_size) # 更新参数
with torch.no_grad():
train_1 = loss_fun(LinReg(X,w,b),y)
print("epoch:%d,loss:%.8f"%(epoch+1,train_1.mean().item()))
这里需要注意的就是loss需要求和转化为标量,如果没有此步骤的话,loss还是一个二维向量,pytorch里面设置的大部分都是标量的求导。
计算的结果如下:
以上就是今天的全部分享了,有问题的话可以在评论区留言哦,看到了就是及时回复大家的,希望哦我们可以一起进步呦。