线性回归初级实现
torch.normal(A, B ,size(C, D), requires_grad=True)
A表示均值,B表示标准差 ,C代表生成的数据行数,D表示列数,requires_grad=True表示对导数开始记录,可以忽略。
import math import torch import os from IPython import display from d2l import torch as d2l import pandas as pd import numpy as np import matplotlib.pyplot as plt from pylab import * import matplotlib.gridspec as gridspec import random #生成数据 def synthetic_data(w, b, num_Lines): '''生成方差0,标准差1,行数num_Lines,列数len(w) ''' x = torch.normal(0, 1, (num_Lines,len(w))) '''生存 y = Xw + b + 噪声''' y = torch.matmul(x, w) + b y += torch.normal(0, 0.01, y.shape) return x, y.reshape((-1,1)) #查看生成的数据 def scan_generateData(): #给定W,B初始化值 true_w = torch.tensor([2,-3.4]) true_b = 4.2 #生成x,y 数据 features, labels = synthetic_data(true_w,true_b,1000) print('features:', features[0], '\nlabel:', labels[0]) # 显示数据 d2l.set_figsize() d2l.plt.scatter(features[:,(1)].detach().numpy(), labels.detach().numpy(),1) plt.show() #小批量遍历数据 def data_iter(batch_size, features, labels): num_examples = len(features) indices = list(range(num_examples)) #这些样本是随机read的,没有特定的顺序 random.shuffle(indices) for i in range(0, num_examples, batch_size): batch_indices = torch.tensor(indices[i:min(i + batch_size,num_examples)]) yield features[batch_indices],labels[batch_indices] # 遍历小批量数据,并print def scan_iterData(): batch_size = 10 # 给定W,B初始化值 true_w = torch.tensor([2,-3.4]) true_b = 4.2 features, labels = synthetic_data(true_w,true_b,1000) #遍历生成的数据,batch size for x , y in data_iter(batch_size,features,labels): print(x,'\n', y) break #define model def linreg(x,w,b): return torch.matmul(x,w) +b #define loss function 平⽅损失函数 def squared_loss(y_hat, y): return (y_hat - y.reshape(y_hat.shape))**2 / 2 #参数:模型参数集合、学习速率、批量⼤小。每⼀步更新的⼤小由学习速率learnRate决定。 def sgd(params, learnRate , batch_size): '''小批量随机梯度下降''' with torch.no_grad(): for param in params: param -= learnRate * param.grad / batch_size #批量⼤小(batch_size)来归⼀化步⻓ param.grad.zero_() if __name__ == '__main__': #均值为0、标准差为0.01的正态分布中采样随机数来初始化权重,并将偏置初始化为0 w = torch.normal(0,0.01, size = (2,1), requires_grad=True) b = torch.zeros(1, requires_grad=True) #目的是构筑一个真值x,y true_w = torch.tensor([2,-3.4]) true_b = 4.2 features, labels = synthetic_data(true_w,true_b,1000) batch_size = 10 learnRate = 0.03 num_epochs = 100 #1000个点,batch_size = 10 net = linreg loss = squared_loss for epoch in range(num_epochs): for x,y in data_iter(batch_size, features, labels): l = loss(net(x,w,b),y) # `X`和`y`的⼩批量损失 # 因为`l`形状是(`batch_size`, 1),⽽不是⼀个标量。`l`中的所有元素被加到⼀起, # 并以此计算关于[`w`, `b`]的梯度 l.sum().backward() # 使⽤参数的梯度更新参数 sgd([w,b],learnRate,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}') print(f'w 的估计误差: {true_w - w.reshape(true_w.shape)}') print(f'b的估计误差: {true_b - b}')
线性回归版本简化
import torch from d2l import torch as d2l from torch.utils import data # nn 是神经⽹络的缩写 from torch import nn # data_arrays: features 和 labels 作为API的参数传递, # 并在实例化数据迭代器对象时指定 batch_size,迭代器的时候一次读取 # is_train 表⽰是否希望数据迭代器对象在每个迭代周期内打乱数据 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) if __name__ == '__main__': #生成数据集 true_w = torch.tensor([3, -5.4]) true_b = 4.2 features, labels = d2l.synthetic_data(true_w, true_b, 1000) #读取数据集 batch_size = 10 data_iter = load_array((features, labels), batch_size) #print(f'data: {next(iter(data_iter))}') #定义⼀个模型变量net,它是⼀个 Sequential 类的实例。Sequential 类为串联在⼀起的多个层定义了⼀个容器。 #全连接层在 Linear 类中定义,⼀个指定输⼊特征形状,即 2,第⼆个指定输出特征形状,输出特征形状为单个标量,因此为 1 net = nn.Sequential(nn.Linear(2, 1)) # 线性回归,net[0]表示第一层:每个权重参数应该从均值为0、标准差为0.01的正态分布中随机采样,偏置参数将初始化为零 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) #训练 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() #梯度求解 trainer.step() l = loss(net(features), labels) print(f'epoch {epoch + 1}, loss {l:f}') w = net[0].weight.data print('w的估计误差:', true_w - w.reshape(true_w.shape)) b = net[0].bias.data print('b的估计误差:', true_b - b)
备注:
TensorDataset:
可用来对tensor进行打包,好比python中的zip功能。它通过每一个tensor的第一个维度进行索引。
因此,该类中的 tensor 第一维度必须相等。
net = nn.Sequential(
nn.Linear(1024, 512), #1024x512
nn.ReLU(inplace=True), #线性整流函数
nn.Linear(512, 256),
nn.ReLU(inplace=True),
nn.Linear(256, 6),
)
net[4].weight.data = torch.zeros(6, 256)
net[4].bias.data = torch.ones(6)
t = torch.randn(32, 1024) # 32x1024
print(net(t).size())