线性模型
假设自变量x和因变量y的关系是线性的,则y可以表示为x的加权和
目的是求出合适的权重w和偏置b建立模型进行预测
在高维数据集中表示为
其中为y的估计值
使用向量表示wx为:
这里只需将w最后1列加入1 x中加入b 就可以将b合并进去得到:这在矩阵中也可以使用
损失函数
用于量化实际值与预测值之间的差距
常用平方误差函数: |添加系数 使求导后系数为1
为度量模型在整个数据集的质量,提出损失均值:对上方n个样本的求和求均值:
展开对求偏导:
为了最小化损失, 令偏导为0求最小值:
即:
小批量随机梯度下降
其中
线性回归 的简洁实现
获取数据集
假设数据集和真实的权重true_w和偏置true_b,用synthetic_data生成随机特征和对应的标签
#
import numpy as np
import torch
from torch.utils import data
from d2l import torch as d2l
true_w = torch.tensor([2, -3.4])
true_b = 4.2
features, labels = d2l.synthetic_data(true_w, true_b, 1000)
读取数据集
TensorDataset将features和labels组合起来的元组(features[i],label[i]),方便DataLoader()使用
由于样本数量较大, 这里使用DataLoader生成一个迭代器,每次返回批次大小batch_size的样本数量
from torch.utils import data
def load_array(data_arrays, batch_size, is_train=True): #@save
"""构造一个PyTorch数据迭代器"""
dataset = data.TensorDataset(*data_arrays)
return data.DataLoader(dataset, batch_size, shuffle=is_train)
batch_size = 10
data_iter = load_array((features, labels), batch_size)
for X,y in data_iter:
print(X,y)
这里的data_iter是可迭代对象,可以使用iter(data_iter)转化为迭代器,使用next(iter(data_iter))依次获取1-10,11-20,21-30…的值
定义模型
在定义模型前先了解以下层和神经元
层和神经元
层是神经网络的基本构建块,从输入层输入数据,经过中间多个层,最后从输出层输出数据,每个层接受上一层的结果作为输入,输出的结果作为下一层的输入
- 常见层类型
- 全连接层(Fully Connected Layer / Linear Layer):每个输入与每个输出都有连接,通常用矩阵-向量乘法来表示。输入与权重矩阵相乘并加上偏置,最终经过激活函数输出。
- 卷积层(Convolutional Layer):主要用于处理图像数据,通过卷积操作提取特征。
- 池化层(Pooling Layer):用于减少数据的维度,通常跟在卷积层之后,降低计算复杂度并减少过拟合。
- 激活层(Activation Layer):应用非线性函数(如 ReLU、Sigmoid 等)来引入非线性特性,使模型能够学习复杂的模式。
- 归一化层(Normalization Layer):如批归一化(Batch Normalization),有助于提高训练稳定性,加速收敛。
- 循环层(Recurrent Layer):用于处理序列数据,像 LSTM 和 GRU 这样的层能够处理时间序列数据。
每一层由多个神经元组成,每个神经元用于计算,将输入的数据进行加权和后输出
这里定义了一个Sequential,是层的集合,用于将层按顺序排列,自动按顺序执行每个层,
from torch import nn
net = nn.Sequential(nn.Linear(2, 1))#只有一层 输入两个特征,输出一个特征
#拓展
net1 = nn.Sequential(
nn.Linear(2, 3),#全连接层 输入两个特征,输出三个特征
nn.ReLU(), # 激活层,增加神经网络的非线性
nn.Linear(3, 1) #全连接层 输入三个特征,输出1个特征
)
初始化模型参数
这里的net[0]是神经网络的第一层,即nn.Linear(2, 1)
weight是他的权重,data是访问权重的原始数据,normal_是服从均值为0 标准差为0.01 的正态分布初始化weight,避免所有神经元的输出都相同,从而避免梯度消失或梯度爆炸的问题。
bias是偏置, fill_将偏置填充为0,偏置的作用是作为一个常数项,不需要特别的初始化,设为0是常见做法零初始化
- 其他的初始化策略
- 零初始化
- 正态分布初始化
- 均匀分布初始化
- Xavier 初始化
- He 初始化
- LeCun 初始化
- Orthogonal 初始化
- 自适应初始化
- 常数初始化
- Sparse Initialization
- Lecun Normal 和 Variance Scaling Initialization
- Weight Norm Initialization
net[0].weight.data.normal_(0, 0.01)
net[0].bias.data.fill_(0)
定义损失函数
MSELoss是一个用于回归任务的标准损失函数
计算均方误差使用的是MSELoss
类(Mean Squared Error,MSE)
这里的loss_fn是生成了一个损失函数可以计算预测值与实际值的平方差的均值
- 其他损失函数
- 回归问题:使用 MSE、SmoothL1、Huber Loss 等。
- 分类问题:使用 Cross-Entropy Loss、BCE Loss 等。
- 特殊任务:使用 KL Divergence Loss、Cosine Embedding Loss
loss_fn = nn.MSELoss()
loss = loss_fn(output,labels)
定义优化器
小批量随机梯度下降算法是一种优化神经网络的标准工具
torch.optim.SGD:(Stochastic Gradient Descent, SGD)是pytorch中用于实现随机梯度下降的优化器
params: 是要优化的参数,通常传入net.parameters()作为参数
lr: (learning rate)学习率 用于控制每次更新的步长。较小的学习率可能导致收敛速度慢,而较大的学习率可能导致跳过最优解
momentum:动量w(Momentum),用于加速梯度下降,并避免在鞍点附近震荡。默认值为 0
dampening: 动量的衰减因子。默认值为 0
weight_decay: 权重衰减(L2 正则化),用于防止过拟合。默认值为 0
nesterov: 是否使用 Nesterov 动量,True 表示使用。默认值为 False
trainer = torch.optim.SGD(net.parameters(), lr=0.03)
#拓展
optimizer = torch.optim.SGD(params, lr=0.01, momentum=0, dampening=0, weight_decay=0, nesterov=False)
训练
num_epochs = 3 # 训练3轮
for epoch in range(num_epochs):
for X, y in data_iter: # 获取特征和标签
l = loss(net(X) ,y) # net(X)即y的预测值,计算损失,前向传播
trainer.zero_grad() # 清除之前的梯度
l.backward() # 反向传播,利用链式法则求损失对参数的梯度
trainer.step() # 优化参数
l = loss(net(features), labels) # 计算这次训练后整个数据集的损失
print(f'epoch {epoch + 1}, loss {l:f}') # 展示优化进度