机器学习入门(三)逻辑回归

在上一篇文章 机器学习入门(二)线性回归 中我们介绍了线性回归,这一篇文章将介绍监督学习中的逻辑回归。

线性回归面对分类问题的缺陷

在生活中除了预测房价这种回归问题,还有像判断一封电子邮件是否是垃圾邮件;区别一个肿瘤是恶性的还是良性的的分类问题。这里以判断肿瘤的种类为例,看一下线性回归如何处理该问题。

如上图所示,横轴代表肿瘤的大小,纵轴表示 0.0 表示是良性肿瘤;1.0表示是恶性肿瘤。如果我们使用线性回归,可以让 y < 0.5 时,预测 y = 0;让 y >= 0.5 时,预测 y = 1。对于上图所示的数据,这样的一个线性模型似乎能很好地完成分类任务。

但是如果此时增加一个非常大的恶性肿瘤的数据,这里获取的直线如下。可以看到,在被新数据影响后,本因被判断为恶性肿瘤的点,此时在该条直线中的 y < 0.5,导致分类出现了问题。

从中可以看出线性回归模型,并不适合解决这样分类的问题。

逻辑回归

上面介绍的线性回归模型的缺陷,其原因主要是预测的值可以超越[0,1]的范围。因此我们引入一个新的模型,逻辑回归,该模型的输出变量范围始终在0和1之间。

常用的逻辑回归函数是 sigmond 函数,其函数公式为 <math xmlns="http://www.w3.org/1998/Math/MathML"> σ ( x ) = 1 1 + e − x \sigma(x) = \frac{1}{1 + e^{-x}} </math>σ(x)=1+e−x1,图形为:

需要注意,逻辑回归不是单独使用 sigmond 函数,而是回归函数 + sigmond 函数。在逻辑回归中,会把回归函数的输出(y)作为 sigmond 函数的输入(x)。由于 sigmond 函数:

  • 当 x = 0 时, <math xmlns="http://www.w3.org/1998/Math/MathML"> σ ( x ) = 0.5 \sigma(x) = 0.5 </math>σ(x)=0.5
  • 当 x > 0 时, <math xmlns="http://www.w3.org/1998/Math/MathML"> σ ( x ) > 0.5 \sigma(x) > 0.5 </math>σ(x)>0.5
  • 当 x < 0 时, <math xmlns="http://www.w3.org/1998/Math/MathML"> σ ( x ) < 0.5 \sigma(x) < 0.5 </math>σ(x)<0.5

这样就避免了回归函数预测的值可以超越[0,1]的范围的问题。逻辑回归的效果如下所示:

而且对于数据呈现如下图这样的分布情况,我们只需要找到对应的二次回归曲线,就可以来适应该图形的椭圆边界。

注意:逻辑回归(Logistic Regression)虽然名称中包含"回归"二字,但它实际上是一种分类方法,主要用于二分类问题。

决策边界和代价函数

从上面的示例中,我们知道如果想要提高分类算法的准确率,就必须找到合适的决策边界,比如选择线性边界 y=ax+b 还是非线性边界 ax^2 + by^2 = c;以及决策边界对应的参数 a、b、c的值。

对于决策边界函数的选取,一般先使用线性边界,当数据复杂且线性边界表现不佳时,再通过可视化、降维等方法来找到需要的决策边界。

选择好决策边界函数后,就需要找出最适合的参数,让数据的拟合误差最小。在线性回归中,我们是使用代价函数来实现。逻辑回归中,也是一样的,区别是使用的代价函数是不一样的,具体可以看 逻辑回归算法详解

示例

这里以根据两场考试成绩来预测第三场考试是否及格为例:

假设决策边界是一条直线:

ini 复制代码
# 训练数据
from sklearn.linear_model import LogisticRegression
# 定义数据
x = data.drop(['Pass'], axis = 1)
y = data.loc[:, 'Pass']
# 训练
LR = LogisticRegression()
LR.fit(x, y)
# x1 表示考试一;x2表示考试2
# 他们的边界关系满足 a * x1 + b * x2 + c = 0
x1 = data.loc[:, 'Exam1']
x2 = data.loc[:, 'Exam2']
c = LR.intercept_
a, b = LR.coef_[0][0],  LR.coef_[0][1]
x2_new = -(c + a * x1) / b
fig3 = plt.figure()
plt.plot(x1, x2_new)
passed = plt.scatter(data.loc[:, 'Exam1'][mask], data.loc[:, 'Exam2'][mask])
failed = plt.scatter(data.loc[:, 'Exam1'][~mask], data.loc[:, 'Exam2'][~mask])
plt.title('Exam1-Exam2')
plt.xlabel('Exam1')
plt.ylabel('Exam2')
plt.legend((passed, failed), ('passed', 'failed'))
plt.show()

效果如下所示:

假设决策边界满足 a0 + a1 * x1 + a2 * x2 + a3 * x1 ^ 2 + a4 * x2 ^ 2 + a5 * x1 * x2 = 0

ini 复制代码
# 创建新的数据
x1_2 = x1 * x1
x2_2 = x2 * x2
x1_x2 = x1 * x2
x_new_data = {'x1':x1, 'x2':x2, 'x1_2': x1_2, 'x2_2': x2_2, 'x1_x2': x1_x2}
x_new_data = pd.DataFrame(x_new_data)
# 再次训练模型
LR2 = LogisticRegression()
LR2.fit(x_new_data, y)
# 此时的边界函数满足 a0 + a1 * x1 + a2 * x2 + a3 * x1 ^ 2 + a4 * x2 ^ 2 + a5 * x1 * x2 = 0
a0 = LR2.intercept_
a1, a2, a3, a4, a5 = LR2.coef_[0][0], LR2.coef_[0][1], LR2.coef_[0][2], LR2.coef_[0][3], LR2.coef_[0][4]
x1_sort_data = x1.sort_values()
a = a4
b = a5 * x1_sort_data + a2
c = a0 + a1 * x1_sort_data + a3 * x1_sort_data * x1_sort_data
x2_new_boundary = (-b + np.sqrt(b * b - 4 * a * c)) / (2 * a)
fig4 = plt.figure()
passed = plt.scatter(data.loc[:, 'Exam1'][mask], data.loc[:, 'Exam2'][mask])
failed = plt.scatter(data.loc[:, 'Exam1'][~mask], data.loc[:, 'Exam2'][~mask])
plt.title('Exam1-Exam2')
plt.xlabel('Exam1')
plt.ylabel('Exam2')
plt.legend((passed, failed), ('passed', 'failed'))
plt.plot(x1_sort_data, x2_new_boundary)
plt.show()

效果如下所示:

参考

相关推荐
悲喜自渡7214 分钟前
线性代数(一些别的应该关注的点)
python·线性代数·机器学习
追逐☞1 小时前
机器学习(10)——神经网络
人工智能·神经网络·机器学习
winner88811 小时前
对抗学习:机器学习里的 “零和博弈”,如何实现 “双赢”?
人工智能·机器学习·gan·对抗学习
小墙程序员2 小时前
机器学习入门(四)决策树
机器学习
神经星星3 小时前
【TVM教程】在 Arduino 上为 microTVM 训练视觉模型
人工智能·机器学习·编程语言
归去_来兮5 小时前
Bagging、Boosting、Stacking的原理
机器学习·数据分析·集成学习
pljnb5 小时前
SVM(支持向量机)
人工智能·机器学习·支持向量机
weixin_430750936 小时前
智能小助手部署 Win10 + ollama的Deepseek + CentOS+ maxKB
linux·人工智能·机器学习·语言模型·自然语言处理·centos
AI_RSER7 小时前
基于 Google Earth Engine 的南京江宁区土地利用分类(K-Means 聚类)
算法·机器学习·分类·kmeans·聚类·遥感·gee