iT邦幫忙

6

【用sklearn學習機器學習】快速學會套用sklearn模組,分類方法總覽-決策樹、隨機森林、SVM、KNN、羅吉斯回歸,學會看預測結果

sklearn是一個好用的機器學習套件,
可以讓我們用短短的程式碼就實作機器學習算法,
讓我們能夠快速上手,
本文主要談論如何使用sklearn套件,
讓讀者快速上手,
不探究如何調整參數等細節

這邊為了避免因版本不同導致程式碼可能有差異,
附上版本資訊:
scikei-learn版本: 0.20.1

主題- 分類

本篇的主題是分類,
讓機器看到一堆資料將資料分到正確的類別,
常聽到的例子是教機器分辨狗和貓的照片

用sklearn寫程式碼,
步驟上大致可以簡化為:
「讀取資料」->「將資料分成訓練集(training data)和測試集(testing data)」->
「呼叫sklearn的分類方法開始訓練分類模型」->「用訓練好的模型預測分類結果」

第一步:取得資料

那一開始該如何獲取資料呢?
如果剛學習要自己收集資料也太花時間,
我們可以直接用sklearn的內建資料,
著名的例子是sklearn的load_iris

from sklearn.datasets import load_iris
iris = load_iris()
x_data, y_data = iris['data'], iris['target']
target_names = iris['target_names']
print(x_data)
print(y_data)
print(target_names)

iris是鳶尾花資料,共150筆資料,
x_data是150*4的二維陣列,
其中每一筆資料表示「花萼長度、花萼寬度、花瓣長度、花瓣寬度」(單位: 公分)

y_data表示每筆資料對應的花的種類,有Setosa,Versicolor和Virginica三個品種
(可參考[資料分析&機器學習] 第2.1講: 如何獲取資料? Sklearn內建資料集)

target_names就是把三種花的類別名稱取出來,即['setosa' 'versicolor' 'virginica']
在第四步顯示結果時會用到

第二步:將資料分成訓練集(training data)和測試集(testing data)

將資料分成訓練集(training data)和測試集(testing data),
就好比說讓學生看一系列的題庫(訓練集),
在給學生考試(測試集),檢測學生是否懂了

對應到機器學習就是我們會將一部分的資料訓練機器,
再用測試資料檢測機器分類的結果是否良好

我們會直接呼叫sklearntrain_test_split函式
(若是較舊的版本可能要寫from sklearn.cross_validation import train_test_split)

from sklearn.model_selection import train_test_split
# from sklearn.cross_validation import train_test_split # for較舊的版本
x_train, x_test, y_train, y_test = train_test_split(x_data, y_data, test_size=0.2, random_state=41)

train_test_split的參數涵義:

x_data: 鳶尾花的特徵資料
y_data: 鳶尾花的類別
test_size = 0.2 : 表示有80%的資料用來訓練,20%的資料結果測試
random_state: 隨機種子,設一樣的話資料分割的結果就一樣

以本例來說,鳶尾花資料共150筆,取20%的資料結果測試表示

  • 訓練資料共120筆
  • 測試資料共30筆

第三步:呼叫sklearn的分類方法開始訓練分類模型

sklearn有許多分類方法可以套用,
待會在慢慢介紹,
選好分類方法後,程式碼都類似,
比如說你可以選「決策樹分類法」做分類

from sklearn.tree import DecisionTreeClassifier
model = DecisionTreeClassifier() #選擇一種分類算法
model.fit(x_train,y_train)  #用訓練資料訓練分類器
predictions = model.predict(x_test) #用分類器對測試資料做分類

又比如說你想用「SVM」方法分類,
就改成

from sklearn.svm import SVC
model = SVC()               #選擇一種分類算法
model.fit(x_train,y_train)  #用訓練資料訓練分類器
predictions = model.predict(x_test) #用分類器對測試資料做分類

訓練預測的方法都清一色是model.fit(x_train,y_train)model.predict(x_test)

第四步:用訓練好的模型預測分類結果

主要看confusion_matrixclassification_report兩個

from sklearn.metrics import classification_report, confusion_matrix
print(confusion_matrix(y_test,predictions))
print(classification_report(y_test,predictions, target_names = target_names))

舉例來說,這邊我印出

[[ 9  0  0]
 [ 0 10  1]
 [ 0  2  8]]
              precision    recall  f1-score   support

      setosa       1.00      1.00      1.00         9
  versicolor       0.83      0.91      0.87        11
   virginica       0.89      0.80      0.84        10

   micro avg       0.90      0.90      0.90        30
   macro avg       0.91      0.90      0.90        30
weighted avg       0.90      0.90      0.90        30

理解confusion_matrix

confusion_matrix以矩陣表示分類結果,
橫看是「真實資料」、直看是「預測結果」
比如說

[[ 9  0  0]
 [ 0 10  1]
 [ 0  2  8]]

(花的種類有Setosa,Versicolor和Virginica三個品種)

  • 真實資料是Setosa、分類器也分類到Setosa的資料有9筆
  • 真實資料是Versicolor、分類器也分類到Versicolor的資料有10筆
  • 真實資料是Versicolor、分類器也分類到Virginica的資料有1筆
  • 真實資料是Virginica、分類器也分類到Versicolor的資料有2筆
  • 真實資料是Virginica、分類器也分類到Virginica的資料有8筆

矩陣的主對角線即是分類正確的資料

理解precision, recall, f1-score

再來讀classification_report,這是什麼意思呢?

              precision    recall  f1-score   support

      setosa       1.00      1.00      1.00         9
  versicolor       0.83      0.91      0.87        11
   virginica       0.89      0.80      0.84        10

   micro avg       0.90      0.90      0.90        30
   macro avg       0.91      0.90      0.90        30
weighted avg       0.90      0.90      0.90        30

看分類結果好不好有兩個指標,precision和recall,

  • precision是以預測結果出發,在機器說「你的分類是x類」時,說對的比率有多少
  • recall又稱召回率,看「真實資料是x類」,機器真的把它分到x類的比率

比方說看 versicolor 品種的花,

(看直向資料)
有12筆資料被機器判定為versicolor 品種,
10筆真的是versicolor、其它2筆判斷錯,
因此versicolor的precision = 10/12 = 0.83

(看橫向資料)
真實資料有11筆資料是versicolor 品種,
有10筆資料分為Versicolor、1筆資料分錯,
因此versicolor的recall = 11/12 = 0.91

f1-score是precision和recall的調和平均
公式為2*precision*recall/(precision+recall)
譬如說versicolor的f1-score = 2*0.83*0.91/(0.83+0.91)=0.87

至於表格下面的micro avg, macro avg, weighted avg 我也不確定是什麼…

precision與recall的取捨

那怎麼知道要用哪一個指標呢?
當然我們希望precision與recall都愈高愈好,
但是有時候無法兼顧的情形下就看需求

譬如說用機器學習看數據判斷銀行的「詐欺案」與「不是詐欺案」,
(分兩類的問題: 是「詐欺」類別,或者不是)

「詐欺」分類的precision高表示: 如果機器說你是詐欺,就高機率真的是詐欺(不會冤枉人,但有可能詐欺案發生但沒抓到)
「詐欺」分類的recall高表示: 如果真的發生詐欺案,機器抓出來的比率高(但有可能沒有詐欺也會被冤枉詐欺)

需求判斷:

  1. 如果銀行希望不要冤枉人,必須非常確定「詐欺」發生才抓,那就希望precision高
  2. 如果銀行認為每次發生「詐欺案」會造成銀行的巨大損失,寧錯抓也不縱放,就希望recall高

如果希望兼顧的話,就看f1-score吧

完整程式碼範例

# 第一步:取得資料
from sklearn.datasets import load_iris
iris = load_iris()
x_data, y_data = iris['data'], iris['target']
target_names = iris['target_names']

# 第二步:將資料分成訓練集(training data)和測試集(testing data)
from sklearn.model_selection import train_test_split
# from sklearn.cross_validation import train_test_split # for較舊的版本
x_train, x_test, y_train, y_test = train_test_split(x_data, y_data, test_size=0.2, random_state=41)

# 第三步:呼叫sklearn的分類方法開始訓練分類模型
from sklearn.tree import DecisionTreeClassifier
model = DecisionTreeClassifier() #選擇一種分類算法
model.fit(x_train,y_train)  #用訓練資料訓練分類器
predictions = model.predict(x_test) #用分類器對測試資料做分類

# 第四步:用訓練好的模型預測分類結果
from sklearn.metrics import classification_report, confusion_matrix
print(confusion_matrix(y_test,predictions))
print(classification_report(y_test,predictions, target_names = target_names))

分類方法總覽- 決策樹、隨機森林、SVM(支持向量機)、KNN(k近鄰算法)、羅吉斯回歸

在我們剛剛談的第三步中,我們可以呼叫sklearn的分類方法開始訓練分類模型,
程式碼都不用自己寫,
只要直接呼叫函式就好,

這邊整理出可以呼叫的分類器

from sklearn.tree import DecisionTreeClassifier # 決策樹
from sklearn.ensemble import RandomForestClassifier # 隨機森林
from sklearn.svm import SVC #支持向量機
from sklearn.neighbors import KNeighborsClassifier # k近鄰算法
from sklearn.linear_model import LogisticRegression # 羅吉斯回歸

稍微簡述一下這些算法在做什麼,
有個概念就好,
對未來該選擇哪個方法來做分類也許有幫助

一開始不確定哪個好的話,也許可以每個都套用看看,
看哪個結果比較好

決策樹(Decision trees)

關於決策樹我覺得決策樹 Decision trees這篤文章寫的蠻好懂的,
引用該文章的一段話:

Decision trees(決策樹)是一種過程直覺單純、執行效率也相當高的監督式機器學習模型,適用於classification及regression資料類型的預測,與其它的ML模型比較起來,執行速度是它的一大優勢。
此外,Decision trees的特點是每個決策階段都相當的明確清楚(不是YES就是NO),相較之下,Logistic Regression與Support Vector Machines就好像黑箱一樣,我們很難去預測或理解它們內部複雜的運作細節。而且Decision trees有提供指令讓我們實際的模擬並繪出從根部、各枝葉到最終節點的決策過程。

舉一個生活化的例子了解決策樹的長相,
比方說女生要相親之前通過「年齡」、「長相」、「收入」和「是否為公務員」這4個特徵,
來決定「見面」與「不見面」的兩個類別:

https://ithelp.ithome.com.tw/upload/images/20200801/20117114ZkeTzAiRap.png
(圖片來源: 機器學習: 決策樹 (Decision Tree))

問題是我們怎麼生成這棵決策樹來幫助分類呢?
我的理解是,決策樹演算法就是讓機器產生一個好的決策樹,
根據輸入的資料自動的建構並決定決策樹的各個節點。

隨機森林(Random Forest)

俗話說「三個臭皮匠勝過一個諸葛亮」,
單獨一個決策樹可能會容易有「過擬合」(overfit)的問題,
隨機森林可以產生多個決策樹,
綜合它們的結果來得到更準確的分類

SVM- Support Vector Machine(支援向量機)

此法做二分類問題有不錯的效果,
可參考[機器學習首部曲] 支援向量機 SVM這篇文章了解原理

KNN- k nearest neighbor(k近鄰算法)

簡單來說,就是我本來已經有一群分類好的類別,
有一個未知的類別怎麼知道它是哪一類呢?
就取與未知類別「距離」最近的k個點,看附近的點最多是哪一類就分到那類
可參考:[Machine Learning] kNN分類演算法

羅吉斯回歸(Logistic regression)

用來做二分類,並可以得到這筆資料比較像A類還是B類的機率,
可參考: [資料分析&機器學習] 第3.3講:線性分類-邏輯斯回歸(Logistic Regression) 介紹

這邊需注意羅吉斯回歸(Logistic regression)與一般在機器學習上會聽到的線性回歸(Linear regression)不太一樣,參考: 機器/統計學習: 羅吉斯回歸(Logistic regression)


1 則留言

1
df568923
iT邦新手 5 級 ‧ 2020-08-02 11:28:04

哇~這篇介紹寫得好清楚。主要觀念都有提到,感謝大大分享~

心原一馬 iT邦研究生 5 級 ‧ 2020-08-02 11:40:55 檢舉

謝謝你的讚賞哦~

我要留言

立即登入留言