【火爐煉AI】機(jī)器學(xué)習(xí)008-簡(jiǎn)單線(xiàn)性分類(lèi)器解決二分類(lèi)問(wèn)題

【火爐煉AI】機(jī)器學(xué)習(xí)008-簡(jiǎn)單線(xiàn)性分類(lèi)器解決二分類(lèi)問(wèn)題

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

分類(lèi)問(wèn)題,就是將數(shù)據(jù)點(diǎn)按照不同的類(lèi)別區(qū)分開(kāi)來(lái),所謂人以類(lèi)聚,物以群分,就是這個(gè)道理。以前的【機(jī)器學(xué)習(xí)001-007】都是講解的回歸問(wèn)題,兩者的不同之處在于:回歸輸出的結(jié)果是實(shí)數(shù),并且一般是連續(xù)的實(shí)數(shù)值,而分類(lèi)問(wèn)題的輸出結(jié)果是離散的某一個(gè)類(lèi)別或不同類(lèi)別的概率。

最簡(jiǎn)單的分類(lèi)問(wèn)題是二元分類(lèi),將整個(gè)樣本劃分為兩個(gè)類(lèi)別,比如將整個(gè)人類(lèi)分為男人和女人(泰國(guó)人妖不在考慮范圍內(nèi),呵呵)。稍微復(fù)雜一點(diǎn)的分類(lèi)問(wèn)題是多元分類(lèi),它將整個(gè)樣本劃分為多個(gè)(一般大于兩個(gè))不同類(lèi)別,比如將家禽數(shù)據(jù)集可以劃分為:雞,鴨,鵝等,將家畜樣本劃分為:狗,豬,牛,羊等等。

下面從一個(gè)最簡(jiǎn)單的二元分類(lèi)問(wèn)題入手,看看二元分類(lèi)器是如何構(gòu)建的。


1. 準(zhǔn)備數(shù)據(jù)集

由于二元分類(lèi)問(wèn)題比較簡(jiǎn)單,此處我們自己構(gòu)建了一些數(shù)據(jù)點(diǎn),并將這些數(shù)據(jù)點(diǎn)按照不同類(lèi)別放入不同變量中,比如把所有第0類(lèi)別的數(shù)據(jù)點(diǎn)都放置到class_0中,把所有第1類(lèi)別的數(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)記中只含有兩類(lèi),故而將特征向量按照標(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)

-------------------------------------輸---------出--------------------------------

[[ 3 1]
[ 6 4]
[ 5 2]
[ 4 -1]]
[[2 5]
[1 8]
[3 5]
[4 7]]

--------------------------------------------完-------------------------------------

上面雖然構(gòu)建了數(shù)據(jù)點(diǎn),但是難以直觀(guān)的看清這個(gè)二分類(lèi)問(wèn)題的數(shù)據(jù)點(diǎn)有什么特點(diǎn),所以為了有更加直觀(guān)的認(rèn)識(shí),一般會(huì)把數(shù)據(jù)點(diǎn)的散點(diǎn)圖畫(huà)出來(lái),如下所示:

# 在圖中畫(huà)出這兩個(gè)不同類(lèi)別的數(shù)據(jù)集,方便觀(guān)察不同類(lèi)別數(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()
兩個(gè)類(lèi)別數(shù)據(jù)集的分布圖

########################小**********結(jié)###############################

1,本次研究的二分類(lèi)問(wèn)題是極其簡(jiǎn)單的分類(lèi)問(wèn)題,故而構(gòu)建了8個(gè)樣本的兩個(gè)類(lèi)別的數(shù)據(jù)點(diǎn),每個(gè)類(lèi)別有四個(gè)點(diǎn)。

2,為了更加直觀(guān)的查看數(shù)據(jù)點(diǎn)的分布特點(diǎn),一般我們要把數(shù)據(jù)點(diǎn)畫(huà)在平面上,對(duì)數(shù)據(jù)點(diǎn)的分布情況有一個(gè)初步的了解,便于后面我們采用哪種分類(lèi)器。

3,本次構(gòu)建的數(shù)據(jù)集是由8行2列構(gòu)成的特征矩陣,即8個(gè)樣本,每個(gè)樣本有兩個(gè)features.

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


2. 構(gòu)建簡(jiǎn)單線(xiàn)性分類(lèi)器

所謂線(xiàn)性可分問(wèn)題,是指在平面上可以通過(guò)一條直線(xiàn)(或更高維度上的,一個(gè)平面)來(lái)將所有數(shù)據(jù)點(diǎn)劃分開(kāi)來(lái)的問(wèn)題,“可以用直線(xiàn)分開(kāi)”是線(xiàn)性可分問(wèn)題的本質(zhì)。相對(duì)應(yīng)的,“不可以用直線(xiàn)分開(kāi)”便是線(xiàn)性不可分問(wèn)題的本質(zhì),對(duì)于線(xiàn)性不可分問(wèn)題,需要用曲線(xiàn)或曲面來(lái)將這些數(shù)據(jù)分開(kāi),對(duì)應(yīng)的就是非線(xiàn)性問(wèn)題。比如,上面自己定義的數(shù)據(jù)集可以用簡(jiǎn)單的直線(xiàn)劃分開(kāi)來(lái),比如可以采用y=x這條直線(xiàn)分開(kāi),如下所示:

# 從上面圖中可以看出,可以畫(huà)一條直線(xiàn)輕松的將class_0和class_1兩個(gè)數(shù)據(jù)點(diǎn)分開(kāi)
# 其實(shí)有很多直線(xiàn)可以起到分類(lèi)器的效果,此處我們只用最簡(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()
使用一條直線(xiàn)可以將這兩個(gè)數(shù)據(jù)集分開(kāi)

實(shí)際上,可以采用非常多的直線(xiàn)來(lái)將本數(shù)據(jù)集的兩個(gè)類(lèi)別區(qū)分開(kāi)來(lái),如下圖所示,這些直線(xiàn)是在斜率和截距上稍微調(diào)整而來(lái)。

可以分開(kāi)的直線(xiàn)有很多條

那么,這么多直線(xiàn)都可以解決簡(jiǎn)單分類(lèi)問(wèn)題,肯定會(huì)有一條最佳直線(xiàn),能夠達(dá)到最佳的分類(lèi)效果。下面,使用sklearn模塊中的SGD分類(lèi)器構(gòu)建最佳直線(xiàn)分類(lèi)器。如下代碼:

# 上面雖然隨機(jī)的選擇了一條直線(xiàn)(y=x)作為分類(lèi)器,但很多時(shí)候我們不知道分類(lèi)
# 下面構(gòu)建一個(gè)SGD分類(lèi)器,它使用隨機(jī)梯度下降法來(lái)訓(xùn)練
# 訓(xùn)練之前需要對(duì)數(shù)據(jù)進(jìn)行標(biāo)準(zhǔn)化,保證每個(gè)維度的特征數(shù)據(jù)方差為1,均值為0,避免某個(gè)特征值過(guò)大而成為影響分類(lèi)的主因
from sklearn.preprocessing import StandardScaler
ss=StandardScaler()
X_train=ss.fit_transform(X) # 由于本項(xiàng)目數(shù)據(jù)集太少,故而全部用來(lái)train

# 構(gòu)建SGD分類(lèi)器進(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分類(lèi)器對(duì)陌生數(shù)據(jù)進(jìn)行分類(lèi)
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)

-------------------------------------輸---------出--------------------------------

[0 1 1 1 1 0]

--------------------------------------------完-------------------------------------

########################小**********結(jié)###############################

1,使用sklearn中的SGDClassifier可以對(duì)數(shù)據(jù)集進(jìn)行簡(jiǎn)單的線(xiàn)性分類(lèi),達(dá)到比較好的分類(lèi)效果。

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著,陶俊杰,陳小莉譯

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容