1.基本要素
线性回归输出是一个连续值,因此适用于回归问题。回归问题在实际中很常见,如预测房屋价格、气温、销售额等连续值的问题。
(1)训练数据
设房屋的面积为 x1 ,房龄为 x2,售出价格为 y。我们需要建立基于输入 x1 和 x2来计算输出 y 的表达式,也就是模型(model)。 其中 w 1和 w 2 是权重(weight),b 是偏差(bias),且均为标量。
通常收集一系列真实数据,在这些数据上面寻找模型参数来使得误差最小,这些数据被称为训练集,一栋房屋被称为一个样本,其真实售出价格称为标签(label),用来预测标签的两个因素称为特征(feature)
(2)损失函数
在模型训练中,我们需要衡量价格预测值与真实值之间的误差。通常会选取一个非负数作为误差,且数值越小表示误差越小。一个常用的选择是平方函数。 在模型训练中,我们希望找出一组模型参数,记为 w *1*∗,w2∗,b∗,来使训练样本平均损失最小
(3)优化算法
当模型和损失函数形式较为简单时,上面的误差最小化问题的解可以直接用公式表达出来。这类解叫作解析解。大多数深度学习模型并没有解析解,只能通过优化算法有限次迭代模型参数来尽可能降低损失函数的值。这类解叫作数值解。
在求数值解的优化算法中,小批量随机梯度下降在深度学习中被广泛使用。它的算法很简单:先选取一组模型参数的初始值,如随机选取;接下来对参数进行多次迭代,使每次迭代都可能降低损失函数的值。在每次迭代中,先随机均匀采样一个由固定数目训练数据样本所组成的小批量(mini-batch=,然后求小批量中数据样本的平均损失有关模型参数的导数(梯度),最后用此结果与预先设定的一个正数的乘积作为模型参数在本次迭代的减小量。
(4)模型预测
模型训练完成后,我们将模型参数 w 1,w 2,b 在优化算法停止时的值分别记作 _w_ˆ1,_w_ˆ2,_b_ˆ,这里得到的不一定是最优解,而是最优解的一个近似
2.表示方法
(1)神经网络图
输入层的输入个数为2。输入个数也叫特征数或特征向量维度。由于输入层并不涉及计算,按照惯例,所示的神经网络的层数为1,所以,线性回归是一个单层神经网络。
(2)矢量计算
尽可能采用矢量计算,以提升计算效率 , 矢量化代码通常会带来数量级的加速 。
3.从零开始实现
(1)生成数据集
python
#特征数
num_inputs=2
#训练数据集样本个数
num_examples=1000
#模型权重
true_w=[2,-3.4]
#偏差
true_b=4.2
features=torch.randn(num_examples,num_inputs,dtype=torch.float32)
labels=true_w[0]*features[:,0]+true_w[1]*features[:,1]+true_b
#给名为labels的张量添加一个随机噪声,向labels张量中的每个元素添加一个从均值为0、标准差为0.01的正态分布中随机采样的值。
labels+=torch.tensor(np.random.normal(0,0.01,size=labels.size()),
dtype=torch.float32)
(2)读取数据
训练模型时,需要遍历数据集并不断读取小批量数据样本
python
# 数据迭代器,用于批量读取数据
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
j = torch.LongTensor(indices[i: min(i + batch_size, num_examples)])
#使用关键字返回当前批次的数据
yield features.index_select(0, j), labels.index_select(0, j)
(3)初始化模型参数
python
#初始化模型参数
#权重初始化为均值0,标准差为0.01的正态随机数,偏差则初始化为0
w=torch.tensor(np.random.normal(0,0.01,(num_inputs)),dtype=torch.float32)
b=torch.zeros(1,dtype=torch.float32)
#之后需要对这些参数求梯度来迭代
w.requires_grad_(requires_grad=True)
b.requires_grad_(requires_grad=True)
(4)定义模型
python
def model(X,w,b):
#mm函数做矩阵乘法
return torch.mm(X,w)+b
(5)定义损失函数
python
def squared_loss(y_hat, y):
return (y_hat - y.view(y_hat.size())) ** 2 / 2
(6)定义优化算法
通过不断迭代模型参数来优化损失函数,这里自动求梯度模块计算得来的梯度是一个批量样本的梯度和,将它除以批量大小来得到平均值。
python
def sgd(params, lr, batch_size):
for param in params:
#这里更改param时用的param.data
param.data -= lr * param.grad / batch_size
(7)训练模型
python
#学习率
lr = 0.03
#训练轮数
num_epochs = 3
net = model
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).sum() # l是有关小批量X和y的损失
l.backward() # 小批量的损失对模型参数求梯度
sgd([w, b], lr, batch_size) # 使用小批量随机梯度下降迭代模型参数
# 梯度清零
w.grad.data.zero_()
b.grad.data.zero_()
train_l = loss(net(features, w, b), labels)
print('epoch %d, loss %f' % (epoch + 1, train_l.mean().item()))
4.使用PyTorch实现
(1)生成数据集
python
import random
import torch
import numpy as np
#特征数
num_inputs=2
#训练数据集样本个数
num_examples=1000
#模型权重
true_w=[2,-3.4]
#偏差
true_b=4.2
features=torch.randn(num_examples,num_inputs,dtype=torch.float32)
labels=true_w[0]*features[:,0]+true_w[1]*features[:,1]+true_b
#给名为labels的张量添加一个随机噪声,向labels张量中的每个元素添加一个从均值为0、标准差为0.01的正态分布中随机采样的值。
labels+=torch.tensor(np.random.normal(0,0.01,size=labels.size()),
dtype=torch.float32)
(2)读取数据
利用data包来读取数据
python
import torch.utils.data as Data
batch_size=10
#将训练数据的特征和标签组合
#TensorDataset:将多个张量打包成一个数据集
dataset=Data.TensorDataset(features,labels)
data_iter=Data.DataLoader(dataset, batch_size,shuffle=True)
(3)定义模型
首先,导入torch.nn模块,nn是neural networks(神经网络)的缩写,该模块定义了大量神经网络的层。之前我们已经用过了autograd,而nn就是利用autograd来定义模型。nn的核心数据结构是Module,使用中,最常见的做法是继承nn.Module,撰写自己的网络/层。一个nn.Module实例应该包含一些层以及返回输出的前向传播(forward)方法。
python
class Net(nn.Module):
def __init__(self,n_feature):
super(Net,self).__init__()
self.linear=nn.Linear(n_feature,1)
def forwad(self,x):
y=self.linear(x)
return y
(4)初始化模型参数
在使用net前,我们需要初始化模型参数,PyTorch在init模块中提供了多种参数初始化方法,我们通过init.normal_将权重参数每个元素初始化为随机采样于均值为0、标准差为0.01的正态分布,偏差会初始化为零。
python
init.normal_(net[0].weight,mean=0,std=0.01)
init.constant_(net[0].bias,val=0)
(5)定义损失函数
python
loss=nn.MSELoss()
(6)定义优化算法
python
import torch.optim as optim
optimizer=optim.SGD(net.parameters(),lr=0.03)
(7)训练模型
python
num_epochs = 3
for epoch in range(1, num_epochs + 1):
for X, y in data_iter:
output = net(X)
l = loss(output, y.view(-1, 1))
#梯度清零
optimizer.zero_grad()
l.backward()
optimizer.step()
print('epoch %d, loss: %f' % (epoch, l.item()))