National Central University
Uedu Main Site
Explore Uedu
Student Console
Register as Member/Login
Research Informed Consent Center
Survey Center
Educational Big Data Challenge
Claim or create a course
Try an AI Scenario Task
Support & Messages
Uptime Data

UeduGPTs

--

Jupyters

3

Local AI

--

Uedu Code

--

中央大學 AQI 80 24°C PM2.5 21
AI Reply Desktop Notifications

Show a desktop notification when the AI TA finishes replying

Chat Message Notifications

Notify me when classmates post messages in the forum

Sound notification

Play an alert sound whenever there is a new notification

Unit 07

羅吉斯迴歸

用 numpy 寫:機率、交叉熵與決策邊界
Interaction實作 30 minute(s)

Learning Objectives

  • 用 numpy 寫出羅吉斯迴歸:sigmoid、交叉熵、梯度下降
  • 說明為什麼分類用交叉熵,以及決策邊界在哪裡
  • 對照 scikit-learn 的 LogisticRegression,說明它預設有 L2 正則化,C 越小越強
  • 讀懂預測機率與係數,並把準確率和基準比較

要預測的是「會不會」

前幾課預測的是分數,答案可以是任何數字。很多問題的答案只有兩種:及格或不及格、是垃圾訊息或不是。這叫二元分類(binary classification),答案寫成 1 與 0。

直接用線性迴歸行不行?線性模型的輸出 w·x + b 可以是任何數字,可能算出 1.7 或 −0.3,這兩個數字當作「及格的機率」都沒有意義。

羅吉斯迴歸(logistic regression)的做法是:線性模型照算,再多一步,把結果壓到 0 到 1 之間,當作機率。名字裡有「迴歸」,但它做的是分類。

z = w·x + b            (和線性迴歸一樣)
p = 1 / (1 + e⁻ᶻ)       (sigmoid 函數,把 z 壓到 0 到 1)

這一課和第 3、4 課的路線相同:先用 numpy 從頭寫,再對照 scikit-learn。

逐步看:sigmoid 與交叉熵

前半段看 sigmoid 把 z 壓到哪裡;後半段看「答案是 1,模型卻給了各種機率」時,兩種損失各是多少。

分類為什麼用交叉熵

訓練模型要有一個損失函數。分類常用交叉熵,整份資料取平均:

損失 = −平均( y × log(p) + (1 − y) × log(1 − p) )

式子看起來長,其實只有一半會作用:y = 1 時只剩 −log(p),y = 0 時只剩 −log(1 − p)。兩種情況都是「給正確答案的機率越低,損失越大」,而且越接近 0 增加得越快。

配上 sigmoid 時,交叉熵還有一個好處:它的梯度形式很簡單,和線性迴歸幾乎一樣(第 4 課是「誤差 × 特徵」):

對 w 的梯度 = 平均( (p − y) × x )
對 b 的梯度 = 平均( p − y )

p − y 就是這筆資料猜錯多少,也決定往哪個方向修正。下面就用這兩行做梯度下降。

逐步看:用 numpy 訓練

八筆資料、兩個特徵(已標準化),走 8 輪梯度下降。注意每一輪的 loss 怎麼下降,以及 p 怎麼往 y 靠近。

決策邊界在哪裡

什麼時候機率剛好是 0.5?sigmoid 在 z = 0 時是 0.5,所以就是

w1 × x1 + w2 × x2 + b = 0

這條線的一邊預測 1、另一邊預測 0,叫決策邊界(decision boundary)。把它改寫成畫圖用的形式:

x2 = −(w1 × x1 + b) / w2

羅吉斯迴歸的決策邊界是一條直線(特徵更多時是平面)。雖然 sigmoid 是曲線,但分界的位置是由線性的 z 決定的。資料如果是一個類別被另一個類別包圍,直線分不開,要加特徵(第 6 課的多項式特徵)或換模型(第 9、11 課)。

互動練習:直線分得開嗎?

實心是訓練資料、空心是測試資料,背景顏色是模型的預測。這裡的羅吉斯迴歸和上面用 numpy 寫的一樣,用梯度下降訓練、沒有正則化。

和 scikit-learn 有什麼不同

接下來用 scikit-learn 對照。LogisticRegression 和我們寫的不完全一樣:它預設有 L2 正則化。

我們寫的 LogisticRegression()
正則化 沒有 預設 penalty='l2',和第 6 課的 Ridge 同一種懲罰
強度 C=1.0,C 是強度的倒數:C 越小,懲罰越強(和 alpha 方向相反)
解法 梯度下降 預設 solver='lbfgs',比單純的梯度下降快得多,max_iter=100

因為有懲罰,它和第 6 課一樣受特徵尺度影響,通常要先標準化。

逐步看:和 scikit-learn 對照

30 筆模擬資料(亂數產生)。先用 numpy 走 20 輪,再用三種 C 訓練 LogisticRegression。C = 1000000 時懲罰幾乎等於沒有,應該要和 numpy 的結果接近。

逐步看:預測是否及格

用 students.csv(程式產生的模擬資料,不是任何學校的真實資料),四個特徵預測是否及格。流程和第 5 課相同,看準確率時別忘了和基準比。

機率與係數怎麼讀

係數不是「機率增加多少」。 上面小考的係數是 0.955(已標準化),正確的讀法是:

在這份資料裡,其他特徵固定時,小考多一個標準差,z 增加 0.955。

z 又叫對數勝算(log-odds),它和機率的關係不是直線:同樣增加 0.955,從 z = 0 開始,機率從 0.5 升到約 0.72;從 z = 4 開始,機率只從 0.98 升到約 0.99。正負號可以看方向,大小要換算才知道機率差多少。 和第 5 課一樣,這是關聯,不是因果,而且會隨放進去的特徵改變。

準確率不夠用的時候。 這份資料約 77% 及格,所以全猜及格就有 0.768。如果只有 5% 的同學不及格,全猜及格的準確率高達 0.95,卻一個需要幫助的同學都找不到。第 13 課的混淆矩陣、精確率與召回率就是要解決這個問題。

多於兩個類別。 LogisticRegression 也可以直接處理三個以上的類別,用法相同,predict_proba 每列會有對應數量的機率。

實作:寫出一步梯度下降

sigmoid 已經寫好了。完成 cross_entropy(y, p)(平均交叉熵)與 train_step(X, y, w, b, lr)(走一步,回傳新的 w 與 b)。完成後,損失應該一輪比一輪小。

你的輸出
預期輸出

小測驗:機率與損失

1.

下面程式會印出什麼?

import numpy as np
z = np.array([-1.0, 0.0, 1.0])
print((1 / (1 + np.exp(-z))).round(2))
2.

一筆資料的答案是 0,模型算出 p = 0.99。和答案是 1、p = 0.99 比起來,交叉熵會?

3.

一個訓練好的模型 w = [1, 2]、b = −3,點 (1, 1) 在哪裡?

第 1 次作答

小測驗:使用 LogisticRegression

1.

關於 LogisticRegression() 的預設值,下面哪一個正確?

2.

測試準確率 0.828,測試資料裡有 76.8% 的同學及格。最恰當的解讀是?

3.

標準化後,小考的係數是 0.955。正確的讀法是?

第 1 次作答

重點整理

  • 羅吉斯迴歸:線性組合 z = w·x + b,再經過 sigmoid 變成機率。名字有迴歸,做的是分類。
  • 損失用交叉熵:給正確答案的機率越低,損失越大,很有信心卻答錯時懲罰很重。梯度是平均( (p − y) × x )。
  • 機率 0.5 的地方就是決策邊界,也就是 w·x + b = 0,是一條直線(或平面)。
  • LogisticRegression 預設有 L2 正則化(C=1.0,C 越小越強),所以要先標準化;C 很大時才接近我們用 numpy 寫的沒有正則化版本。
  • 準確率要和全猜最多的類別比;係數是對數勝算,看得出方向,大小要換算才知道機率差多少。
  • 下一課的 k 近鄰完全不學係數:直接找最像的幾筆資料來投票。
這一課完成了!
Next lesson:k 近鄰
你目前沒有登入,學習進度只存在這個瀏覽器。 Login 後,進度會跟著帳號,換電腦也看得到。