深度学习建模的整体流程

整体导库

在三种建模实验中,所需要导入的库大体是一样的,同时用到了深度学习笔记7中所封装的三个数据集创建函数:

回归类数据集tensorGenReg()
分类型数据集tensorGenCla()
小批量切分函数数据集data_iter()

同时需要用到深度学习中torch的各种工具

#随机模块
import random

#绘图工具
import matplotlib as mpl
import matplotlib.pyplot as plt

import numpy as np

import torch
from torch import nn,optim
import torch.nn.functional as F
from torch.utils.data import Dataset,TensorDataset,DataLoader
from torch.utils.tensorboard import SummaryWriter

#自定义模块,即上个笔记封装的三个数据集创建函数
from torchLearning import*

线性回归建模试验

定义核心参数

batch_size= 10     #每一个小批量的数据数量
lr = 0.03  #学习率
num_epochs = 3  #循环轮次,遍历多少次所有数据

数据准备

# 设置随机数种子
torch.manual_seed(420)   

# 创建数据集 
features, labels = tensorGenReg()           
features = features[:, :-1]                                  # 剔除最后全是1的列
data = TensorDataset(features, labels)                       # 数据封装
batchData = DataLoader(data, batch_size = batch_size, shuffle = True)      # 数据加载

此处剔除最后全是1的那一列的原因是:最后全为1的列通常是手动添加的 “偏置项”(类似线性回归中的常数项)。此处剔除是为了后续在模型中通过设置bias=True来自动处理,更符合 PyTorch 的模型设计习惯。

torch的数据集切分封装和加载函数TensorDataset和DataLoader通常一起使用,完成对数据集的处理。

定义模型

本次简单实验定义一个一层的网络

模型具体构建

class LR(nn.Module):
    def __init__(self, in_features=2, out_features=1):       # 定义模型的点线结构
        super(LR, self).__init__()
        self.linear = nn.Linear(in_features, out_features)
        
    def forward(self, x):                                    # 定义模型的正向传播规则
        out = self.linear(x)             
        return out

# 实例化模型
LR_model = LR()

定义损失函数

criterion = nn.MSELoss()

MSELoss:均方误差损失,先求预测值与真实值之间差值的平方,再对所有样本的平方误差取平均值,MSE=\frac{1}{N}SSE。

定义优化方法

optimizer = optim.SGD(LR_model.parameters(), lr = 0.03)
#LR_model是你定义的模型(例如线性回归模型nn.Linear),
#.parameters()方法会返回模型中所有需要被优化的参数(通常是权重weight和偏置bias),这些参数是优化器的调整对象。
#lr学习率,控制参数更新幅度的超参数。

初始化一个随机梯度下降优化器,用来最小化损失函数MSE。

定义训练函数

def fit(net, criterion, optimizer, batchdata, epochs):
    for epoch in range(epochs):           #多轮迭代
        for X, y in batchdata:            #批次迭代
            yhat = net.forward(X)         #前向传播
            loss = criterion(yhat, y)     #计算损失
            optimizer.zero_grad()         #梯度清零,防止梯度累积,第一次循环则使初始梯度为0
            loss.backward()               #反向传播,计算梯度
            optimizer.step()              #参数更新,使损失函数减小

函数超参数:

net:需要训练的模型,在这里是LR_model

criterion:损失函数,在这里是MSE

optimizer:优化器,在这里是SGD

batchdata:批量数据加载器,提供DataLoader对象,提供按批次迭代的(特征X,标签y)数据

epochs:训练总轮次

执行模型训练并查看结果

# 设置随机数种子
torch.manual_seed(420)   

fit(net = LR_model, 
    criterion = criterion, 
    optimizer = optimizer, 
    batchdata = batchData, 
    epochs = num_epochs)

查看结果:

模型架构和每层的输入输出

模型训练后获得的最佳参数

模型训练后的损失,0.0001非常小

逻辑回归建模试验

定义核心参数

batch_size = 10                                # 每一个小批的数量
lr = 0.03                                      # 学习率
num_epochs = 3                                 # 训练过程遍历几次数据

此时定义逻辑回归的核心参数与线性回归参数相同。

数据准备

# 设置随机数种子
torch.manual_seed(420)   

# 创建数据集
features, labels = tensorGenCla(num_class=2)          #手动设置类别为2,该任务为二分类
labels = labels.float()                                 # 损失函数要求标签也必须是浮点型
data = TensorDataset(features, labels)            
batchData = DataLoader(data, batch_size = batch_size, shuffle = True)   #与回归一致

分类任务中常用的损失函数,如二元交叉熵损失BCEWithLogitsLoss,要求输入的标签必须是浮点型,与模型输出的概率值在数值类型上匹配。

定义模型

定义的神经网络结构

具体设计

class logisticR(nn.Module):
    def __init__(self, in_features=2, out_features=1):       # 定义模型的点线结构
        super(logisticR, self).__init__()
        self.linear = nn.Linear(in_features, out_features)
        
    def forward(self, x):                                    # 定义模型的正向传播规则
        out = self.linear(x)             
        return out

# 实例化模型和
logic_model = logisticR()

定义损失函数

criterion = nn.BCEWithLogitsLoss()

BCEWithLogitsLoss是二分类中经典损失函数,它将 “Sigmoid函数”“二元交叉熵损失BCE Loss” 合并为一个操作,简化了代码,又提高了数值稳定性。

定义优化方法

optimizer = optim.SGD(logic_model.parameters(), lr = lr)

优化方法同样选择SGD

定义训练函数

def fit(net, criterion, optimizer, batchdata, epochs):
    for epoch in range(epochs):
        for X, y in batchdata:
            zhat = net.forward(X)
            loss = criterion(zhat, y)
            optimizer.zero_grad()
            loss.backward()
            optimizer.step()    

训练函数与上个实验相同

定义准确率函数

对于分类模型,通常需要定义一个准确率函数,来判断模型分类的效果

将概率值转换为类别标签的函数,核心功能是通过设定阈值(p=0.5),将模型输出的概率(或分数)映射为离散的类别(0 或 1)然后经过float转化为浮点型0或1。

def cal(sigma, p=0.5):            
    return((sigma >= p).float())

准确率函数

def accuracy(sigma, y):
    acc_bool = cal(sigma).flatten() == y.flatten()
    acc = torch.mean(acc_bool.float())
    return(acc)

超参数解释:

sigma:模型的预测输出

y:真实标签,此时y就是上述数据集创建的labels,一定是浮点型,与sigma数据类型一致

.flatten()将预测值和真实标签都展平为一维张量,避免因维度不匹配导致比较错误。

==  逐元素比较,相同为True,不相同为False

acc_bool.float(),将布尔张量转换为浮点型张量,True转换为1,False转换为0

mean()则计算平均值,也就得出了准确率

执行模型训练并查看结果

# 设置随机数种子
torch.manual_seed(420)   

fit(net = logic_model, 
    criterion = criterion, 
    optimizer = optimizer, 
    batchdata = batchData, 
    epochs = num_epochs)

查看结果

softmax回归建模实验

定义核心参数

batch_size = 10                                # 每一个小批的数量
lr = 0.03                                      # 学习率
num_epochs = 3                                 # 训练过程遍历几次数据

数据准备

# 设置随机数种子
torch.manual_seed(420)   

# 创建数据集
features, labels = tensorGenCla(deg_dispersion = [6, 2])
labels = labels.float()                           # 损失函数要求标签也必须是浮点型
data = TensorDataset(features, labels)            
batchData = DataLoader(data, batch_size = batch_size, shuffle = True)

定义模型

定义的神经网络结构:

具体实现:

class softmaxR(nn.Module):
    def __init__(self, in_features=2, out_features=3, bias=False):       # 定义模型的点线结构
        super(softmaxR, self).__init__()
        self.linear = nn.Linear(in_features, out_features)
        
    def forward(self, x):                                    # 定义模型的正向传播规则
        out = self.linear(x)             
        return out

# 实例化模型和
softmax_model = softmaxR()

定义损失函数

criterion = nn.CrossEntropyLoss()

CrossEntropyLoss是一个多分类常用的损失函数,本质上是LogSoftmax和NLLLoss的结合体,具体操作过程可拆分为:

  1. 对模型输出的原始 logits(未经过 softmax 的输出)应用LogSoftmax,将其转换为归一化的对数概率(保证数值稳定性)。

  2. 计算NLLLoss:即对 “真实类别对应的对数概率” 取负值,再求平均(或加权平均)。

定义优化方法

optimizer = optim.SGD(softmax_model.parameters(), lr = lr)

定义训练函数

def fit(net, criterion, optimizer, batchdata, epochs):
    for epoch in range(epochs):
        for X, y in batchdata:
            zhat = net.forward(X)
            y = y.flatten().long()       # 损失函数计算要求转化为整数,使用ling()
            loss = criterion(zhat, y)
            optimizer.zero_grad()
            loss.backward()
            optimizer.step()

定义准确率函数

def m_accuracy(soft_z, y):
    acc_bool = torch.argmax(soft_z, 1).flatten() == y.flatten()
    acc = torch.mean(acc_bool.float())
    return(acc)

argmax函数在维度为1(列,类别维度)上取最大值索引,得到模型预测的类别。

argmax用法示例
x = torch.tensor([3, 1, 4, 2])  # 1维张量(shape: (4,))
print(torch.argmax(x))  # 输出:tensor(2)(值4在索引2的位置)
x = torch.tensor([
    [1, 3, 2],
    [4, 1, 5]
])  # 2维张量(shape: (2, 3),2行3列)

# dim=0:按列计算(比较每一列的元素,返回最大值所在的行索引)
print(torch.argmax(x, dim=0))  # 输出:tensor([1, 0, 1])
# 解释:
# 第0列:[1,4] → 最大值4在第1行 → 索引1
# 第1列:[3,1] → 最大值3在第0行 → 索引0
# 第2列:[2,5] → 最大值5在第1行 → 索引1

# dim=1:按行计算(比较每一行的元素,返回最大值所在的列索引)
print(torch.argmax(x, dim=1))  # 输出:tensor([1, 2])
# 解释:
# 第0行:[1,3,2] → 最大值3在第1列 → 索引1
# 第1行:[4,1,5] → 最大值5在第2列 → 索引2
x = torch.tensor([
    [[1, 5], [3, 2]],  # 第0个深度层
    [[4, 0], [6, 7]]   # 第1个深度层
])  # 3维张量(shape: (2, 2, 2),2深度×2行×2列)

# dim=0:按“深度”维度计算(比较每个位置在不同深度的值,返回最大值的深度索引)
print(torch.argmax(x, dim=0))  # 输出:
# tensor([[1, 0],
#         [1, 1]])
# 解释:
# 位置(0,0):[1,4] → 最大值4在深度1 → 索引1
# 位置(0,1):[5,0] → 最大值5在深度0 → 索引0
# 位置(1,0):[3,6] → 最大值6在深度1 → 索引1
# 位置(1,1):[2,7] → 最大值7在深度1 → 索引1

# dim=1:按“行”维度计算(在每个深度层内,按行找最大值的行索引)
print(torch.argmax(x, dim=1))  # 输出:
# tensor([[1, 0],
#         [1, 1]])
# 解释(以第0个深度层为例):
# 第0列:[1,3] → 最大值3在第1行 → 索引1
# 第1列:[5,2] → 最大值5在第0行 → 索引0

执行模型训练并查看结果

torch.manual_seed(420)

fit(net = softmax_model, 
    criterion = criterion, 
    optimizer = optimizer, 
    batchdata = batchData, 
    epochs = num_epochs)

查看结果

加餐:TensordBoard的使用

TensorBoard用来进行记录一些表格或图像数据,作为日志,用于将模型训练过程中的关键指标(如损失、准确率)、模型参数分布、图像等数据写入日志文件,方便后续通过 TensorBoard 工具进行可视化分析。使用前需要导入:

from torch.utils.tensorboard import SummaryWriter

使用实例

writer = SummaryWriter(log_dir = 'test')

初始化一个日志记录器,log_dir='test'是指定日志文件的保存路径。

Scalar:记录标量,如训练 / 验证损失(loss)、准确率(accuracy)等随训练轮次(epoch)的变化曲线。

Image:记录图像,如输入数据的样本、模型生成的图像等。

Histogrm:记录直方图,如模型参数(权重、偏置)的分布变化,帮助分析参数是否正常更新。

Graph:记录计算图,可视化模型的网络结构。

实例代码:

for i in range(20):
    writer.add_scalar('mull',i+i,i)
for i in range(10):
    writer.add_scalar('mul', i*i, i)
writer.add_scalar('中国',100)
writer.add_scalar('我',80)
writer.add_scalar('爱你',120)

全部运行后,在TensorBoard查看结果:

终端界面查看:

命令进入到对应的目录,刚刚创建的test一定要在该目录下

代码:

tensorboard --logdir "test" --port=6006

#--port=6006 定向使用端口6006来打开tensorboard,如果6006被占用,可使用其他端口

然后点击网址进入tensorboard页面查看内容

关闭这个页面后,一定到终端界面摁Ctrl+c退出!!!(可能是电脑性能不行,不能及时清理缓存,会检测到没有关闭,在持续打开进程,不会关闭)

jupyter notebook界面查看

代码:

%load_ext tensorboard
%tensorboard --logdir=="test" 

CMD释放进程命令:

tasklist | findstr tensorboard
taskkill /IM tensorboard.exe /F

CMD查看端口目前正在进行的进程:

netstat -ano | findstr :6006

更多推荐