PyTorch之逻辑回归模型实现与函数介绍

文章目录

    • 一、逻辑回归简介和完整代码
      • 基本原理
      • 损失函数
      • 优化算法
      • 多分类问题
      • 应用场景
      • 代码实现
    • 二、逻辑回归模型构建
      • 1.导入库
      • 2.设置超参数
      • 3.加载数据集
      • 4.创建数据加载器
      • 5.定义模型
      • 6.定义损失函数和优化器
      • 7.训练模型
      • 8.测试模型
      • 9.保存模型
    • 三、常用函数解析

一、逻辑回归简介和完整代码

逻辑回归(Logistic Regression)是一种广泛应用于二分类问题的统计模型,尽管它的名字中有“回归”二字,但实际上它用于分类任务。逻辑回归通过使用逻辑函数将输入特征转换为0和1之间的值,从而预测一个事件发生的概率。

基本原理

逻辑回归使用的是Sigmoid函数,其数学表达式为:
[ \sigma(z) = \frac{1}{1 + e^{-z}} ]
其中,( z ) 是线性组合 ( z = w^Tx + b ),这里 ( w ) 是权重向量,( x ) 是特征向量,( b ) 是偏置项。

Sigmoid函数的输出范围在0和1之间,这使得它非常适合用作概率的估计。在二分类问题中,我们可以将Sigmoid函数的输出解释为属于正类(通常标记为1)的概率。

损失函数

逻辑回归使用的损失函数是二元交叉熵损失(Binary Cross-Entropy Loss)。对于单个样本,损失函数定义为:
[ \text{Loss} = -\left( y \cdot \log(\sigma(z)) + (1 - y) \cdot \log(1 - \sigma(z)) \right) ]
其中,( y ) 是真实标签(0或1),( \sigma(z) ) 是模型预测为正类的概率。

对于整个数据集,损失函数通常是所有样本损失的均值。

优化算法

逻辑回归通常使用梯度下降(Gradient Descent)或其变种(如随机梯度下降SGD、小批量梯度下降MBGD等)来优化损失函数,从而学习权重 ( w ) 和偏置 ( b )。

多分类问题

逻辑回归也可以扩展到多分类问题,这通常通过“一对余”(One-vs-Rest)或“一对一”(One-vs-One)策略来实现。在PyTorch中,nn.CrossEntropyLoss已经内置了对多分类的支持,它接受一个分类的 logits 向量和对应的标签,内部自动应用了softmax函数来进行多分类的概率估计。

应用场景

逻辑回归适用于以下场景:

  • 二分类问题,如垃圾邮件检测、疾病诊断等。
  • 需要输出概率预测的问题。
  • 数据集特征和标签是线性可分的。

逻辑回归简单、易于实现,并且计算效率高,但它也有一些局限性,比如对于非线性问题,它可能无法很好地工作,此时可能需要更复杂的模型,如神经网络。

代码实现

在PyTorch中,逻辑回归可以通过nn.Linear层来实现,其中最后一层的输出维度是2(对于二分类问题)。然后使用nn.Sigmoidnn.BCEWithLogitsLoss(它结合了Sigmoid和BCELoss,更稳定)来进行概率估计和损失计算。

import torch
import torch.nn as nn
import torchvision
import torchvision.transforms as transforms


# Hyper-parameters 
input_size = 28 * 28    # 784
num_classes = 10
num_epochs = 5
batch_size = 100
learning_rate = 0.001

# MNIST dataset (images and labels)
train_dataset = torchvision.datasets.MNIST(root='../../data', 
                                           train=True, 
                                           transform=transforms.ToTensor(),
                                           download=True)

test_dataset = torchvision.datasets.MNIST(root='../../data', 
                                          train=False, 
                                          transform=transforms.ToTensor())

# Data loader (input pipeline)
train_loader = torch.utils.data.DataLoader(dataset=train_dataset, 
                                           batch_size=batch_size, 
                                           shuffle=True)

test_loader = torch.utils.data.DataLoader(dataset=test_dataset, 
                                          batch_size=batch_size, 
                                          shuffle=False)

# Logistic regression model
model = nn.Linear(input_size, num_classes)

# Loss and optimizer
# nn.CrossEntropyLoss() computes softmax internally
criterion = nn.CrossEntropyLoss()  
optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate)  

# Train the model
total_step = len(train_loader)
for epoch in range(num_epochs):
    for i, (images, labels) in enumerate(train_loader):
        # Reshape images to (batch_size, input_size)
        images = images.reshape(-1, input_size)
        
        # Forward pass
        outputs = model(images)
        loss = criterion(outputs, labels)
        
        # Backward and optimize
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        
        if (i+1) % 100 == 0:
            print ('Epoch [{}/{}], Step [{}/{}], Loss: {:.4f}' 
                   .format(epoch+1, num_epochs, i+1, total_step, loss.item()))

# Test the model
# In test phase, we don't need to compute gradients (for memory efficiency)
with torch.no_grad():
    correct = 0
    total = 0
    for images, labels in test_loader:
        images = images.reshape(-1, input_size)
        outputs = model(images)
        _, predicted = torch.max(outputs.data, 1)
        total += labels.size(0)
        correct += (predicted == labels).sum()

    print('Accuracy of the model on the 10000 test images: {} %'.format(100 * correct / total))

# Save the model checkpoint
torch.save(model.state_dict(), 'model.ckpt')

二、逻辑回归模型构建

1.导入库

import torch
import torch.nn as nn
import torchvision
import torchvision.transforms as transforms

这部分代码导入了所需的PyTorch库,包括基础的torch模块、神经网络模块torch.nntorchvision用于加载数据集,以及transforms用于图像预处理。

2.设置超参数

# Hyper-parameters 
input_size = 28 * 28    # 784
num_classes = 10
num_epochs = 5
batch_size = 100
learning_rate = 0.001

这里定义了模型训练的超参数,包括输入数据的维度、类别数、训练轮数、批次大小和学习率。

3.加载数据集

# MNIST dataset (images and labels)
train_dataset = torchvision.datasets.MNIST(root='../../data', 
                                           train=True, 
                                           transform=transforms.ToTensor(),
                                           download=True)

test_dataset = torchvision.datasets.MNIST(root='../../data', 
                                          train=False, 
                                          transform=transforms.ToTensor())

加载MNIST数据集,包括训练集和测试集。使用transforms.ToTensor()将图像转换为PyTorch张量。

4.创建数据加载器

# Data loader (input pipeline)
train_loader = torch.utils.data.DataLoader(dataset=train_dataset, 
                                           batch_size=batch_size, 
                                           shuffle=True)

test_loader = torch.utils.data.DataLoader(dataset=test_dataset, 
                                          batch_size=batch_size, 
                                          shuffle=False)

创建数据加载器,用于批量加载数据,并在训练时打乱数据顺序。

5.定义模型

# Logistic regression model
model = nn.Linear(input_size, num_classes)

定义一个线性模型,用于逻辑回归。

6.定义损失函数和优化器

# Loss and optimizer
# nn.CrossEntropyLoss() computes softmax internally
criterion = nn.CrossEntropyLoss()  
optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate)  

使用交叉熵损失函数和随机梯度下降优化器。

7.训练模型

# Train the model
total_step = len(train_loader)
for epoch in range(num_epochs):
    for i, (images, labels) in enumerate(train_loader):
        # Reshape images to (batch_size, input_size)
        images = images.reshape(-1, input_size)
        
        # Forward pass
        outputs = model(images)
        loss = criterion(outputs, labels)
        
        # Backward and optimize
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        
        if (i+1) % 100 == 0:
            print ('Epoch [{}/{}], Step [{}/{}], Loss: {:.4f}' 
                   .format(epoch+1, num_epochs, i+1, total_step, loss.item()))

训练循环,包括前向传播、损失计算、反向传播和参数更新。

8.测试模型

# Test the model
# In test phase, we don't need to compute gradients (for memory efficiency)
with torch.no_grad():
    correct = 0
    total = 0
    for images, labels in test_loader:
        images = images.reshape(-1, input_size)
        outputs = model(images)
        _, predicted = torch.max(outputs.data, 1)
        total += labels.size(0)
        correct += (predicted == labels).sum()

    print('Accuracy of the model on the 10000 test images: {} %'.format(100 * correct / total))

测试循环,计算模型在测试集上的准确率。

9.保存模型

# Save the model checkpoint
torch.save(model.state_dict(), 'model.ckpt')

保存模型参数。

三、常用函数解析

以下是代码中使用的PyTorch函数和类,包括它们的格式、参数意义、函数意义以及在代码中的用法:

  1. torchvision.datasets.MNIST(root, train, transform, download)

    • 格式:torchvision.datasets.MNIST(root, train, transform, download)
    • 参数:
      • root:数据集存放的根目录。
      • train:布尔值,指示是否加载训练集。
      • transform:一个变换,比如transforms.ToTensor(),用于对数据集进行预处理。
      • download:布尔值,指示是否下载数据集。
    • 意义:加载MNIST数据集。
    • 用法:
      train_dataset = torchvision.datasets.MNIST(root='../../data', train=True, transform=transforms.ToTensor(), download=True)
      
  2. torch.utils.data.DataLoader(dataset, batch_size, shuffle)

    • 格式:torch.utils.data.DataLoader(dataset, batch_size, shuffle)
    • 参数:
      • dataset:要加载的数据集。
      • batch_size:每个批次的样本数量。
      • shuffle:布尔值,指示在每个epoch开始时是否打乱数据。
    • 意义:创建一个数据加载器,用于批量加载数据。
    • 用法:
      train_loader = torch.utils.data.DataLoader(dataset=train_dataset, batch_size=batch_size, shuffle=True)
      
  3. nn.Linear(in_features, out_features)

    • 格式:nn.Linear(in_features, out_features)
    • 参数:
      • in_features:输入特征的数量。
      • out_features:输出特征的数量。
    • 意义:创建一个线性层。
    • 用法:
      model = nn.Linear(input_size, num_classes)
      
  4. nn.CrossEntropyLoss()

    • 格式:nn.CrossEntropyLoss()
    • 参数:无默认参数。
    • 意义:创建一个计算交叉熵损失的模块,内部计算softmax。
    • 用法:
      criterion = nn.CrossEntropyLoss()
      
  5. torch.optim.SGD(params, lr)

    • 格式:torch.optim.SGD(params, lr)
    • 参数:
      • params:模型参数的迭代器。
      • lr:学习率。
    • 意义:创建随机梯度下降优化器。
    • 用法:
      optimizer = torch.optim.SGD(model.parameters(), lr=learning_rate)
      
  6. loss.backward()

    • 格式:loss.backward()
    • 参数:无。
    • 意义:计算损失相对于模型参数的梯度。
    • 用法:
      loss.backward()
      
  7. optimizer.step()

    • 格式:optimizer.step()
    • 参数:无。
    • 意义:根据计算得到的梯度更新模型参数。
    • 用法:
      optimizer.step()
      
  8. optimizer.zero_grad()

    • 格式:optimizer.zero_grad()
    • 参数:无。
    • 意义:清除(重置)过往梯度。
    • 用法:
      optimizer.zero_grad()
      
  9. torch.no_grad()

    • 格式:torch.no_grad()
    • 参数:无。
    • 意义:上下文管理器,用于在测试或推理阶段禁用梯度计算以节省内存。
    • 用法:
      with torch.no_grad():
          # 测试模型的代码
      
  10. torch.save(obj, f)

    • 格式:torch.save(obj, f)
    • 参数:
      • obj:要保存的对象。
      • f:文件路径或文件对象。
    • 意义:将对象保存到文件。
    • 用法:
      torch.save(model.state_dict(), 'model.ckpt')
      
  11. images.reshape(-1, input_size)

    • 格式:images.reshape(shape)
    • 参数:
      • shape:期望的新形状。
    • 意义:重塑张量的形状。
    • 用法:
      images = images.reshape(-1, input_size)
      
  12. _, predicted = torch.max(outputs.data, 1)

    • 格式:torch.max(input, dim, keepdim=False)
    • 参数:
      • input:输入张量。
      • dim:要计算最大值的维度。
    • 意义:计算张量在指定维度上的最大值和索引。
    • 用法:
      _, predicted = torch.max(outputs.data, 1)
      

猜你喜欢

转载自blog.csdn.net/wumingzei/article/details/141020862