[Day 9] 逻辑回归 (Logistic Regression)

逻辑回归 (Logistic Regression)

今日学习目标

  • 认识逻辑回归
    • 线性分类器
    • 逻辑回归学习机制
    • 比较线性回归与逻辑回归
    • 多元分类逻辑回归
  • 逻辑回归程序手把手
    • 使用逻辑回归建立鸢尾花朵分类器

认识逻辑回归

逻辑回归 (Logistic regression) 是由线性回归变化而来的,它是一种分类的模型。其目标是要找出一条直线能够将所有数据清楚地分开并做分类,我们又可以称回归的线性分类器。逻辑回归其实是在说明一个机率的意义,透过一个 function 去训练得到的一组参数,不同的 w,b 就会得到不同的 function。於是我们可以说 fw,b(x) 即为 posteriror probability。

https://ithelp.ithome.com.tw/upload/images/20210921/20107247E3C5jCk2JX.png

线性回归与逻辑回归

逻辑回归是用来处理分类问题,目标是找到一条直线可以将资料做分类。主要是利用 sigmoid function 将输出转换成 0~1 的值,表示可能为这个类别的机率值。而线性回归是用来预测一个连续的值,目标是想找一条直线可以逼近真实的资料。

https://ithelp.ithome.com.tw/upload/images/20210921/20107247bAuvC938XZ.png

逻辑回归学习机制

逻辑回归是一个最基本的二元线性分类器。我们要找一个机率 (posterior probability) 当机率 P(C1|x) 大於 0.5 时则输出预测 Class 1,反之机率小於 0.5 则输出 Class 2。如果我们假设资料是 Gaussian 机率分布,我们可以说这个 posterior probability 就是 σ(z)。其中 z=w*x+b,x 为输入特徵,而 w 与 b 分别为权重(weight)与偏权值(bias) 他们是透过训练得到的一组参数。

https://ithelp.ithome.com.tw/upload/images/20210921/20107247BseW6cMxQh.png

以下就是一个逻辑回归的运作机制,如果以图像化表示会长这样。我们的 function 会有两组参数,一组是 w 我们称为 weight,另一个常数 b 称为 bias。假设我们有两个输入特徵,并将这两个输入分别乘上 w 再加上 b 就可以得到 z,然後通过一个 sigmoid function 得到的输出就是 posterior probability。

https://ithelp.ithome.com.tw/upload/images/20210921/20107247JkzWcebAcY.png

在逻辑回归中我们定义的损失函数是要去最小化的对象是所有训练资料 cross entropy 的总和。我们希望模型的输出要跟目标答案要越接近越好。因此我们可以将最小化的目标写成一个函数:

https://ithelp.ithome.com.tw/upload/images/20210921/201072470uiafS0F57.png

最後是寻找一组最好的参数,使得 loss 能够最低。因此这里采用梯度下降 (Gradient Descent) 来最小化交叉熵 (Cross Entropy)。我们将损失函数对权重求偏导後,可以得到下面的权重更新的式子:

https://ithelp.ithome.com.tw/upload/images/20210921/20107247WMtDBj3we7.png

多元分类逻辑回归 (Multinomial Logistic Regression)

在 Sklearn 中也能使用逻辑回归分类器应用在多类别的分类问题上,对於多元逻辑回归有 one-vs-rest(OvR) 和 many-vs-many(MvM) 两种方法。两者的做法都是将所有类别的资料依序作二元分类训练。MvM 相较於 OvR 比较精准,但 liblinear 只支援 OvR。

  • one-vs-rest(OvR): 训练时把某个类别的资料归为一类,其他剩余的资料归为另一类做逻辑回归,因此若有 k 个类别的资料会有 k 个二元分类器。假如有三个类别 A、B、C,首先抽取 A 类别的资料做为正集,B、C 类别资料做为负集; B 类别的资料作为正集,A、C 类别类别资料做为负集; C 类别的资料作为正集,A、B 类别类别资料做为负集。透过这三组训练集分别进行训练,然後的得到三个分类器 f1(x)、f2(x)、f3(x)。预测的时候就是把资料丢进三个分类器,查看哪个分类器预测的分数最高就决定该类别。
  • many-vs-many(MvM): 与 OvR 差别在於训练时每次只会挑两个类别训练一个分类器,因此 k 个类别的资料就需要 k(k-1)/2 个二元分类器。假如有三个类别 A、B、C,因此我们会有三组二元分类器分别有 (A、B)、(A、C) 与 (B、C)。训练完成後当有新资料要预测时,把资料分别对三个二元分类器进行预测,最终多数决的方式得到预测结果。

[程序实作]

逻辑回归 (分类器)

逻辑回归虽然有回归两字但他其实是被用来做分类的,目的是要找出一条直线能够将两个类别分开。本范例采用鸢尾花朵资料集做分类器实验,希望能够透过线性分类器将三个类别彼此区隔开。

Parameters:

  • penalty: 正规化l1/l2,防止模型过度拟合。
  • C: 数值越大对 weight 的控制力越弱,预设为1。
  • n_init: 预设为10次随机初始化,选择效果最好的一种来作为模型。
  • solver: 优化器的选择。newton-cg,lbfgs,liblinear,sag,saga。预设为liblinear。
  • multi_class: 选择分类方式,ovr就是one-vs-rest(OvR),而multinomial就是many-vs-many(MvM)。预设为 auto,故模型训练中会取一个最好的结果。
  • max_iter: 迭代次数,预设为100代。
  • class_weight: 若遇资料不平衡问题可以设定balance,预设=None。
  • random_state: 乱数种子仅在solver=sag/liblinear时有用。

Attributes:

  • coef_: 取得斜率。
  • intercept_: 取得截距。

Methods:

  • fit: 放入X、y进行模型拟合。
  • predict: 预测并回传预测类别。
  • predict_proba: 预测每个类别的机率值。
  • score: 预测成功的比例。
from sklearn.linear_model import LogisticRegression

# 建立Logistic模型
logisticModel = LogisticRegression(random_state=0)
# 使用训练资料训练模型
logisticModel.fit(X_train, y_train)
# 使用训练资料预测分类
predicted = logisticModel.predict(X_train)

使用Score评估模型

我们可以直接呼叫 score() 直接计算模型预测的准确率。

# 预测成功的比例
print('训练集: ',logisticModel.score(X_train,y_train))
print('测试集: ',logisticModel.score(X_test,y_test))

输出结果:

训练集:  0.9714285714285714
测试集:  0.9333333333333333

透过 Sklearn 的 LogisticRegression 可以实作一个典型的二元分类器。不过当有多个类别的时候,我们可以透过参数 multi_class 来设定多元分类器的学习机制。我们可以观察一下训练好的模型在测试集上的预测能力,为了方便观察训练结果,因此我们只挑选其中两个特徵并绘制平面的点散图。下图中左边的是测试集的真实分类,右边的是模型预测的分类结果。

https://ithelp.ithome.com.tw/upload/images/20210921/20107247Y93CgKQqBg.png

本系列教学内容及范例程序都可以从我的 GitHub 取得!


<<:  [Day07]程序菜鸟自学C++资料结构演算法 – 链结串列实作应用

>>:  【Day 6】Google Apps Script - 触发条件与简单触发器(Simple Triggers)

ESP32_DAY5 来新建一个专案吧!

程序架构 昨天只有介绍到Arduino的程序架构可以分为两大函式: setup()及loop()。 ...

Firebase来帮忙登入画面 Day 11

因为昨天安装了Firebase的资料库,那麽今天就来使用Firebase实作登入画面的操作 在Fir...

用 Python 畅玩 Line bot - 19:加入与移除好友

当加入一个 line bot 的时候,通常 bot 会传送一个欢迎讯息给使用者,而此设定除了可以透过...

[Day 27] Bevy 游戏引擎 (Part 1)

昨天大概讲完 Rocket 的运用了 所以接下来就来介绍其他东西吧 这次要讲的是 Game Engi...

C# object sender

以下 是在写 win form 常常看到的 Btn事件 private void button1_C...