一个非常非常简单的net
def synthetic_data(w,b,num_example):
#用来生成一些噪音的函数
x = torch.normal(0,1,(num_example,len(w)))
#在这里,我们实现了一个均值为0,方差为1的,样本个数为num_example,样本维数为len(w)的序列
y = torch.matmul(x,w) + b
#在这里,我们把x 与 w进行相乘 例子里是 1000*2的矩阵与 2*1的矩阵相乘
y += torch.normal(0,0.01,y.shape)# 在这里我们加上均值为0,方差为0.1的白噪声
return x , y.reshape((-1,1))
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):#在这里,循环是按照0-batchsize为Stride跳跃的
batch_indices = torch.tensor(indices[i:min(i+batch_size,num_examples)])
yield features[batch_indices] , labels[batch_indices]#相当于一次我随机选取batch_size的序列和laebl
def linreg(x,w,b):
return torch.matmul(x,w) + b
#这就是一个非常非常简单的线性层
def squared_loss(y_hat,y):
return (y_hat - y.reshape(y_hat.shape)) ** 2 / 2
#这里定义了我们的损失函数
def sgd(params, lr, batch_size):
with torch.no_grad():
for param in params:
param -= lr * param.grad / batch_size
param.grad.zero_()
# 一个简单的随机梯度下降算法送给大家
#main函数
lr = 0.03 #在这里定义了学习率
num_epochs = 3 #在这里定义了循环的次数,定义训练巡回
net = linreg #在这里我们定义了我们的网络层,但是我们的网络就是一个很简单的线性映射
loss = squared_loss #在这里定义了我们的损失函数
batch_size = 10 #在这里定义了我们的批量的大小
true_w = torch.tensor([2, -3.4]) #初始化我们的w
true_b = 4.2 #初始化我们的bias
features, labels = synthetic_data(true_w, true_b, 1000) #初始化一些数据
w = torch.normal(0, 0.01, size=(2,1), requires_grad=True) #这是我们想要训练的 w
b = torch.zeros(1, requires_grad=True) #这里是我们想要训练的bias
for epoch in range(num_epochs):#在这里进行了三个轮回
for X, y in data_iter(batch_size, features, labels): #x表示特征,y表示label
l = loss(net(X, w, b), y) # `X`和`y`的小批量损失,在这里计算了损失
# 因为`l`形状是(`batch_size`, 1),而不是一个标量。`l`中的所有元素被加到一起,
# 并以此计算关于[`w`, `b`]的梯度
l.sum().backward() #backwoard()就是计算梯度的api
sgd([w, b], lr, batch_size) # 使用参数的梯度更新参数
with torch.no_grad():
train_l = loss(net(features, w, b), labels)
print(f'epoch {epoch + 1}, loss {float(train_l.mean()):f}')
如果使用了一些api事情又会变得如何呢
在此之前,我需要介绍一下
requires_grad这个参数
在tensor中,每一个tensor都可以记录自己的梯度,只要requires_grad=true
在后面对应的算术表达式中,使用backward()这个函数就可以了。就会对对应的tensor中的每一个
参数,计算对应与这个表达算式的梯度。
并且我还需要介绍一下
-
torch.utils.data.TensorDataset
这其实是一个包装类,把 features 和 label包装秤TensorDataset -
torch.utils.data.DataLoader(data,batch_size,shuffle)
- data一定要是TensorDataset类型的,这是pytorch指定的
- batch_size,指我们一次能从这个DataLoader中抽取多少个数据
- shuffle:如果我们在训练的时候,用训练集的数据就必须是打乱的
-
net = torch.nn.Sequential() 这个相当于是一个容器,装载了我们的各个层
-
nn.Linear() 这个函数就是一个简单的线性层
-
net[0].weight.data.normal_(0,0.01)
net[0].bias.data.fill_(0),从这里我们看出其实每一个层都有一个weight参数和一个bias参数,它代表了这个网络层的权重和偏移量,这个也是我们需要去训练的地方。 -
nn.MSELoss() 常用的误差函数在nn中也是有被定义的
-
torch.optim.SGD(net.parameters().lr=0.03)常用的优化函数,这个就是随机梯度下降法,传入参数和学习步长
import numpy as np
import torch
from torch.utils import data
true_w = torch.tensor([2,-3.4])
true_b = 4.2
feature,labels = synthetic_data(true_w,true_b,1000)
def load_array(data_arrays,batch_size,is_train=True):
#构造一个pytorch的数据迭代器
dataset = data.TensorDataset(*data_arrays)
return data.DataLoader(dataset,batch_size,shuffle=is_train)
from torch import nn
net = nn.Sequential(nn.Linear(2,1))
net[0].weight.data.normal_(0,0.01)
net[0].bias.data.fill_(0)
loss = nn.MSELoss() #常用的误差
trainer = torch.optim.SGD(net.parameters(),lr=0.03)
# main
num_epochs = 3
for epoch in range(num_epochs):
for x,y in data_iter:
l = loss(net(X),y)
trainer.zero_grad()
l.backward()#计算出 梯度后,用step()来更新参数
trainer.setp()