機器學習四(學習筆記) 迴歸算法(轉)

迴歸算法

迴歸是統計學中最有力的工具之一。機器學習監督學習算法分爲分類算法和迴歸算法兩種,其實就是根據類別標籤分佈類型爲離散型、連續性而定義的。迴歸算法用於連續型分佈預測,針對的是數值型的樣本,使用迴歸,可以在給定輸入的時候預測出一個數值,這是對分類方法的提升,因爲這樣可以預測連續型數據而不僅僅是離散的類別標籤。

迴歸分析中,只包括一個自變量和一個因變量,且二者的關係可用一條直線近似表示,這種迴歸分析稱爲一元線性迴歸分析。如果迴歸分析中包括兩個或兩個以上的自變量,且因變量和自變量之間是線性關係,則稱爲多元線性迴歸分析。那麼什麼是線性關係和非線性關係?

比如說在房價上,房子的面積和房子的價格有着明顯的關係。那麼X=房間大小,Y=房價,那麼在座標系中可以看到這些點:

那麼通過一條直線把這個關係描述出來,叫線性關係

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-sfksavSk-1577722401544)(./images/房價線性.png)]

如果是一條曲線,那麼叫非線性關係

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-VoVGRBqI-1577722401546)(./images/房價非線性.png)]

那麼迴歸的目的就是建立一個迴歸方程(函數)用來預測目標值,迴歸的求解就是求這個迴歸方程的迴歸係數。

一、迴歸算法之線性迴歸

線性迴歸的定義是:目標值預期是輸入變量的線性組合。線性模型形式簡單、易於建模,但卻蘊含着機器學習中一些重要的基本思想。線性迴歸,是利用數理統計中迴歸分析,來確定兩種或兩種以上變量間相互依賴的定量關係的一種統計分析方法,運用十分廣泛。

優點:結果易於理解,計算不復雜

缺點:對非線性的數據擬合不好

適用數據類型:數值型和標稱型

對於單變量線性迴歸,例如:前面房價例子中房子的大小預測房子的價格。f(x) = w1*x+w0,這樣通過主要參數w1就可以得出預測的值。

通用公式爲:

h\left(\theta\right){=}\theta_0+\theta_1{x}h(θ)=θ0+θ1x

那麼對於多變量回歸,例如:瓜的好壞程度 f(x) = w0+0.2色澤+0.5根蒂+0.3*敲聲,得出的值來判斷一個瓜的好與不好的程度。

通用公式爲:

h\left(\theta\right){=}\theta_{0}+\theta_{1}{x_{1}}+\theta_{2}{x_{2}}h(θ)=θ0+θ1x1+θ2x2

線性模型中的向量W值,客觀的表達了各屬性在預測中的重要性,因此線性模型有很好的解釋性。對於這種“多特徵預測”也就是(多元線性迴歸),那麼線性迴歸就是在這個基礎上得到這些W的值,然後以這些值來建立模型,預測測試數據。簡單的來說就是學得一個線性模型以儘可能準確的預測實值輸出標記。

那麼如果對於多變量線性迴歸來說我們可以通過向量的方式來表示W值與特徵X值之間的關係:

\theta = \begin{pmatrix}\theta_0 \\theta_1 \\theta_2 \\theta_3\end{pmatrix}θ=⎝⎜⎜⎛θ0θ1θ2θ3⎠⎟⎟⎞ X = \begin{pmatrix}x_0\x_1\x_2\x_3\end{pmatrix}X=⎝⎜⎜⎛x0x1x2x3⎠⎟⎟⎞

兩向量相乘,結果爲一個整數是估計值,其中所有特徵集合的第一個特徵值x_0x0=1,那麼我們可以通過通用的向量公式來表示線性模型:

h(\theta) = \theta^T * xh(θ)=θT∗x

一個列向量的轉置與特徵的乘積,得出我們預測的結果,但是顯然我們這個模型得到的結果可定會有誤差,如下圖所示:

單變量

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-HsnIQR34-1577722401549)(./images/房價誤差.png)]

多變量

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-VjsF2nyj-1577722401552)(./images/多變量回歸誤差.png)]

損失函數

損失函數是一個貫穿整個機器學習重要的一個概念,大部分機器學習算法都會有誤差,我們得通過顯性的公式來描述這個誤差,並且將這個誤差優化到最小值。

對於線性迴歸模型,將模型與數據點之間的距離差之和做爲衡量匹配好壞的標準,誤差越小,匹配程度越大。我們要找的模型就是需要將f(x)和我們的真實值之間最相似的狀態。於是我們就有了誤差公式,模型與數據差的平方和最小:

J\left(\theta\right){=}\sum_{i=1}^{m} \left({h_\theta}({x}{(i)}){-}{y}{(i)}\right)^{2}J(θ)=∑i=1m(hθ(x(i))−y(i))2

上面公式定義了所有的誤差和,那麼現在需要使這個值最小?那麼有兩種方法,一種使用梯度下降算法另一種使正規方程解法(只適用於簡單的線性迴歸)

梯度下降算法

上面誤差公式是一個通式,我們取兩個單個變量來求最小值,誤差和可以表示爲:

cost\left({w_0+w_1x_1}\right){=}\sum_{i=1}^{N} \left({w_0+w_1x_i}{-}{y_i}\right)^{2}cost(w0+w1x1)=∑i=1N(w0+w1xi−yi)2

可以通過調整不同的w_1w1和w_0w0的值,就能使誤差不斷變化,而當你找到這個公式的最小值時,你就能得到最好的w_1w1,w_0w0 而這對\left({w_1},{w_0}\right)(w1,w0)就是能最好描述你數據關係的模型參數。

怎麼找cost\left({w_0+w_1x_1}\right)cost(w0+w1x1)的最小? cost\left({w_0+w_1x_1}\right)cost(w0+w1x1)的圖像其實像一個山谷一樣,有一個最低點。找這個最低點的辦法就是,先隨便找一個點(w_1w1=5, w_0w0=4), 然後 沿着這個碗下降的方向找,最後就能找到山谷的最低點。

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-CT5Bi52R-1577722401555)(./images/梯度下降.png)]

1、LinearRegression

sklearn.linear_model.LinearRegression

class LinearRegression(fit_intercept = True,normalize = False,copy_X = True,n_jobs = 1)
  """
  :param normalize:如果設置爲True時,數據進行標準化。請在使用normalize = False的估計器調時用fit之前使用preprocessing.StandardScaler

  :param copy_X:boolean,可選,默認爲True,如果爲True,則X將被複制

  :param n_jobs:int,可選,默認1。用於計算的CPU核數
  """

實例代碼:

from sklearn.linear_model import LinearRegression
reg = LinearRegression()

1.方法

fit(X,y,sample_weight = None)

使用X作爲訓練數據擬合模型,y作爲X的類別值。X,y爲數組或者矩陣

reg.fit ([[0, 0], [1, 1], [2, 2]], [0, 1, 2])

predict(X)

預測提供的數據對應的結果

reg.predict([[3,3]])

array([ 3.])

2.屬性

coef_

表示迴歸係數w=(w1,w2…)

reg.coef_

array([ 0.5,  0.5])

intercept_ 表示w0

加入交叉驗證

前面我們已經提到了模型的交叉驗證,那麼我們這個自己去建立數據集,然後通過線性迴歸的交叉驗證得到模型。由於sklearn中另外兩種迴歸嶺迴歸、lasso迴歸都本省提供了迴歸CV方法,比如linear_model.Lasso,交叉驗證linear_model.LassoCV;linear_model.Ridge,交叉驗證linear_model.RidgeCV。所以我們需要通過前面的cross_validation提供的方法進行k-折交叉驗證。

from sklearn.datasets.samples_generator import make_regression
from sklearn.model_selection import cross_val_score
from sklearn import linear_model
import matplotlib.pyplot as plt

lr = linear_model.LinearRegression()
X, y = make_regression(n_samples=200, n_features=5000, random_state=0)
result = cross_val_score(lr, X, y)
print result

3、線性迴歸案例分析

波士頓房價預測

使用scikit-learn中內置的迴歸模型對“美國波士頓房價”數據進行預測。對於一些比賽數據,可以從kaggle官網上獲取,網址:https://www.kaggle.com/datasets

1.美國波士頓地區房價數據描述

from sklearn.datasets import load_boston

boston = load_boston()

print boston.DESCR

2.波士頓地區房價數據分割

from sklearn.cross_validation import train_test_split
import numpy as np
X = boston.data
y = boston.target

X_train,X_test,y_train,y_test = train_test_split(X,y,random_state=33,test_size = 0.25)

3.訓練與測試數據標準化處理

from sklearn.preprocessing import StandardScaler
ss_X = StandardScaler()
ss_y = StandardScaler()

X_train = ss_X.fit_transform(X_train)
X_test = ss_X.transform(X_test)
y_train = ss_X.fit_transform(y_train)
X_train = ss_X.transform(y_test)

4.使用最簡單的線性迴歸模型LinearRegression和梯度下降估計SGDRegressor對房價進行預測

from sklearn.linear_model import LinearRegression
lr = LinearRegression()
lr.fit(X_train,y_train)
lr_y_predict = lr.predict(X_test)

from sklearn.linear_model import SGDRegressor
sgdr = SGDRegressor()
sgdr.fit(X_train,y_train)
sgdr_y_predict = sgdr.predict(X_test)

5.性能評測

對於不同的類別預測,我們不能苛刻的要求迴歸預測的數值結果要嚴格的與真實值相同。一般情況下,我們希望衡量預測值與真實值之間的差距。因此,可以測評函數進行評價。其中最爲直觀的評價指標均方誤差(Mean Squared Error)MSE,因爲這也是線性迴歸模型所要優化的目標。

MSE的計算方法如式:

{MSE=}\frac{1}{m}\sum_{i=1}{m}\left({y{i}-\bar{y}}\right)^{2}MSE=m1∑i=1m(yi−y¯)2

使用MSE評價機制對兩種模型的迴歸性能作出評價

from sklearn.metrics import mean_squared_error

print '線性迴歸模型的均方誤差爲:',mean_squared_error(ss_y.inverse_transform(y_test),ss_y.inverse_tranform(lr_y_predict))
print '梯度下降模型的均方誤差爲:',mean_squared_error(ss_y.inverse_transform(y_test),ss_y.inverse_tranform(sgdr_y_predict))

通過這一比較發現,使用梯度下降估計參數的方法在性能表現上不及使用解析方法的LinearRegression,但是如果面對訓練數據規模十分龐大的任務,隨即梯度法不論是在分類還是迴歸問題上都表現的十分高效,可以在不損失過多性能的前提下,節省大量計算時間。根據Scikit-learn官網的建議,如果數據規模超過10萬,推薦使用隨機梯度法估計參數模型。

注意:線性迴歸器是最爲簡單、易用的迴歸模型。正式因爲其對特徵與迴歸目標之間的線性假設,從某種程度上說也侷限了其應用範圍。特別是,現實生活中的許多實例數據的各種特徵與迴歸目標之間,絕大多數不能保證嚴格的線性關係。儘管如此,在不清楚特徵之間關係的前提下,我們仍然可以使用線性迴歸模型作爲大多數數據分析的基線系統。

完整代碼如下:

from sklearn.linear_model import LinearRegression, SGDRegressor, Ridge
from sklearn.preprocessing import StandardScaler
from sklearn.datasets import load_boston
from sklearn.cross_validation import train_test_split
from sklearn.metrics import mean_squared_error,classification_report
from sklearn.cluster import KMeans


def linearmodel():
    """
    線性迴歸對波士頓數據集處理
    :return: None
    """

    # 1、加載數據集

    ld = load_boston()

    x_train,x_test,y_train,y_test = train_test_split(ld.data,ld.target,test_size=0.25)

    # 2、標準化處理

    # 特徵值處理
    std_x = StandardScaler()
    x_train = std_x.fit_transform(x_train)
    x_test = std_x.transform(x_test)


    # 目標值進行處理

    std_y  = StandardScaler()
    y_train = std_y.fit_transform(y_train)
    y_test = std_y.transform(y_test)

    # 3、估計器流程

    # LinearRegression
    lr = LinearRegression()

    lr.fit(x_train,y_train)

    # print(lr.coef_)

    y_lr_predict = lr.predict(x_test)

    y_lr_predict = std_y.inverse_transform(y_lr_predict)

    print("Lr預測值:",y_lr_predict)


    # SGDRegressor
    sgd = SGDRegressor()

    sgd.fit(x_train,y_train)

    # print(sgd.coef_)

    y_sgd_predict = sgd.predict(x_test)

    y_sgd_predict = std_y.inverse_transform(y_sgd_predict)

    print("SGD預測值:",y_sgd_predict)

    # 帶有正則化的嶺迴歸

    rd = Ridge(alpha=0.01)

    rd.fit(x_train,y_train)

    y_rd_predict = rd.predict(x_test)

    y_rd_predict = std_y.inverse_transform(y_rd_predict)

    print(rd.coef_)

    # 兩種模型評估結果

    print("lr的均方誤差爲:",mean_squared_error(std_y.inverse_transform(y_test),y_lr_predict))

    print("SGD的均方誤差爲:",mean_squared_error(std_y.inverse_transform(y_test),y_sgd_predict))

    print("Ridge的均方誤差爲:",mean_squared_error(std_y.inverse_transform(y_test),y_rd_predict))

    return None

1、欠擬合與過擬合

機器學習中的泛化,泛化即是,模型學習到的概念在它處於學習的過程中時模型沒有遇見過的樣本時候的表現。在機器學習領域中,當我們討論一個機器學習模型學習和泛化的好壞時,我們通常使用術語:過擬合和欠擬合。我們知道模型訓練和測試的時候有兩套數據,訓練集和測試集。在對訓練數據進行擬合時,需要照顧到每個點,而其中有一些噪點,當某個模型過度的學習訓練數據中的細節和噪音,以至於模型在新的數據上表現很差,這樣的話模型容易複雜,擬合程度較高,造成過擬合。而相反如果值描繪了一部分數據那麼模型複雜度過於簡單,欠擬合指的是模型在訓練和預測時表現都不好的情況,稱爲欠擬合。

我們來看一下線性迴歸中擬合的幾種情況圖示:

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-CaL4fzBA-1577722401560)(./images/欠擬合.png)]

\theta_0+\theta_1{x}θ0+θ1x

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-xuVBANoP-1577722401562)(./images/擬合程度較好.png)]

\theta_{0}+\theta_{1}{x}+\theta_{2}x^{2}θ0+θ1x+θ2x2

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-8gkxLMod-1577722401565)(./images/過擬合.png)]

\theta_{0}+\theta_{1}{x}+\theta_{2}x{2}+\theta_{3}x{3}+\theta_{4}x^{4}θ0+θ1x+θ2x2+θ3x3+θ4x4

還有在邏輯迴歸分類中的擬合情況:

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-dCXHUIwR-1577722401568)(./images/LR欠擬合.png)]

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-nV4BdwhS-1577722401570)(./images/LR擬合程度較好.png)]

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-YAgVAI9S-1577722401573)(./images/LR過擬合.png)]

解決過擬合的方法

在線性迴歸中,對於特徵集過小的情況,容易造成欠擬合(underfitting),對於特徵集過大的情況,容易造成過擬合(overfitting)。針對這兩種情況有了更好的解決辦法

欠擬合

欠擬合指的是模型在訓練和預測時表現都不好的情況,欠擬合通常不被討論,因爲給定一個評估模型表現的指標的情況下,欠擬合很容易被發現。矯正方法是繼續學習並且試着更換機器學習算法。

過擬合

對於過擬合,特徵集合數目過多,我們需要做的是儘量不讓迴歸係數數量變多,對擬合(損失函數)加以限制。

(1)當然解決過擬合的問題可以減少特徵數,顯然這只是權宜之計,因爲特徵意味着信息,放棄特徵也就等同於丟棄信息,要知道,特徵的獲取往往也是艱苦卓絕的。

(2)引入了 正則化 概念。

直觀上來看,如果我們想要解決上面迴歸中的過擬合問題,我們最好就要消除x_3x3和x_4x4的影響,也就是想讓\theta_3{,}\theta_4θ3,θ4都等於0,一個簡單的方法就是我們對\theta_3{,}\theta_4θ3,θ4進行懲罰,增加一個很大的係數,這樣在優化的過程中就會使這兩個參數爲零。

二、迴歸算法之嶺迴歸

具有L2正則化的線性最小二乘法。嶺迴歸是一種專用於共線性數據分析的有偏估計迴歸方法,實質上是一種改良的最小二乘估計法,通過放棄最小二乘法的無偏性,以損失部分信息、降低精度爲代價獲得迴歸係數更爲符合實際、更可靠的迴歸方法,對病態數據的擬合要強於最小二乘法。當數據集中存在共線性的時候,嶺迴歸就會有用。

1、sklearn.linear_model.Ridge

class sklearn.linear_model.Ridge(alpha=1.0, fit_intercept=True, normalize=False, copy_X=True, max_iter=None, tol=0.001, solver='auto', random_state=None)**
  """
  :param alpha:float類型,正規化的程度
  """
from sklearn.linear_model import Ridge
clf = Ridge(alpha=1.0)
clf.fit([[0, 0], [0, 0], [1, 1]], [0, .1, 1]))

1.1方法

score(X, y, sample_weight=None)

clf.score()

1.2屬性

coef_

clf.coef_
array([ 0.34545455,  0.34545455])

intercept_

clf.intercept_
0.13636..

2、嶺迴歸案例分析

def linearmodel():
    """
    線性迴歸對波士頓數據集處理
    :return: None
    """

    # 1、加載數據集

    ld = load_boston()

    x_train,x_test,y_train,y_test = train_test_split(ld.data,ld.target,test_size=0.25)

    # 2、標準化處理

    # 特徵值處理
    std_x = StandardScaler()
    x_train = std_x.fit_transform(x_train)
    x_test = std_x.transform(x_test)


    # 目標值進行處理

    std_y  = StandardScaler()
    y_train = std_y.fit_transform(y_train)
    y_test = std_y.transform(y_test)

    # 3、估計器流程

    # LinearRegression
    lr = LinearRegression()

    lr.fit(x_train,y_train)

    # print(lr.coef_)

    y_lr_predict = lr.predict(x_test)

    y_lr_predict = std_y.inverse_transform(y_lr_predict)

    print("Lr預測值:",y_lr_predict)


    # SGDRegressor
    sgd = SGDRegressor()

    sgd.fit(x_train,y_train)

    # print(sgd.coef_)

    y_sgd_predict = sgd.predict(x_test)

    y_sgd_predict = std_y.inverse_transform(y_sgd_predict)

    print("SGD預測值:",y_sgd_predict)

    # 帶有正則化的嶺迴歸

    rd = Ridge(alpha=0.01)

    rd.fit(x_train,y_train)

    y_rd_predict = rd.predict(x_test)

    y_rd_predict = std_y.inverse_transform(y_rd_predict)

    print(rd.coef_)

    # 兩種模型評估結果

    print("lr的均方誤差爲:",mean_squared_error(std_y.inverse_transform(y_test),y_lr_predict))

    print("SGD的均方誤差爲:",mean_squared_error(std_y.inverse_transform(y_test),y_sgd_predict))

    print("Ridge的均方誤差爲:",mean_squared_error(std_y.inverse_transform(y_test),y_rd_predict))

    return None

三、聚類算法學習之k-means

1、K-Means類概述

在scikit-learn中,包括兩個K-Means的算法,一個是傳統的K-Means算法,對應的類是KMeans。另一個是基於採樣的Mini Batch K-Means算法,對應的類是MiniBatchKMeans。一般來說,使用K-Means的算法調參是比較簡單的。

用KMeans類的話,一般要注意的僅僅就是k值的選擇,即參數n_clusters;如果是用MiniBatchKMeans的話,也僅僅多了需要注意調參的參數batch_size,即我們的Mini Batch的大小。

當然KMeans類和MiniBatchKMeans類可以選擇的參數還有不少,但是大多不需要怎麼去調參。下面我們就看看KMeans類和MiniBatchKMeans類的一些主要參數。

2. KMeans類主要參數

KMeans類的主要參數有:

  1. n_clusters: 即我們的k值,一般需要多試一些值以獲得較好的聚類效果。k值好壞的評估標準在下面會講。

2)max_iter: 最大的迭代次數,一般如果是凸數據集的話可以不管這個值,如果數據集不是凸的,可能很難收斂,此時可以指定最大的迭代次數讓算法可以及時退出循環。

3)**n_init:**用不同的初始化質心運行算法的次數。由於K-Means是結果受初始值影響的局部最優的迭代算法,因此需要多跑幾次以選擇一個較好的聚類效果,默認是10,一般不需要改。如果你的k值較大,則可以適當增大這個值。

4)init: 即初始值選擇的方式,可以爲完全隨機選擇’random’,優化過的’k-means++‘或者自己指定初始化的k個質心。一般建議使用默認的’k-means++’。

5)algorithm:有“auto”, “full” or “elkan”三種選擇。“full"就是我們傳統的K-Means算法, “elkan”是我們原理篇講的elkan K-Means算法。默認的"auto"則會根據數據值是否是稀疏的,來決定如何選擇"full"和“elkan”。一般數據是稠密的,那麼就是 “elkan”,否則就是"full”。一般來說建議直接用默認的"auto"

3. MiniBatchKMeans類主要參數

MiniBatchKMeans類的主要參數比KMeans類稍多,主要有:

  1. n_clusters: 即我們的k值,和KMeans類的n_clusters意義一樣。

2)**max_iter:**最大的迭代次數, 和KMeans類的max_iter意義一樣。

3)**n_init:**用不同的初始化質心運行算法的次數。這裏和KMeans類意義稍有不同,KMeans類裏的n_init是用同樣的訓練集數據來跑不同的初始化質心從而運行算法。而MiniBatchKMeans類的n_init則是每次用不一樣的採樣數據集來跑不同的初始化質心運行算法。

4)batch_size:即用來跑Mini Batch KMeans算法的採樣集的大小,默認是100.如果發現數據集的類別較多或者噪音點較多,需要增加這個值以達到較好的聚類效果。

5)init: 即初始值選擇的方式,和KMeans類的init意義一樣。

6)init_size: 用來做質心初始值候選的樣本個數,默認是batch_size的3倍,一般用默認值就可以了。

7)reassignment_ratio: 某個類別質心被重新賦值的最大次數比例,這個和max_iter一樣是爲了控制算法運行時間的。這個比例是佔樣本總數的比例,乘以樣本總數就得到了每個類別質心可以重新賦值的次數。如果取值較高的話算法收斂時間可能會增加,尤其是那些暫時擁有樣本數較少的質心。默認是0.01。如果數據量不是超大的話,比如1w以下,建議使用默認值。如果數據量超過1w,類別又比較多,可能需要適當減少這個比例值。具體要根據訓練集來決定。

8)**max_no_improvement:**即連續多少個Mini Batch沒有改善聚類效果的話,就停止算法, 和reassignment_ratio, max_iter一樣是爲了控制算法運行時間的。默認是10.一般用默認值就足夠了。

4. K值的評估標準

不像監督學習的分類問題和迴歸問題,我們的無監督聚類沒有樣本輸出,也就沒有比較直接的聚類評估方法。但是我們可以從簇內的稠密程度和簇間的離散程度來評估聚類的效果。常見的方法有輪廓係數Silhouette Coefficient和Calinski-Harabasz Index。個人比較喜歡Calinski-Harabasz Index,這個計算簡單直接,得到的Calinski-Harabasz分數值ss越大則聚類效果越好。

Calinski-Harabasz分數值ss的數學計算公式是:

s(k)=tr(Bk)tr(Wk)m−kk−1s(k)=tr(Bk)tr(Wk)m−kk−1

其中m爲訓練集樣本數,k爲類別數。BkBk爲類別之間的協方差矩陣,WkWk爲類別內部數據的協方差矩陣。trtr爲矩陣的跡。

也就是說,類別內部數據的協方差越小越好,類別之間的協方差越大越好,這樣的Calinski-Harabasz分數會高。在scikit-learn中, Calinski-Harabasz Index對應的方法是metrics.calinski_harabaz_score.

5. K-Means應用實例

下面用一個實例來講解用KMeans類和MiniBatchKMeans類來聚類。我們觀察在不同的k值下Calinski-Harabasz分數。

首先我們隨機創建一些二維數據作爲訓練集,選擇二維特徵數據,主要是方便可視化。代碼如下:

import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
from sklearn.datasets.samples_generator import make_blobs
# X爲樣本特徵,Y爲樣本簇類別, 共1000個樣本,每個樣本4個特徵,共4個簇,簇中心在[-1,-1], [0,0],[1,1], [2,2], 簇方差分別爲[0.4, 0.2, 0.2]
X, y = make_blobs(n_samples=1000, n_features=2, centers=[[-1,-1], [0,0], [1,1], [2,2]], cluster_std=[0.4, 0.2, 0.2, 0.2], 
                  random_state =9)
plt.scatter(X[:, 0], X[:, 1], marker='o')
plt.show()

從輸出圖可以我們看看我們創建的數據如下:

img

現在我們來用K-Means聚類方法來做聚類,首先選擇k=2,代碼如下:

from sklearn.cluster import KMeans
y_pred = KMeans(n_clusters=2, random_state=9).fit_predict(X)
plt.scatter(X[:, 0], X[:, 1], c=y_pred)
plt.show()

k=2聚類的效果圖輸出如下:

img

現在我們來看看我們用Calinski-Harabasz Index評估的聚類分數:

from sklearn import metrics
metrics.calinski_harabaz_score(X, y_pred)  

輸出如下:

3116.1706763322227

現在k=3來看看聚類效果,代碼如下:

from sklearn.cluster import KMeans
y_pred = KMeans(n_clusters=3, random_state=9).fit_predict(X)
plt.scatter(X[:, 0], X[:, 1], c=y_pred)
plt.show()  

k=3的聚類的效果圖輸出如下:

img

現在我們來看看我們用Calinski-Harabaz Index評估的k=3時候聚類分數:

metrics.calinski_harabaz_score(X, y_pred)  

輸出如下:

2931.625030199556

可見此時k=3的聚類分數比k=2還差。

現在我們看看k=4時候的聚類效果:

from sklearn.cluster import KMeans
y_pred = KMeans(n_clusters=4, random_state=9).fit_predict(X)
plt.scatter(X[:, 0], X[:, 1], c=y_pred)
plt.show()

k=4的聚類的效果圖輸出如下:

img

現在我們來看看我們用Calinski-Harabasz Index評估的k=4時候聚類分數:

metrics.calinski_harabaz_score(X, y_pred)  

輸出如下:

5924.050613480169

可見k=4的聚類分數比k=2和k=3都要高,這也符合我們的預期,我們的隨機數據集也就是4個簇。當特徵維度大於2,我們無法直接可視化聚類效果來肉眼觀察時,用Calinski-Harabaz Index評估是一個很實用的方法。

現在我們再看看用MiniBatchKMeans的效果,我們將batch size設置爲200. 由於我們的4個簇都是凸的,所以其實batch size的值只要不是非常的小,對聚類的效果影響不大。

for index, k in enumerate((2,3,4,5)):
    plt.subplot(2,2,index+1)
    y_pred = MiniBatchKMeans(n_clusters=k, batch_size = 200, random_state=9).fit_predict(X)
    score= metrics.calinski_harabaz_score(X, y_pred)  
    plt.scatter(X[:, 0], X[:, 1], c=y_pred)
    plt.text(.99, .01, ('k=%d, score: %.2f' % (k,score)),
                 transform=plt.gca().transAxes, size=10,
                 horizontalalignment='right')
plt.show()

對於k=2,3,4,5對應的輸出圖爲:

img

可見使用MiniBatchKMeans的聚類效果也不錯,當然由於使用Mini Batch的原因,同樣是k=4最優,KMeans類的Calinski-Harabasz Index分數爲5924.05,而MiniBatchKMeans的分數稍微低一些,爲5921.45。這個差異損耗並不大。

K-Means聚類案列

from sklearn.metrics import silhouette_score
from sklearn.cluster import KMeans

def kmeans():
    """
    手寫數字聚類過程
    :return: None
    """
    # 加載數據

    ld = load_digits()

    print(ld.target[:20])


    # 聚類
    km = KMeans(n_clusters=810)

    km.fit_transform(ld.data)

    print(km.labels_[:20])

    print(silhouette_score(ld.data,km.labels_))

    return None



if __name__=="__main__":
    kmeans()
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章