Scikit-learn從入門到放棄

愚生浅末發表於2024-08-18

目錄
  • Scikit-learn簡介
  • SVM分類
  • 隨機森林迴歸
  • K-means聚類

前置建議閱讀:

1、NumPy從入門到放棄

2、Pandas從入門到放棄

3、SciPy從入門到放棄

Scikit-learn簡介

Sklearn:官方文件https://scikitlearn.com.cn/0.21.3/

Scikit-learn(也稱sklearn)是基於Python程式語言的機器學習工具,是簡單高效的資料探勘和資料分析工具,它建立在NumPy、SciPy和matplotlib等庫的基礎上,可在各種環境中重複使用。其基本功能主要被分為六大部分:分類、迴歸、聚類、資料降維、模型選擇以及資料預處理。

(1) 分類:識別給定物件的所屬類別,屬於監督學習的範疇,常見的應用場景包括影像識別等。目前Scikit-learn已經實現的演算法包括:支援向量機(SVM)、最近鄰、邏輯迴歸、隨機森林、決策樹以及多層級感知器(MLP)神經網路等。

(2) 迴歸:預測與給定物件相關聯的連續值屬性,常見的應用場景包括客流預測等。目前Scikit-learn已經實現了以下演算法:支援向量迴歸(SVR)、Lasso迴歸、貝葉斯迴歸、隨機森林迴歸等。Scikit-learn實現的迴歸演算法幾乎涵蓋了開發者的各種需求範圍,並且還為各種演算法提供簡單的例項參考。

(3) 聚類:與分類不同,聚類是對給定物件根據相似特徵進行分組集合,屬於無監督學習的範疇,最常見的應用包括車站聚類、軌跡資料聚類、計程車上下客點聚類等。目前Scikit-learn實現的演算法包括:K-means聚類、譜聚類、層次聚類以及DBSCAN聚類等。

(4) 資料降維:當樣本數量遠少於樣本的特徵數量時,或特徵數量過多導致計算量過大,特徵稀疏性過於嚴重時,往往需要進行特徵降維,例如使用主成分分析(PCA)、非負矩陣分解(NMF)或特徵選擇等降維技術來減少要考慮的隨機變數個數,其主要應用場景包括圖片處理等。

(5) 模型選擇:對於給定的引數和模型,比較、驗證和選擇哪個模型的效果最好,其主要目的是透過設定不同的引數來執行模型,進而透過結果選擇最優引數以提升最終的模型精度。目前Scikit-learn實現的模組包括:格點搜尋,交叉驗證和各種針對預測誤差評估的度量函式。

(6) 資料預處理:資料的特徵提取和歸一化,通常是機器學習過程中的第一個也是最重要的一個環節,可以大大提高學習的效率。其中,特徵提取是指將文字或影像資料轉換為可用於機器學習的數字變數。透過去除不變、協變或其他統計上不重要的特徵量來改進機器學習,提高學習的精確度的一種方法。歸一化是指將輸入資料轉換為具有零均值和單位權方差的新變數,但因為大多數時候都做不到精確等於零,因此會設定一個可接受的範圍,一般都要求落在0-1之間。

Scikit-learn搭建了一套完整的用於資料預處理、資料降維、特徵提取和歸一化的演算法(模組),同時它針對每個演算法和模組都提供了豐富的參考案例和說明文件。可以透過Sklearn的官方文件(中文版)進行檢視學習。

SVM分類

SVM(Support Vector Machines),支援向量機是一種二分類模型,其基本模型定義為特徵空間上間隔最大的線性分類器。它將例項的特徵向量對映為空間中的一些點,其目的就是畫出一條線,以便區分兩類點,以至如果以後有了新的點,這條線也可以做出很好的分類。該演算法適合中小型資料樣本、非線性、高維的分類問題。在所有知名的資料探勘演算法中,SVM是最準確、最高效的演算法之一,屬於二分類演算法,可以支援線性和非線性的分類。

Sklearn中的SVM演算法庫封裝了libsvm和liblinear的實現,僅僅重寫了演算法的介面部分,使用時直接呼叫即可。SVM將演算法庫分為了兩類,一類是分類的演算法庫,主要包含LinearSVC、NuSVC和SVC三種演算法,另一類是迴歸演算法類,包含SVR、NuSVR和LinearSVR三種演算法。關於各種演算法的具體使用可以看官方文件,官方文件有著非常詳細的講解。

下面以一個簡單的二分類案例對Sklearn中SVM的使用進行簡單示範,具體過程如下:

首先構造資料集,資料集包含正類和負類,均服從正態分佈,且每個類的元素個數均為(200,2),不同處在於正類的中心點為(2,2),負類的中心點為(0,0)。接著給資料集分別貼上標籤,正類標籤為1,負類標籤為0,並將正負類按行合併成同一個資料集。

import numpy as np
from sklearn import svm
import pandas as pd
import matplotlib.pyplot as plt

# 正類,服從(0,1)的正態分佈
p = np.random.randn(200, 2)
for i in range(200):
    p[i][0] += 2
    p[i][1] += 2
# 負類,服從(0,-1)的正態分佈
f = np.random.randn(200, 2)

# 將np陣列轉換成dataframe
df_p = pd.DataFrame(p, columns=['x', 'y'])
# 加上標籤z,正類標籤為1
df_p['z'] = 1
# 負類標籤為0
df_f = pd.DataFrame(f, columns=['x', 'y'])
df_f['z'] = 0

# 將正負類合併成一個dataframe(按行進行合併)
con = pd.concat([df_p,df_f],axis=0)
print(con)

image

資料集構造好以後可以劃分訓練集和測試集,共有400個資料,取其中250個資料點作為訓練集,150個點作為測試集。接著規定訓練集的特徵和標籤,並進行分類訓練:透過svm介面直接新建SCM分類器,對分類器進行訓練,得到訓練好的引數以及測試集上的準確率。

# 重置資料集索引
con.reset_index(inplace=True, drop=True)
# 劃分訓練集和測試集
test_size = 150
train_data = con[:-test_size]
test_data = con[-test_size:]

# 選擇訓練集特徵和標籤
X = train_data[['x', 'y']]
Z = train_data['z']

# 新建SCV分類器
clf = svm.SVC(kernel='linear')
# 訓練
clf.fit(X,Z)
# 在訓練集上的準確率
clf.score(X, Z)
# 訓練好的引數: coefficients:類別特徵向量,Intercept:判別函式類別引數
print('Coefficients: %s \n\nIntercept %s' % (clf.coef_, clf.intercept_))
# 在測試集上的準確率
print('\n\nScore: %.2f' % clf.score(test_data[['x','y']], test_data['z']))

經過模型訓練,返回相關引數及模型準確率如表所示:

隨機森林迴歸

隨機森林是一種由多個決策樹構成的整合演算法,在分類和迴歸問題上都有不錯的表現。在解釋隨機森林以前,需要簡單介紹一下決策樹。決策樹是一種很簡單的演算法,解釋性強,也符合人類的直觀思維。這是一種基於if-then-else規則的有監督學習演算法。

image

隨機森林就是由很多決策樹構成的,不同決策樹之間沒有關聯。當我們進行分類任務時,新的輸入樣本進入,森林的每棵決策樹分別進行判斷分類,每個決策樹會得到一個自己的分類結果,分類結果中哪一個分類最多,隨機森林就會把這個結果當作最終結果。 隨機森林作為解決分類、迴歸問題的整合演算法,具有以下的優點:

(1) 對於大部分資料,可以產生高準確度的分類器;

(2) 可以處理大量的輸入變數;

(3) 隨機性的引入,不容易過擬合;

(4) 能處理離散型和連續性資料,無需規範化。

同樣,在利用隨機森林解決分類、迴歸問題時,也存在以下的缺點:

(1) 在某些噪音較大的分類或迴歸問題上會過擬合;

(2) 同一屬性,有不同取值的資料中,取值劃分較多的屬性會對隨機森林產生更大的影響,在該類資料上產出的屬性權值是不可信的;

(3) 森林中的決策樹個數很多時,訓練需要的時間和空間會較大。

以北京西直門地鐵站的進站客流資料為例,透過sklearn的隨機森林演算法對客流進行預測,更好地理解sklearn的基本使用方法。

首先利用Pandas匯入西直門地鐵站每15min的進站客流量,並且利用matplotlib繪製客流曲線圖。具體程式碼如下:

import pandas as pd
import matplotlib.pyplot as plt
from sklearn.ensemble import RandomForestRegressor

# 匯入西直門地鐵站點15min進站客流
df = pd.read_csv('./xizhimen.csv', encoding="gbk", parse_dates=True)
len(df)
df.head()  # 觀察資料集,這是一個單變數時間序列

plt.figure(figsize=(15, 5))
plt.grid(True)  # 網格化
plt.plot(df.iloc[:, 0], df.iloc[:, 1], label="XiZhiMen Station")
plt.legend()
plt.show()

image

考慮到客流量大小受先前客流影響,此處新增該時刻地鐵客流的前一個15min客流量、該時刻前五個15min的平均客流量以及前十個15min的平均客流量,以此提高客流預測的準確率,同時刪除異常資料NULL的所在行,避免影響預測。取資料集的80%作為訓練集,20%作為測試集。具體程式碼如下:

# 增加前一天的資料
df['pre_date_flow'] = df.loc[:, ['p_flow']].shift(1)
# 5日移動平均
df['MA5'] = df['p_flow'].rolling(5).mean()
# 10日移動平均
df['MA10'] = df['p_flow'].rolling(10).mean()
df.dropna(inplace=True)

X = df[['pre_date_flow', 'MA5', 'MA10']]
y = df['p_flow']
X.index = range(X.shape[0])

X_length = X.shape[0]
split = int(X_length * 0.8)
X_train, X_test = X[:split], X[split:]
y_train, y_test = y[:split], y[split:]
print()

接著需要對隨機森林模型進行擬合,由於sklearn已經將實現隨機森林迴歸的相關函式進行封裝,因此只需要透過介面呼叫相關函式就可以進行迴歸預測。預測得到結果以後,利用matplotlib對預測結果進行視覺化。具體程式碼如下:

random_forest_regressor = RandomForestRegressor(n_estimators=15)
# 擬合模型
random_forest_regressor.fit(X_train, y_train)
score = random_forest_regressor.score(X_test, y_test)
result = random_forest_regressor.predict(X_test)

plt.figure(figsize = (15, 5))
plt.title('The result of Prediction')
plt.plot(y_test.ravel(), label='real')
plt.plot(result, label = 'predict')
plt.legend()
plt.show()

image

K-means聚類

聚類分析:將大量資料中具有“相似”特徵的資料點或樣本劃分為一個類別。

與分類、序列標註等任務不同,聚類是在事先並不知道任何樣本標籤的情況下,透過資料之間的內在關係把樣本劃分為若干類別,使得同類別樣本之間的相似度高,不同類別樣本之間的相似度低(簇內差異小,簇間差異大)。聚類模型建立在無類標記的資料上,是一種非監督的學習演算法,相對於監督學習,蘊含了巨大的潛力與價值。 K-means聚類是無監督學習的傑出代表之一,是最基礎常用的聚類演算法,基於點與點之間的距離相似度來計算最佳類別歸屬。它的基本思想是:透過迭代尋找K個簇(Cluster)的一種劃分方案,使得聚類結果對應的損失函式最小。其中損失函式定義為各個樣本距離所屬簇中心點的誤差平方和。

在sklearn中,為了方便使用,將K-means演算法的實現進行打包封裝,在需要使用該演算法進行聚類分析時,直接呼叫即可。下面以北京地鐵進站客流資料向讀者展示如何使用sklearn中的K-means演算法。

首先透過Pandas匯入北京地鐵站點15min進站客流資料,接著對資料進行預處理,刪除NULL值所在行的資料,刪除“Station_name”列,僅僅保留每個車站的15min進站客流資料。

import pandas as pd
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from sklearn import metrics

# 匯入北京地鐵站點15min進站客流
df = pd.read_csv('./in_15min.csv', encoding="gbk", parse_dates=True)
len(df)
df.dropna(inplace=True) # 首先去除空值所在的行

x_data = df.drop('Station_name', axis=1) # 以列為單位,刪除'Station_name'列

接著需要確定K值,此處基於簇內誤差平方和,使用肘方法確定簇的最佳數量(即K值),其基本理念就是找出聚類偏差驟減的K值,以此確定最優聚類數。透過畫出不同K值的聚類偏差圖可以清楚看出。具體程式碼如下:

# 肘方法看K值
d = []
for i in range(1, 15):
    km = KMeans(n_clusters=i, init='k-means++', n_init=10, max_iter=300, random_state=0)
    km.fit(x_data)
    d.append(km.inertia_) # inertia簇內誤差平方和

plt.plot(range(1, 15), d, marker='o')
plt.xlabel('number of clusters')
plt.ylabel('distortions')
plt.show()

由聚類偏差圖可以看出,K值取6較為合適,或根據需要,取大致聚類結果即可。

呼叫sklearn的KMeans演算法,根據客流進站資料對車站類別進行聚類,並返回聚類結果。至於聚類效果的評價指標,此處選擇了兩個較為常見的指標:輪廓係數以及c&h得分,判斷聚類效果的好壞。具體程式碼如下:

# 從效果圖可以看出,K取6最合適
model_kmeans = KMeans(n_clusters=6, random_state=0)
model_kmeans.fit(x_data)
y_pre = model_kmeans.predict(x_data)
y_pre += 1
print('聚類結果為:' + str(y_pre))

# 評價指標
silhouette_s = metrics.silhouette_score(x_data, y_pre, metric = 'euclidean')
calinski_harabaz_s = metrics.calinski_harabasz_score(x_data, y_pre)
print('輪廓係數為:%.2f,c&h得分為:%d' % (silhouette_s, calinski_harabaz_s))

該模型的評價指標如模型評價指標表所示:

聚類所追求的是對於每個簇而言,其簇內差異小,簇外差異大。輪廓係數S正是描述簇內外差異的關鍵指標,取值範圍為[-1, 1],當S越接近於1,聚類效果越好;越接近-1,聚類效果越差。該模型的輪廓係數為0.39,說明聚類效果良好。至於c&h分數,被定義為組間離散於組內離散的比率,該分值越大說明聚類效果越好,該模型的c&h分數為200,聚類效果良好。

本文相關資料檔案公眾號回覆“Scikit-learn從入門到放棄”獲取。
公眾號本文地址:https://mp.weixin.qq.com/s/L0tKz9JFnsgrzSCXDswbRA
image

相關文章