【火炉炼AI】机器学习008-简单线性分类器解决二分类问题
【火爐煉AI】機器學習008-簡單線性分類器解決二分類問題
(本文所使用的Python庫和版本號: Python 3.5, Numpy 1.14, scikit-learn 0.19, matplotlib 2.2 )
分類問題,就是將數據點按照不同的類別區分開來,所謂人以類聚,物以群分,就是這個道理。以前的【機器學習001-007】都是講解的回歸問題,兩者的不同之處在于:回歸輸出的結果是實數,并且一般是連續的實數值,而分類問題的輸出結果是離散的某一個類別或不同類別的概率。
最簡單的分類問題是二元分類,將整個樣本劃分為兩個類別,比如將整個人類分為男人和女人(泰國人妖不在考慮范圍內,呵呵)。稍微復雜一點的分類問題是多元分類,它將整個樣本劃分為多個(一般大于兩個)不同類別,比如將家禽數據集可以劃分為:雞,鴨,鵝等,將家畜樣本劃分為:狗,豬,牛,羊等等。
下面從一個最簡單的二元分類問題入手,看看二元分類器是如何構建的。
1. 準備數據集
由于二元分類問題比較簡單,此處我們自己構建了一些數據點,并將這些數據點按照不同類別放入不同變量中,比如把所有第0類別的數據點都放置到class_0中,把所有第1類別的數據點放入class_1中,如下所示。
# 首先準備數據集 # 特征向量 X = np.array([[3,1], [2,5], [1,8], [6,4], [5,2], [3,5], [4,7], [4,-1]]) # 自定義的數據集 # 標記 y = [0, 1, 1, 0, 0, 1, 1, 0]# 由于標記中只含有兩類,故而將特征向量按照標記分割成兩部分 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_0=np.array([X[i] for i in range(len(X)) if y[i]==0]) # print(class_0) # class_1=np.array([X[i] for i in range(len(X)) if y[i]==1]) # print(class_1) 復制代碼-------------------------------------輸---------出--------------------------------
[[ 3 1] [ 6 4] [ 5 2] [ 4 -1]] [[2 5] [1 8] [3 5] [4 7]]
--------------------------------------------完-------------------------------------
上面雖然構建了數據點,但是難以直觀的看清這個二分類問題的數據點有什么特點,所以為了有更加直觀的認識,一般會把數據點的散點圖畫出來,如下所示:
# 在圖中畫出這兩個不同類別的數據集,方便觀察不同類別數據的特點 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.legend() 復制代碼########################小**********結###############################
1,本次研究的二分類問題是極其簡單的分類問題,故而構建了8個樣本的兩個類別的數據點,每個類別有四個點。
2,為了更加直觀的查看數據點的分布特點,一般我們要把數據點畫在平面上,對數據點的分布情況有一個初步的了解,便于后面我們采用哪種分類器。
3,本次構建的數據集是由8行2列構成的特征矩陣,即8個樣本,每個樣本有兩個features.
#################################################################
2. 構建簡單線性分類器
所謂線性可分問題,是指在平面上可以通過一條直線(或更高維度上的,一個平面)來將所有數據點劃分開來的問題,“可以用直線分開”是線性可分問題的本質。相對應的,“不可以用直線分開”便是線性不可分問題的本質,對于線性不可分問題,需要用曲線或曲面來將這些數據分開,對應的就是非線性問題。比如,上面自己定義的數據集可以用簡單的直線劃分開來,比如可以采用y=x這條直線分開,如下所示:
# 從上面圖中可以看出,可以畫一條直線輕松的將class_0和class_1兩個數據點分開 # 其實有很多直線可以起到分類器的效果,此處我們只用最簡單的y=x作為演示 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.plot(range(10),range(10),label='line_classifier') # 此處x=range(10), y=x plt.legend() 復制代碼實際上,可以采用非常多的直線來將本數據集的兩個類別區分開來,如下圖所示,這些直線是在斜率和截距上稍微調整而來。
那么,這么多直線都可以解決簡單分類問題,肯定會有一條最佳直線,能夠達到最佳的分類效果。下面,使用sklearn模塊中的SGD分類器構建最佳直線分類器。如下代碼:
# 上面雖然隨機的選擇了一條直線(y=x)作為分類器,但很多時候我們不知道分類 # 下面構建一個SGD分類器,它使用隨機梯度下降法來訓練 # 訓練之前需要對數據進行標準化,保證每個維度的特征數據方差為1,均值為0,避免某個特征值過大而成為影響分類的主因 from sklearn.preprocessing import StandardScaler ss=StandardScaler() X_train=ss.fit_transform(X) # 由于本項目數據集太少,故而全部用來train# 構建SGD分類器進行訓練 from sklearn.linear_model import SGDClassifier sgdClassifier=SGDClassifier(random_state=42) sgdClassifier.fit(X_train,y) # y作為label已經是0,1形式,不需進一步處理# 使用訓練好的SGD分類器對陌生數據進行分類 X_test=np.array([[3,2],[2,3],[2.5,2.4],[2.4,2.5],[5,8],[6.2,5.9]]) X_test=ss.fit_transform(X_test) # test set也要記過同樣的處理 test_predicted=sgdClassifier.predict(X_test) print(test_predicted) 復制代碼-------------------------------------輸---------出--------------------------------
[0 1 1 1 1 0]
--------------------------------------------完-------------------------------------
########################小**********結###############################
1,使用sklearn中的SGDClassifier可以對數據集進行簡單的線性分類,達到比較好的分類效果。
2,在數據集的特征上,貌似x>y時,數據屬于class_0, 而x<y時,數據屬于class_1,SGDClassifier模型在測試數據集上也基本能夠正確劃分,只有在x和y大體相等的關鍵點處容易出現錯誤判斷。
#################################################################
注:本部分代碼已經全部上傳到(我的github)上,歡迎下載。
參考資料:
1, Python機器學習經典實例,Prateek Joshi著,陶俊杰,陳小莉譯
總結
以上是生活随笔為你收集整理的【火炉炼AI】机器学习008-简单线性分类器解决二分类问题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 二进制图片转换成BMP位图(C++)
- 下一篇: js 对象