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