深度学习 Pytorch 逻辑回归建模实验

embedded/2025/2/8 14:38:21/

接下来进行逻辑回归的建模实验,首先需要导入相关库和自定义的模块。

# 随机模块
import random# 绘图模块
import matplotlib as mpl
import matplotlib.pyplot as plt# numpy
import numpy as np# pytorch
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 *# 导入以下包从而使得可以在jupyter中的一个cell输出多个结果
from IPython.core.interactiveshell import InteractiveShell
InteractiveShell.ast_node_interactivity = "all"

当然,我们可以通过查看我们自定义的函数帮助文档来验证是否导入成功

tensorGenCla?
# output :
Signature:
tensorGenCla(num_examples=500,num_inputs=2,num_class=3,deg_dispersion=[4, 2],bias=False,
)
Docstring:
分类数据集创建函数。 
:param num_examples: 每个类别的数据数量
:param num_inputs: 数据集特征数量
:param num_class:数据集标签类别总数
:param deg_dispersion:数据分布离散程度参数,需要输入一个列表,其中第一个参数表示每个类别数组均值的参考、第二个参数表示随机数组标准差。
:param bias:建立模型逻辑回归模型时是否带入截距
:return: 生成的特征张量和标签张量,其中特征张量是浮点型二维数组,标签张量是长正型二维数组。
File:      c:\users\desktop\study\【2024深度学习课件\lesson 12\【pdf配套代码】code\torchlearning.py
Type:      function

54 逻辑回归手动实现

接下来,尝试手动实现二分类逻辑回归,还是根据此前介绍的深度学习建模流程进行手动实现。


54.1 生成数据集

利用此前创建的tensorGenCla进行二分类数据集的创建

# 设置随机数种子
torch.manual_seed(420)   # 创建数据集
features, labels = tensorGenCla(num_class=2, bias=True)# 可视化展示
plt.scatter(features[:, 0], features[:, 1], c = labels)

在这里插入图片描述

features
# output :
tensor([[-2.0141, -0.9911,  1.0000],[-0.6593, -2.7657,  1.0000],[-1.9395, -1.2347,  1.0000],...,[ 2.9623,  2.0861,  1.0000],[ 0.4535, -0.2140,  1.0000],[-2.6681,  3.3935,  1.0000]])

54.2 建模过程

Stage 1 模型选择

针对二分类问题(0-1问题),我们可以简单的输出一个结果,作为标签取值为1的概率,因此模型结构如下

对应的可定义如下模型

  1. 激活函数

    def sigmoid(z):return 1 / (1 + torch.exp(-z))
    
  2. 逻辑回归函数

    def logistic(X, w):return sigmoid(torch.mm(X, w))
    
  3. 辅助函数

    由于sigmoid输出结果是连续值,而用于二分类判别时,我们需要将连续数值转化为所判定的类别,可定义对应分类函数如下:

    def cal(sigma, p = 0.5):return ((sigma>=0.5).float())
    
    a = torch.randint(10, (5, ))
    a
    # output :
    tensor([8, 0, 4, 4, 2])a >= 5
    # output :
    tensor([ True, False, False, False, False])(a >= 5).float()
    # output :
    tensor([1., 0., 0., 0., 0.])
    

另外,对分类模型,我们往往会通过准确率 判别模型效果 ,因此还需要定义准确率函数

  1. 准确率函数

    def accuracy(sigma, y):acc_bool = cal(sigma).flatten() == y.flatten()acc = torch.mean(acc_bool.float())return (acc)
    
    p = torch.tensor([1, 1, 2]) == torch.tensor([1, 2, 2])
    p
    # output :
    tensor([ True, False,  True])p.float()
    # output :
    tensor([1., 0., 1.])torch.mean(p.float())
    # output :
    tensor(0.6667)
    

Stage 2 定义损失函数

def cross_entropy(sigma, y):return (-(1/y.numel())*torch.sum((1-y)*torch.log(1-sigma)+y*torch.log(sigma)))

Stage 3 定义优化方法

def sgd(params,lr):params.data -= lr * params.gradparams.grad.zero_()

Stage 4 训练模型

# 设置随机数种子
torch.manual_seed(420)    # 初始化核心参数
batch_size = 10                                # 每一个小批的数量
lr = 0.03                                      # 学习率
num_epochs = 3                                 # 训练过程遍历几次数据
w = torch.ones(3, 1, requires_grad = True)     # 随机设置初始权重# 参与训练的模型方程
net = logistic                                 # 使用逻辑回归方程
loss = cross_entropy                           # 交叉熵损失函数# 训练过程
for epoch in range(num_epochs):for X, y in data_iter(batch_size, features, labels):l = loss(net(X, w), y)l.backward()sgd(w, lr)train_acc = accuracy(net(features, w), labels)print('epoch %d, accuracy %f' % (epoch + 1, train_acc))
# output :
epoch 1, accuracy 0.904000
epoch 2, accuracy 0.907000
epoch 3, accuracy 0.914000
w
# output :
tensor([[1.0069],[0.9753],[0.5765]], requires_grad=True)

54.3 模型调试

根据上述迭代三轮返回的准确率,能够看出整体还在增加,让我们再多迭代几轮查看结果

# 设置随机数种子
torch.manual_seed(420)   # 迭代轮数
num_epochs = 20# 设置初始权重
w = torch.ones(3, 1, requires_grad = True)    # 设置列表容器
train_acc = []# 执行迭代
for i in range(num_epochs):for epoch in range(i):for X, y in data_iter(batch_size, features, labels):l = loss(net(X, w), y)l.backward()sgd(w, lr)train_acc.append(accuracy(net(features, w), labels))# 绘制图像查看准确率变化情况
plt.plot(list(range(num_epochs)), train_acc)

在这里插入图片描述

train_acc
# output :
[tensor(0.8970),tensor(0.9040),tensor(0.9120),tensor(0.9170),tensor(0.9190),tensor(0.9150),tensor(0.9150),tensor(0.9150),tensor(0.9150),tensor(0.9150),tensor(0.9150),tensor(0.9150),tensor(0.9150),tensor(0.9140),tensor(0.9140),tensor(0.9150),tensor(0.9150),tensor(0.9150),tensor(0.9150),tensor(0.9150)]

能够看出,增加迭代次数之后,损失函数逼近最小值点,每次迭代梯度取值较小,整体准确率趋于平稳

当然,如果我们将数据难度增加,也就是增加数据的离散程度,是否会对模型结果造成影响

tensorGenCla?
# output :
Signature:
tensorGenCla(num_examples=500,num_inputs=2,num_class=3,deg_dispersion=[4, 2],bias=False,
)
Docstring:
分类数据集创建函数。 
:param num_examples: 每个类别的数据数量
:param num_inputs: 数据集特征数量
:param num_class:数据集标签类别总数
:param deg_dispersion:数据分布离散程度参数,需要输入一个列表,其中第一个参数表示每个类别数组均值的参考、第二个参数表示随机数组标准差。
:param bias:建立模型逻辑回归模型时是否带入截距
:return: 生成的特征张量和标签张量,其中特征张量是浮点型二维数组,标签张量是长正型二维数组。
File:      c:\users\desktop\study\【2024深度学习课件\lesson 12\【pdf配套代码】code\torchlearning.py
Type:      function
torch.manual_seed(420)   features, labels = tensorGenCla(num_class=2, bias=True, deg_dispersion=[4, 4])# 可视化展示
plt.scatter(features[:, 0], features[:, 1], c = labels)

在这里插入图片描述

# 设置随机数种子
torch.manual_seed(420)   # 迭代轮数
num_epochs = 20# 设置初始权重
w = torch.zeros(3, 1, requires_grad = True)    # 设置列表容器
train_acc = []# 执行迭代
for i in range(num_epochs):for epoch in range(i):for X, y in data_iter(batch_size, features, labels):l = loss(net(X, w), y)l.backward()sgd(w, lr)train_acc.append(accuracy(net(features, w), labels))# 绘制图像查看准确率变化情况
plt.plot(list(range(num_epochs)), train_acc)

在这里插入图片描述

能够发现,随着数据情况变复杂,相同模型的准确率发生了很大的变化。

train_acc
# output :
[tensor(0.5000),tensor(0.7320),tensor(0.7310),tensor(0.7330),tensor(0.7320),tensor(0.7300),tensor(0.7290),tensor(0.7310),tensor(0.7290),tensor(0.7310),tensor(0.7320),tensor(0.7260),tensor(0.7320),tensor(0.7340),tensor(0.7270),tensor(0.7330),tensor(0.7320),tensor(0.7270),tensor(0.7310),tensor(0.7280)]

55 逻辑回归的快速实现


55.1 构建模型

接下来,我们练习使用PyTorch中的函数和类,进行逻辑回归的快速构建。


定义核心参数

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

数据准备

# 设置随机数种子
torch.manual_seed(420)   # 创建数据集
features, labels = tensorGenCla(num_class=2)
labels = labels.float()   # 损失函数要求标签也必须是浮点型
data = TensorDataset(features, labels)            
batchData = DataLoader(data, batch_size = batch_size, shuffle = True)

Stage 1 定义模型

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()

Stage 2 定义损失函数

criterion = nn.BCEWithLogitsLoss()

Stage 3 定义优化方法

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

Stage 4 模型训练

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()      

接下来,即可执行模型训练

# 设置随机数种子
torch.manual_seed(420)   fit(net = logic_model, criterion = criterion, optimizer = optimizer, batchdata = batchData, epochs = num_epochs)

查看模型训练结果

logic_model
# output :
logisticR((linear): Linear(in_features=2, out_features=1, bias=True)
)
# 查看模型参数
list(logic_model.parameters())
# output :
[Parameter containing:tensor([[0.8394, 0.8016]], requires_grad=True),Parameter containing:tensor([-0.2617], requires_grad=True)]
# 计算交叉熵损失
criterion(logic_model(features), labels)
# output :
tensor(0.2293, grad_fn=<BinaryCrossEntropyWithLogitsBackward>)
def acc_zhat(zhat, y):"""输入为线性方程计算结果,输出为逻辑回归准确率的函数:param zhat:线性方程输出结果 :param y: 数据集标签张量:return:准确率 """sigma = sigmoid(zhat)return accuracy(sigma, y)
acc_zhat(logic_model(features), labels)
# output :
tensor(0.9130)

55.2 模型调试

同样,我们首先尝试多迭代几次,看下准确率如何发生变化

#创建数据
torch.manual_seed(420)   features, labels = tensorGenCla(num_class=2)                     
labels = labels.float()                           
data = TensorDataset(features, labels)            
batchData = DataLoader(data, batch_size = batch_size, shuffle = True)
# 设置随机数种子
torch.manual_seed(420)  # 初始化核心参数
num_epochs = 20
LR1 = logisticR()
cr1 = nn.BCEWithLogitsLoss()
op1 = optim.SGD(LR1.parameters(), lr = lr)# 创建列表容器
train_acc = []# 执行建模
for epochs in range(num_epochs):fit(net = LR1, criterion = cr1, optimizer = op1, batchdata = batchData, epochs = epochs)epoch_acc = acc_zhat(LR1(features), labels)train_acc.append(epoch_acc)# 绘制图像查看准确率变化情况
plt.plot(list(range(num_epochs)), train_acc)

在这里插入图片描述

train_acc
# output :
[tensor(0.5170),tensor(0.9040),tensor(0.9180),tensor(0.9180),tensor(0.9150),tensor(0.9150),tensor(0.9150),tensor(0.9150),tensor(0.9150),tensor(0.9150),tensor(0.9150),tensor(0.9150),tensor(0.9150),tensor(0.9150),tensor(0.9140),tensor(0.9150),tensor(0.9150),tensor(0.9150),tensor(0.9150),tensor(0.9150)]

接下来,和此前一样,接下来尝试增加数据难度来测试模型分类性能

#创建数据
torch.manual_seed(420)   features, labels = tensorGenCla(num_class=2, deg_dispersion=[4, 4])                     
labels = labels.float()                           
data = TensorDataset(features, labels)            
batchData = DataLoader(data, batch_size = batch_size, shuffle = True)
plt.scatter(features[:, 0], features[:, 1], c = labels)

在这里插入图片描述

#创建数据
torch.manual_seed(420)   # 数据封装与加载
data = TensorDataset(features, labels)            
batchData = DataLoader(data, batch_size = batch_size, shuffle = True)# 初始化核心参数
num_epochs = 20
LR1 = logisticR()
cr1 = nn.BCEWithLogitsLoss()
op1 = optim.SGD(LR1.parameters(), lr = lr)# 创建列表容器
train_acc = []# 执行建模
for epochs in range(num_epochs):fit(net = LR1, criterion = cr1, optimizer = op1, batchdata = batchData, epochs = epochs)epoch_acc = acc_zhat(LR1(features), labels)train_acc.append(epoch_acc)# 绘制图像查看准确率变化情况
plt.plot(list(range(num_epochs)), train_acc)

在这里插入图片描述

train_acc
# output :
[tensor(0.4970),tensor(0.7250),tensor(0.7260),tensor(0.7290),tensor(0.7300),tensor(0.7260),tensor(0.7260),tensor(0.7300),tensor(0.7260),tensor(0.7250),tensor(0.7290),tensor(0.7310),tensor(0.7320),tensor(0.7340),tensor(0.7300),tensor(0.7300),tensor(0.7320),tensor(0.7290),tensor(0.7290),tensor(0.7330)]

和此前一样,准确率在0.7-0.75之间徘徊。


http://www.ppmy.cn/embedded/160558.html

相关文章

使用 OpenGL ES 加载图片并写入纹理单元

使用 OpenGL ES 加载图片并写入纹理单元:完整实现与解析 在 OpenGL ES 中,纹理是渲染图形的重要组成部分。纹理可以为 3D 模型或 2D 图形提供丰富的细节和视觉效果。在 iOS 开发中,我们通常需要将图片加载到 OpenGL ES 的纹理单元中,以便在渲染时使用。本文将通过一个完整…

智能化转型2.0:从“工具应用”到“价值重构”

过去几年&#xff0c;“智能化”从一个模糊的概念逐渐成为企业发展的核心议题。2024年&#xff0c;随着生成式AI、大模型、智能体等技术的爆发式落地&#xff0c;中国企业正式迈入智能化转型的2.0时代。这一阶段的核心特征是从单一场景的“工具应用”转向全链条的“价值重构”&…

【服务器知识】如何在linux系统上搭建一个nfs

文章目录 NFS网络系统搭建**1. 准备工作****2. 服务器端配置****(1) 安装 NFS 服务****(2) 创建共享目录****(3) 配置共享规则****(4) 生效配置并启动服务****(5) 防火墙配置** **3. 客户端配置****(1) 安装 NFS 客户端工具****(2) 创建本地挂载点****(3) 挂载 NFS 共享目录***…

全栈开发:使用.NET Core WebAPI构建前后端分离的核心技巧(二)

目录 配置系统集成 分层项目使用 筛选器的使用 中间件的使用 配置系统集成 在.net core WebAPI前后端分离开发中&#xff0c;配置系统的设计和集成是至关重要的一部分&#xff0c;尤其是在管理不同环境下的配置数据时&#xff0c;配置系统需要能够灵活、可扩展&#xff0c…

JMeter通过BeanShell创建CSV文件

在JMeter中通过BeanShell创建CSV文件&#xff0c;可以使用以下脚本实现&#xff1a; import java.io.FileWriter; import java.io.IOException;// 定义CSV文件路径&#xff08;建议使用绝对路径&#xff09; String csvFilePath "C:/jmeter_test/data/output.csv";…

IEEE 802.3/802.2 | LLC / SNAP

注&#xff1a;本文为 “IEEE 802.3/802.2 | LLC / SNAP” 相关文章合辑。 未整理去重。 第三篇部分内容出自第二篇。 802.2 协议 haoay321 2010-01-28 20:52:02 LLC 协议 LLC&#xff08;Logic Link Control&#xff0c;逻辑链路控制&#xff09;是 IEEE 802.2 协议中规定…

多方法实现影像组学特征降维与选择

大家好&#xff0c;我是带我去滑雪&#xff01; 在机器学习模型中&#xff0c;图像组学特征可分为三类。第一类是相关特征&#xff0c;这些特征对机器学习有积极作用&#xff0c;能够提升学习算法的性能。第二类是无关特征&#xff0c;它们对算法没有任何帮助&#xff0c;不会改…

51单片机(STC89C52)开发:点亮一个小灯

软件安装&#xff1a; 安装开发板CH340驱动。 安装KEILC51开发软件&#xff1a;C51V901.exe。 下载软件&#xff1a;PZ-ISP.exe 创建项目&#xff1a; 新建main.c 将main.c加入至项目中&#xff1a; main.c:点亮一个小灯 #include "reg52.h"sbit LED1P2^0; //P2的…