【火爐煉AI】機器學習009-用邏輯迴歸分類器解決多分類問題

煉丹老頑童發表於2018-08-06

【火爐煉AI】機器學習009-用邏輯迴歸分類器解決多分類問題

(本文所使用的Python庫和版本號: Python 3.5, Numpy 1.14, scikit-learn 0.19, matplotlib 2.2 )

前面的【火爐煉AI】機器學習008已經講解了用簡單線性分類器解決二分類問題,但是對於多分類問題,我們該怎麼辦了?

此處介紹一種用於解決多分類問題的分類器:邏輯迴歸。雖然名稱中含有迴歸二字,但邏輯迴歸不僅可以用來做迴歸分析,也可以用來做分類問題。邏輯迴歸是機器學習領域比較常用的演算法,用於估計樣本所屬類別的可能性,關於邏輯迴歸的更深層次的公式推導,可以參看https://blog.csdn.net/devotion987/article/details/78343834。


1. 準備資料集

此處我們自己構建了一些簡單的資料樣本作為資料集,首先我們要分析該資料集,做到對資料集的特性瞭然如胸。

# 首先準備資料集
# 特徵向量
X =np.array([[4, 7], [3.5, 8], [3.1, 6.2], [0.5, 1], [1, 2],
             [1.2, 1.9], [6, 2], [5.7, 1.5], [5.4, 2.2]]) # 自定義的資料集
# 標記
y = np.array([0, 0, 0, 1, 1, 1, 2, 2, 2]) # 三個類別

# 按照類別將資料點畫到散點圖中
class_0=np.array([feature for (feature,label) in zip(X,y) if label==0])
# print(class_0) # 確保沒有問題
class_1=np.array([feature for (feature,label) in zip(X,y) if label==1])
# print(class_1)
class_2=np.array([feature for (feature,label) in zip(X,y) if label==2])
# print(class_2)

# 繪圖
plt.figure()
plt.scatter(class_0[:,0],class_0[:,1],marker='s',label='class_0')
plt.scatter(class_1[:,0],class_1[:,1],marker='x',label='class_1')
plt.scatter(class_2[:,0],class_2[:,1],marker='o',label='class_2')
plt.legend()
複製程式碼

簡單資料集的分佈情況

########################小**********結###############################

1,通過將資料集的y label可以看出,整個資料集有三個類別,每個類別的資料點都聚集到一塊,這個可以從散點圖中看出,故而此處是典型的多分類問題。

2,此處資料集的樣本數比較少(每個類別三個樣本),且特徵向量只有兩個,並且從散點圖中可以看出,資料集各個類別都區分的比較開,故而相對比較容易分類。

#################################################################


2. 構建邏輯迴歸分類器

邏輯迴歸分類器的構建非常簡單,如下程式碼所示,首先我們用該分類器的預設引數做一下分類試試。

# 構建邏輯迴歸分類器
from sklearn.linear_model import LogisticRegression
classifier = LogisticRegression(random_state=37) # 先用預設的引數
classifier.fit(X, y) # 對國際迴歸分類器進行訓練
複製程式碼

雖然此處我們構建了邏輯迴歸分類器, 並且用我們的資料集進行了訓練,但訓練的效果該怎麼檢視了?此時我們也沒有測試集,所以暫時的,我們將該分類器在訓練集上的分類效果畫到圖中,給出一個直觀的分類效果。為了在圖中看到分類效果,需要定義一個專門繪製分類器效果展示的函式,如下。

# 將分類器繪製到圖中
def plot_classifier(classifier, X, y):
    x_min, x_max = min(X[:, 0]) - 1.0, max(X[:, 0]) + 1.0 # 計算圖中座標的範圍
    y_min, y_max = min(X[:, 1]) - 1.0, max(X[:, 1]) + 1.0
    step_size = 0.01 # 設定step size
    x_values, y_values = np.meshgrid(np.arange(x_min, x_max, step_size), np.arange(y_min, y_max, step_size))
    # 構建網格資料
    mesh_output = classifier.predict(np.c_[x_values.ravel(), y_values.ravel()])
    mesh_output = mesh_output.reshape(x_values.shape) 
    plt.figure()
    plt.pcolormesh(x_values, y_values, mesh_output, cmap=plt.cm.gray)
    plt.scatter(X[:, 0], X[:, 1], c=y, s=80, edgecolors='black', linewidth=1, cmap=plt.cm.Paired)
    # specify the boundaries of the figure
    plt.xlim(x_values.min(), x_values.max())
    plt.ylim(y_values.min(), y_values.max())

    # specify the ticks on the X and Y axes
    plt.xticks((np.arange(int(min(X[:, 0])-1), int(max(X[:, 0])+1), 1.0)))
    plt.yticks((np.arange(int(min(X[:, 1])-1), int(max(X[:, 1])+1), 1.0)))

    plt.show()
複製程式碼

然後直接呼叫該繪圖函式,檢視該邏輯迴歸分類器在訓練集上的分類效果。

plot_classifier(classifier, X, y)
複製程式碼

邏輯迴歸分類器的分類效果

########################小**********結###############################

1,使用sklearn模組中的LogisticRegression函式可以輕鬆的定義和訓練一個邏輯迴歸分類器模型。

2,由於此處採用分類器的預設引數,而不是最適合引數,故而得到的分類效果並不是最佳,比如從圖中可以看出,雖然該分類模型能夠將三個類別區分開來,但是其模型明顯還可以繼續優化。

#################################################################


3. 對分類模型的優化

邏輯迴歸分類器有兩個最重要的引數:solver和C,其中引數solver用於設定求解系統方程的演算法型別,引數C表示對分類錯誤的懲罰值,故而C越大,表明該模型對分類錯誤的懲罰越大,即越不能接受分類發生錯誤。

此處,作為拋磚引玉,可以優化C值對分類效果的影響,如下,我們隨機選擇幾種C值,然後將分類結果圖畫出來,憑藉直觀感受來判斷哪一個比較好。當然,更科學的做法是,使用測試集結合各種評估指標來綜合評價那個引數組合下的模型最好。

# 優化模型中的引數C
for c in [1,5,20,50,100,200,500]:
    classifier = LogisticRegression(C=c,random_state=37)
    classifier.fit(X, y)
    plot_classifier(classifier, X, y)
# 貌似C越多,分類的效果越好。
複製程式碼

C=5時邏輯迴歸分類器的分類效果

C=100時邏輯迴歸分類器的分類效果

C=500時邏輯迴歸分類器的分類效果

########################小**********結###############################

1,對模型進行優化是一項體力活,也是最能考驗機器學習技術功底的工作,此處作為拋磚引玉,我們僅僅優化了邏輯迴歸分類器的一個引數。

2,邏輯迴歸分類器的C值越大,得到的分類器模型就越在兩個資料集中間區分開來,這也符合我們的預期,那麼,是否有必要在一開始時就設定非常大的C值?

#################################################################


注:本部分程式碼已經全部上傳到(我的github)上,歡迎下載。

參考資料:

1, Python機器學習經典例項,Prateek Joshi著,陶俊傑,陳小莉譯

相關文章