目标:
实现一个简单的二分类模型的训练过程,通过模拟数据集进行训练和优化,训练目标是使模型能够根据输入特征正确分类数据。
演示:
1.通过PyTorch生成了一个模拟的二分类数据集,包括特征矩阵data_x
和对应的标签数据data_y
。标签数据通过基于特征的线性组合生成,并转换成独热编码的形式。
import torch
# 从torch库中导入神经网络模块nn,用于构建神经网络模型
from torch import nn
# 导入torch.nn模块中的functional子模块,可用于访问各种函数,例如激活函数
import torch.nn.functional as F
n_item = 1000
n_feature = 2
learning_rate = 0.01
epochs = 100
# 生成一个模拟的数据集,其中包括一个随机生成的特征矩阵data_x和相应生成的标签数据data_y。标签数据通过基于特征的线性组合生成,并且转换成独热编码的形式。
# 设置随机数生成器的种子为123,通过设置随机种子,我们可以确保在每次运行代码时生成的随机数相同,这对于结果的可重现性非常重要。
torch.manual_seed(123)
# 生成一个随机数矩阵data_x,其中包含n_item行和n_feature列。矩阵中的元素是从标准正态分布(均值为0,标准差为1)中随机采样的。
data_x = torch.randn(size=(n_item, n_feature)).float()
# torch.where(...): 根据条件返回两个张量中相应位置的值。如果条件成立,将为0,否则为1。 long(): 用于将张量转换为Long型数据类型。
data_y = torch.where(torch.subtract(data_x[:, 0]*0.5, data_x[:, 1]*1.5)+0.02 > 0, 0, 1).long()
# 将标签数据data_y转换为独热编码形式,即将每个标签转换为一个相应长度的独热向量
data_y = F.one_hot(data_y)
# print(data_x)
# print(data_y)
2.定义了一个简单的二分类模型BinaryClassificationModel
,包含一个单层感知器(Single Perceptron)结构,其中使用了一个线性层和sigmoid激活函数,用于将输入特征映射到概率空间。
# 定义了一个简单的二分类模型,采用单层感知器的结构,包含一个线性层和sigmoid激活函数,用于将输入特征映射到概率空间。这样的模型可以用来对数据集进行二分类任务的预测。
# 定义了一个名为BinaryClassificationModel的类,其继承自nn.Module类,这意味着这个类是一个PyTorch模型。
class BinaryClassificationModel(nn.Module):
def __init__(self, in_feature):
# 调用了父类nn.Module的构造函数,确保正确初始化模型。
super(BinaryClassificationModel, self).__init__()
"""single perception"""
# 这行代码定义了模型的第一层,是一个线性层(Fully Connected Layer)。in_features参数指定输入特征的数量,out_features指定输出特征的数量,这里设置为2表示二分类问题。bias=True表示该层包含偏置项。
self.layer_1 = nn.Linear(in_features=in_feature, out_features=2, bias=True)
# 定义模型前向传播的方法,即输入数据x通过模型前向计算得到输出。
def forward(self, x):
# 输入数据x首先通过定义的线性层self.layer_1进行线性变换,然后通过F.sigmoid()函数进行激活函数处理。
return F.sigmoid(self.layer_1(x))
3.创建了该二分类模型的实例model
、使用随机梯度下降(SGD)优化器opt
、以及二分类问题常用的损失函数BCELoss(Binary Cross Entropy Loss)。
4.在训练过程中,通过多个epoch和每个样本的批处理(在这里是一次处理一个样本),计算模型预测输出和真实标签之间的损失值,进行反向传播计算梯度,并更新模型参数以最小化损失函数。
# 完成对模型的训练过程,每个epoch中通过优化器进行参数更新,计算损失,反向传播更新梯度。最终我们会得到训练过程中每个epoch的损失值,并可以观察损失的变化情况。
# 创建了一个二分类模型实例model,参数n_feature表示输入特征的数量。
model = BinaryClassificationModel(n_feature)
# 创建了一个随机梯度下降(SGD)优化器opt,用于根据计算出的梯度更新模型参数。
opt = torch.optim.SGD(model.parameters(), lr=learning_rate)
# 创建了一个二分类问题常用的损失函数BCELoss(Binary Cross Entropy Loss),用于衡量模型输出与真实标签之间的差异。
criteria = nn.BCELoss()
for epoch in range(epochs):
# 对每个样本进行训练。
for step in range(n_item):
x = data_x[step]
y = data_y[step]
# 梯度清零,避免梯度累加影响优化结果。
opt.zero_grad()
# 将输入特征x通过模型前向传播得到预测输出y_hat。unsqueeze(0)是因为我们的模型期望输入是(batch_size, n_feature)的形式。
y_hat = model(x.unsqueeze(0))
# 计算预测输出y_hat和真实标签y之间的损失值。
loss = criteria(y_hat, y.unsqueeze(0).float())
# 反向传播计算梯度。
loss.backward()
# 根据计算出的梯度更新模型参数。
opt.step()
print("Epoch: %03d, Loss: %.3f" % (epoch, loss.item()))
5.打印出每个epoch的序号和损失值,用于监控训练过程中损失值的变化情况。