(课程笔记)深度学习入门 - 6 - Logistic Regression

开篇:Logistics回归的背景

        Logistic回归是一种用于二分类问题的统计学习方法。它通过将输入特征与一个逻辑函数(也称为sigmoid函数,在这里充当激活函数的作用,激活函数有什么用详见第1篇博客)进行组合,得到一个概率估计模型,用来预测具体样本属于某个类别的概率。

        需要注意的是:Logistics回归虽然带有回归二字,但实际上是解决分类问题的。

        另外:虽然我们要求的是概率估计模型,但实际上我们并不需要知道概率值具体是多少,只要能够得到哪个模型对应的概率大就可以了。

        Logistic回归的特点包括:

  1. 线性决策边界:Logistic回归基于线性模型,因此它所建立的决策边界是线性的。

  2. 输出概率:相对于其他分类方法,Logistic回归可以输出样本属于某个类别的概率值,而不仅仅是简单的分类结果。

  3. 参数可解释性强:Logistic回归通过计算权重参数,可以解释每个特征对分类结果的贡献程度,从而提供了一定的可解释性。

  4. 对异常值不敏感:相对于其他分类算法(如支持向量机),Logistic回归对异常值的影响相对较小,鲁棒性较好。

一、Pytorch实现Logistics回归模型

1、MNIST数据集

        MNIST数据集的模样长这个样子:

         它包含了60000多个训练样本,10000多个测试样本,用于训练模型将给出的元素正确分类到0~9这十个数字类中的某一个,具体要做的就是看这个样本属于哪一个数字类的概率最大。

2、回归与分类的区别

        回归表达的意思如下图所示:

        (StudyHours,Points)=(1,2),(2,4),(3,6)

        问(4,?)中的?是多少

         分类表达的意思如下图所示:

        (StudyHours,Pass/Fail)=(1,Fail),(2,Fail),(3,Pass)

        问(4,?),(2.8,?)中的?是Pass还是Fail

 3、采取的激活函数

        当线性回归模型 y = wx + b 经过一个激活函数后,可以将其映射到 [0, 1] 的区间内,那么采取哪一个激活函数进行非线性变换呢,这里Logistics回归中,我们采取的是Sigmoid激活函数,如下图所示:

         这样我们就可以在线性层输出线性数据的时候,添加Sigmoid激活函数模块,让其映射到0~1的闭区间上,实现线性到非线性的变换,以拟合更多实际情况,提高模型的拟合能力(这也是激活函数的作用之一)。

4、线性模型的修改

        由于需要在线性层输出后,采取Sigmoid函数进行非线性激活,所以以前的线性模型需要修改。以前的线性模型为:

y_{pred}=wx+b

        而Logistics回归的模型为:

y_{pred}=sigmoid(wx+b)

sigmoid(x)=\frac{1}{1+e^{-x}}

5、损失函数模型的修改

        以前的线性模型损失函数为:

Loss=(y_{pred}-y_{label})^{2}=(wx-y_{label})^{2}

        而Logistics回归的损失函数为:

Loss=-(y_{label}log(y_{pred})+(1-y_{label})log(1-y_{pred}))

        简化表示就是:

Loss=-(ylog \hat{y}+(1-y)log(1-\hat{y}))

        这个损失函数模型在torch中其实就是BCELoss函数,即:

                BCELoss = -[y * log(p) + (1 - y) * log(1 - p)]

6、代码实现

6.0、导入必要的包

import torch
import torch.nn.functional as F
import numpy as np
import matplotlib.pyplot as plt

        其中,torch.nn.functional的意思是:

        该模块提供了一系列神经网络操作函数的实现,例如卷积、池化、归一化等,还包括许多非线性激活函数,如ReLU、sigmoid、tanh等。这些函数可以通过导入functional包来方便地使用。

6.1、数据集准备

# 步骤1:创建数据集

x_data_set = torch.tensor([[1.0], [2.0], [3.0]])
y_data_set = torch.tensor([[0.0], [0.0], [1.0]])

        数据集的准备没有大变更,也就是把 y 的标签值更改为0和1这样的二进制数,用于二分类。

6.2、创建Logistics回归模型

# 定义Linear模型类,继承至torch.nn.Module类
class LinearModel(torch.nn.Module):  
 
    def __init__(self):

        super(LinearModel, self).__init__()  
        self.linear = torch.nn.Linear(1, 1)  
 
 
    # 前馈模型,用于输出预测值,即 y_pred = sigmoid(wx + b) = σ(wx + b)
    # 此处调用了F模块中的sigmoid函数用于激活线性层输出
    def forward(self, x):
        y_predict_value = F.sigmoid(self.linear(x))  
        return y_predict_value
 

# 完成模型的定义后,创建实例化对象model
model = LinearModel()

        模型定义只需要修改forward前馈模型中的y_pred即可,让它通过Sigmoid函数映射到0~1上。

6.3、创建损失函数与优化器

# 步骤3:定义损失函数,可以求平均loss,采用SGD方法优化
# BCELoss(Binary Cross Entropy Loss)是一种二分类问题常用的损失函数。
# 它通常用于训练模型,使其能够输出一个介于0和1之间的概率值,表示样本属于正类的概率。
# BCELoss = -[y * log(p) + (1 - y) * log(1 - p)]
# 对于多分类问题,可以使用交叉熵损失函数(Cross-Entropy Loss)的扩展版本。

BCE_loss = torch.nn.BCELoss(size_average=True)
optim_SGD = torch.optim.SGD(model.parameters(), lr=0.03)

        将MSELoss损失模型更改为了BCELoss损失模型。

        什么是BCELoss损失模型?

        BCELoss(Binary Cross Entropy Loss)是一种二分类问题常用的损失函数。它通常用于训练模型,使其能够输出一个介于0和1之间的概率值,表示样本属于正类的概率。

        BCELoss的定义如下:

        BCELoss = -[y * log(p) + (1 - y) * log(1 - p)]

        其中,y 是真实的标签(0或1),p 是模型预测的概率值(范围在0和1之间)。这个损失函数通过比较真实的标签和模型的预测值,计算出模型的误差。当 y=1 时,对应的第一项 -y * log(p) 贡献较大;当 y=0 时,对应的第二项 -(1 - y) * log(1 - p) 贡献较大。通过最小化这个损失函数,可以使模型更准确地拟合训练数据。

        BCELoss常用于二分类问题,例如判断邮件是否为垃圾邮件、图像是否包含某个目标等。对于多分类问题,可以使用交叉熵损失函数(Cross-Entropy Loss)的扩展版本。

6.4、开始训练

# 步骤4:开始训练,前馈 - 反馈 - 更新

epochs = 2000

for epoch in range(epochs):
    # 计算前馈输出y_pred
    y_predict_value = model(x_data_set)  

    # 用y_pred和y_label计算Loss
    loss = BCE_loss(y_predict_value, y_data_set)  
    print(f"当前迭代{epoch}次,损失值为{loss.item() / len(x_data_set) :.5f}")

    optim_SGD.zero_grad()  # 清空梯度信息
    loss.backward()  # 使用反馈自动求导求得新的梯度信息 - loss对w和b的偏导值
    optim_SGD.step()  # 更新权重指令
print("======测试开始======")
x_test_1 = torch.tensor([[2.8]])  # 此处可以测试学习2.8小时,通过考试的概率p(n)
y_test_1 = model(x_test_1)
print(f"当x为{x_test_1.item():.3f}时,输出y的预测值为{y_test_1.item():.5f}")


x_test_2 = torch.tensor([[4.0]])  # 此处可以测试学习4小时,通过考试的概率p(n)
y_test_2 = model(x_test_2)
print(f"当x为{x_test_2.item():.3f}时,输出y的预测值为{y_test_2.item():.5f}")
# 一维向量,这里相当于创建x轴是学习时间0~10小时,创建200个时间坐标点
x = np.linspace(0, 10, 200)  

# 把它变成二维矩阵张量,用于计算y的预测值(张量形式)
x_test_plt = torch.tensor(x, dtype=torch.float32).view((200, 1))

# 根据上面训练好的模型,来计算通过考试的概率,类型是二维矩阵张量形式
y_test_plt = model(x_test_plt)  

# 将y_test转化为一维向量,用于绘图
y = y_test_plt.data.numpy()  

plt.plot(x, y)

plt.xlabel("Study Hours")
plt.ylabel("Probability of Passing Exam")

# 绘制一条直线,始末点为(0, 0.8)  (10, 0.8),颜色red,用于标识大概率通过考试的底线
plt.plot([0, 10], [0.8, 0.8], c='r')  

plt.grid()
plt.show()

6.5、结论记录

当前迭代0次,损失值为0.26183
当前迭代1次,损失值为0.25990
当前迭代2次,损失值为0.25809
当前迭代3次,损失值为0.25639
当前迭代4次,损失值为0.25481
当前迭代5次,损失值为0.25332
当前迭代6次,损失值为0.25193
当前迭代7次,损失值为0.25063
当前迭代8次,损失值为0.24941
当前迭代9次,损失值为0.24827
当前迭代10次,损失值为0.24719
当前迭代11次,损失值为0.24619
当前迭代12次,损失值为0.24524
当前迭代13次,损失值为0.24435
当前迭代14次,损失值为0.24350
当前迭代15次,损失值为0.24271
当前迭代16次,损失值为0.24196
当前迭代17次,损失值为0.24126
当前迭代18次,损失值为0.24058
当前迭代19次,损失值为0.23995
当前迭代20次,损失值为0.23935
当前迭代21次,损失值为0.23877
当前迭代22次,损失值为0.23823
当前迭代23次,损失值为0.23770
当前迭代24次,损失值为0.23721
当前迭代25次,损失值为0.23673
当前迭代26次,损失值为0.23627
当前迭代27次,损失值为0.23583
当前迭代28次,损失值为0.23541
当前迭代29次,损失值为0.23500
当前迭代30次,损失值为0.23461
当前迭代31次,损失值为0.23423
当前迭代32次,损失值为0.23386
当前迭代33次,损失值为0.23351
当前迭代34次,损失值为0.23316
当前迭代35次,损失值为0.23282
当前迭代36次,损失值为0.23249
当前迭代37次,损失值为0.23217
当前迭代38次,损失值为0.23186
当前迭代39次,损失值为0.23155

......

......

当前迭代1975次,损失值为0.08342
当前迭代1976次,损失值为0.08340
当前迭代1977次,损失值为0.08338
当前迭代1978次,损失值为0.08335
当前迭代1979次,损失值为0.08333
当前迭代1980次,损失值为0.08331
当前迭代1981次,损失值为0.08328
当前迭代1982次,损失值为0.08326
当前迭代1983次,损失值为0.08324
当前迭代1984次,损失值为0.08321
当前迭代1985次,损失值为0.08319
当前迭代1986次,损失值为0.08317
当前迭代1987次,损失值为0.08314
当前迭代1988次,损失值为0.08312
当前迭代1989次,损失值为0.08310
当前迭代1990次,损失值为0.08307
当前迭代1991次,损失值为0.08305
当前迭代1992次,损失值为0.08303
当前迭代1993次,损失值为0.08300
当前迭代1994次,损失值为0.08298
当前迭代1995次,损失值为0.08296
当前迭代1996次,损失值为0.08293
当前迭代1997次,损失值为0.08291
当前迭代1998次,损失值为0.08289
当前迭代1999次,损失值为0.08286


======测试开始======
当x为2.800时,输出y的预测值为0.67109
当x为4.000时,输出y的预测值为0.94919

二、注意事项

        【  GPT解析  】

        在训练逻辑回归(Logistic Regression)模型时,有几个重要的细节和注意事项需要考虑:

  1. 数据预处理:确保数据的质量和一致性,包括处理缺失值、异常值和离群点等。同时,进行特征工程,选择合适的特征,进行特征缩放等操作。

  2. 数据集划分:将数据集划分为训练集和测试集,一般采用交叉验证或留出法来评估模型性能。确保测试集和训练集的样本分布和特征分布相似。

  3. 损失函数选择:逻辑回归一般使用二分类问题中的对数损失函数(Log Loss),即二项交叉熵损失函数(Binary Cross-Entropy Loss)。该损失函数能够度量实际标签和模型预测之间的差异,并用于模型的参数更新。

  4. 参数优化算法:常用的优化算法包括梯度下降(Gradient Descent)及其变种,如批量梯度下降(Batch Gradient Descent)、随机梯度下降(Stochastic Gradient Descent)和小批量梯度下降(Mini-Batch Gradient Descent)。选择合适的学习率和迭代次数,以确保模型收敛或达到最优点。

  5. 正则化:为了避免过拟合,可以在损失函数中加入正则化项,如L1正则化和L2正则化。这有助于控制模型的复杂度并减小参数的影响,增强模型的泛化能力。

  6. 模型评估与监控:使用适当的指标对模型进行评估,例如准确率(Accuracy)、精确率(Precision)、召回率(Recall)、F1分数(F1-Score)等。定期监控模型的表现,并根据需要进行调整和改进。

  7. 特征选择和交互效应:通过特征选择和特征组合来提高模型性能。可以使用相关性分析、信息增益等方法选择重要的特征,还可以考虑引入特征的多项式和交互项。

  8. 处理类别不平衡问题:如果数据集存在类别不平衡情况,即某个类别的样本数量较少,可以考虑采用欠采样、过采样或类别加权等方法来处理。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值