如何使用pytorch从0开始搭建一个简单的线性类神经网络
这里的主要内容包括使用pytorch去生成预训练数据,设置产生的batch_size的数据,搭建和训练类神经网络
#从零开始搭建一个简单的线性回归的神经网络
import matplotlib.pyplot as plt
import random
import torch
# x先构造一个人造数据集
def sysnthetic_data(w,b,num_examples):
X=torch.normal(0,1,(num_examples,len(w)))#先生成一个包含num_examples个样本的随机特征矩阵,每个样本是均值为0,方差为1的随机数,并且每个样本和w相同的长度
Y=torch.matmul(X,w)+b#线性函数的运算
Y+=torch.normal(0,0.01,Y.shape)#加入一个随机噪音,随机噪音中的均值为0,方差为0.01.形状和y是一样的
return X,Y.reshape((-1,1))#返回x与y,并且将y做成一个列向量返回
true_w=torch.tensor([2,-3,4])
true_w = true_w.float()
true_b=4.2#定义真实的w和b
features,labels=sysnthetic_data(true_w,true_b,1000)#将w和b传给生成函数产生特征和标注
#以上是用于产生一个真实的模拟数据集,特征就是原始数据,标注时我们期望产生的结果
print('features:', features[0], '\nlabels:', labels[0])
plt.scatter(features[:, 0].numpy(), labels)#将labels与features用图象的方式表现出来
plt.savefig('xianxin.jpg')
print(features.shape)#features是一个1000X3的二维张量
print(labels.shape)#labels是一个1000X1的列向量
def data_iter(batch_size,features,labels):
num_examples = len(features)
indices = list(range(num_examples))#创建一个包含样本索引的列表
random.shuffle(indices)#将样本索引列表打乱顺序,以随机顺序遍历数据
for i in range(0,num_examples,batch_size):#以batch_size的跨度执行循环
batch_indicates=torch.tensor(indices[i:min(i+batch_size,num_examples)])#每次产生batch_size大小的张量,最后一个可能已经到了num_examples,但是大小没到batch_siz
yield features[batch_indicates],labels[batch_indicates]#使用yield,这相当于一个生成器,每次调用data_iter,都会生成一个包含特征和标签的批次
batch_size=10
for X,y in data_iter(batch_size,features,labels):
print('X',X,'\ny',y)
#以上是将预训练数据准备好了——--------------------------------------------
w=torch.normal(0,0.01,size=(3,1),requires_grad=True)
b=torch.zeros(1,requires_grad=True)
#上面两步是初始化模型参数,其中w是一个均值为0,方差为0.01的向量,向量的形状和预训练中的形状是一样,b的初始值是0,设置requires_grad为true代表是要求更新梯度的
def linearg(X,w,b):#定义模型
return torch.matmul(X,w)+b
def square_loss(y_hat,y):#定义损失函数
return (y_hat-y.reshape(y_hat.shape))**2/2#用的是平方损失
def sgd(params,lr,batch_size):#定义随机梯度下降优化算法
with torch.no_grad():#这是一个上下文管理器,它告诉 PyTorch 在这个上下文中不要追踪梯度。这是因为在优化步骤中,我们只对参数进行更新,而不需要计算更新的梯度
for param in params:#params 是一个包含模型参数的列表,每个参数是一个张量
param-=lr*param.grad / batch_size#对每个参数执行梯度下降更新,这里除以batch_size是因为我们在计算损失函数的时候应该是要求均值的
param.grad.zero_()#在更新参数后,将参数的梯度清零。这是因为 PyTorch 默认会累积梯度,所以在每次更新后需要清零。
#搭建好模型与优化算法之后,接下来进行模型的训练
lr = 0.1
e=3#将整个数据扫三遍
net=linearg
loss=square_loss
for i in range(e):
for X,y in data_iter(batch_size,features,labels):
l=loss(net(X,w,b),y)#对每一个批次都计算l
l.sum().backward()#将每一个梯度的loss相加然后求梯度
sgd([w,b],lr,batch_size)#使用求出的梯度去更新参数
with torch.no_grad():
loss2=loss(net(features, w, b),labels)
print(loss2.mean().numpy())
运行结果如下所示:
F:\Python\venv\Scripts\python.exe F:\Python\helloworld.py
features: tensor([ 0.8305, -1.5939, -0.4009])
labels: tensor([9.0419])
torch.Size([1000, 3])
torch.Size([1000, 1])
X tensor([[ 0.6411, -1.1396, -0.3526],
[ 0.4752, 0.2158, -0.6305],
[-0.6407, -0.7436, -0.7071],
[-1.0023, 0.2902, -0.1413],
[-0.0624, 0.6895, 0.8490],
[ 0.7566, -0.1526, -2.1063],
[ 1.9979, 0.0630, -0.0187],
[-0.0772, 0.7002, 0.6006],
[ 0.5424, -1.1031, 2.2793],
[-0.5211, 0.3012, -0.3653]])
y tensor([[ 7.4989],
[ 1.9765],
[ 2.3350],
[ 0.7712],
[ 5.4146],
[-2.2430],
[ 7.9225],
[ 4.3264],
[17.7163],
[ 0.8020]])
4.7627665e-05
4.790091e-05
4.829032e-05
进程已结束,退出代码为 0
详细的内容可以看如下链接:
https://zh-v2.d2l.ai/chapter_linear-networks/linear-regression-scratch.html
出自李沐老师的《动手学深度学习》