线性模型

假设自变量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是生成了一个损失函数可以计算预测值与实际值的平方差的均值

  • 其他损失函数
    • 回归问题:使用 MSESmoothL1Huber Loss 等。
    • 分类问题:使用 Cross-Entropy LossBCE Loss 等。
    • 特殊任务:使用 KL Divergence LossCosine 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}') # 展示优化进度