【火爐煉AI】機(jī)器學(xué)習(xí)014-用SVM構(gòu)建非線性分類模型
(本文所使用的Python庫(kù)和版本號(hào): Python 3.5, Numpy 1.14, scikit-learn 0.19, matplotlib 2.2 )
支持向量機(jī)(Support Vector Machine,SVM)是一種常見的判別方法吓坚,其基本模型是在特征空間上找到最佳的分離超平面,使得數(shù)據(jù)集上的正負(fù)樣本間隔最大溺欧。SVM用來解決二分類問題的有監(jiān)督學(xué)習(xí)算法,其可以解決線性問題整袁,也可以通過引入核函數(shù)的方法來解決非線性問題告丢。
本項(xiàng)目旨在使用SVM構(gòu)建非線性分類模型來判別數(shù)據(jù)集的不同類別。
1. 準(zhǔn)備數(shù)據(jù)集
首先來加載和查看數(shù)據(jù)集的一些特性慨灭。如下代碼加載數(shù)據(jù)集并查看其基本信息
# 準(zhǔn)備數(shù)據(jù)集
data_path='E:\PyProjects\DataSet\FireAI/data_multivar_2_class.txt'
df=pd.read_csv(data_path,header=None)
# print(df.head()) # 沒有問題
print(df.info()) # 查看數(shù)據(jù)信息,確保沒有錯(cuò)誤
dataset_X,dataset_y=df.iloc[:,:-1],df.iloc[:,-1]
# print(dataset_X.head())
# print(dataset_X.info())
# print(dataset_y.head()) # 檢查沒問題
dataset_X=dataset_X.values
dataset_y=dataset_y.values
-------------------------------------輸---------出--------------------------------
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 300 entries, 0 to 299
Data columns (total 3 columns):
0 300 non-null float64
1 300 non-null float64
2 300 non-null int64
dtypes: float64(2), int64(1)
memory usage: 7.1 KB
None
--------------------------------------------完-------------------------------------
從上面的df.info()函數(shù)的結(jié)果可以看出球及,這個(gè)數(shù)據(jù)集有兩個(gè)特征屬性(0,1列氧骤,連續(xù)的float類型),一個(gè)標(biāo)記(2列吃引,離散的int型筹陵,只有兩個(gè)類別),每一列都沒有缺失值镊尺。然后來看看這個(gè)數(shù)據(jù)集中數(shù)據(jù)點(diǎn)的分布情況朦佩,如下圖所示:
# 數(shù)據(jù)集可視化
def visual_2D_dataset(dataset_X,dataset_y):
'''將二維數(shù)據(jù)集dataset_X和對(duì)應(yīng)的類別dataset_y顯示在散點(diǎn)圖中'''
assert dataset_X.shape[1]==2,'only support dataset with 2 features'
plt.figure()
classes=list(set(dataset_y))
markers=['.',',','o','v','^','<','>','1','2','3','4','8'
,'s','p','*','h','H','+','x','D','d','|']
colors=['b','c','g','k','m','w','r','y']
for class_id in classes:
one_class=np.array([feature for (feature,label) in
zip(dataset_X,dataset_y) if label==class_id])
plt.scatter(one_class[:,0],one_class[:,1],marker=np.random.choice(markers,1)[0],
c=np.random.choice(colors,1)[0],label='class_'+str(class_id))
plt.legend()
visual_2D_dataset(dataset_X,dataset_y)
我以前的很多文章都講到了數(shù)據(jù)集的處理,拆分庐氮,準(zhǔn)備等语稠,此處的數(shù)據(jù)集比較簡(jiǎn)單,故而簡(jiǎn)單講述一下弄砍。
2. 用SVM構(gòu)建線性分類器
你沒有看錯(cuò)仙畦,我就是想用SVM構(gòu)建一個(gè)線性分類器來判別這個(gè)數(shù)據(jù)集。當(dāng)然音婶,即使是入門級(jí)的機(jī)器學(xué)習(xí)攻城獅們慨畸,也能看出,這個(gè)數(shù)據(jù)集是一個(gè)線性不可分類型桃熄,需要用非線性分類器來解決先口。所以型奥,此處瞳收,我就用線性分類器來擬合一下,看看會(huì)有什么樣的“不好”的結(jié)果厢汹。
# 從數(shù)據(jù)集的分布就可以看出螟深,這個(gè)數(shù)據(jù)集不可能用直線分開
# 為了驗(yàn)證我們的判斷,下面還是使用SVM來構(gòu)建線性分類器將其分類
# 將整個(gè)數(shù)據(jù)集劃分為train set和test set
from sklearn.model_selection import train_test_split
train_X, test_X, train_y, test_y=train_test_split(
dataset_X,dataset_y,test_size=0.25,random_state=42)
# print(train_X.shape) # (225, 2)
# print(train_y.shape) # (225,)
# print(test_X.shape) # (75, 2)
# 使用線性核函數(shù)初始化一個(gè)SVM對(duì)象烫葬。
from sklearn.svm import SVC
classifier=SVC(kernel='linear') # 構(gòu)建線性分類器
classifier.fit(train_X,train_y)
-------------------------------------輸---------出--------------------------------
SVC(C=1.0, cache_size=200, class_weight=None, coef0=0.0,
decision_function_shape='ovr', degree=3, gamma='auto', kernel='linear',
max_iter=-1, probability=False, random_state=None, shrinking=True,
tol=0.001, verbose=False)
--------------------------------------------完-------------------------------------
然后查看一下這個(gè)訓(xùn)練好的SVM線性分類器在訓(xùn)練集和測(cè)試集上的表現(xiàn)界弧,如下為在訓(xùn)練集上的性能報(bào)告:
# 模型在訓(xùn)練集上的性能報(bào)告:
from sklearn.metrics import classification_report
plot_classifier(classifier,train_X,train_y) # 分類器在訓(xùn)練集上的分類效果
target_names = ['Class-0', 'Class-1']
y_pred=classifier.predict(train_X)
print(classification_report(train_y, y_pred, target_names=target_names))
-------------------------------------輸---------出--------------------------------
precision recall f1-score support
Class-0 0.60 0.96 0.74 114
Class-1 0.89 0.35 0.50 111
avg / total 0.74 0.66 0.62 225
--------------------------------------------完-------------------------------------
很明顯凡蜻,從分類效果圖和性能報(bào)告中,都可以看出這個(gè)模型很差垢箕,差到姥姥家了划栓。。条获。
所以忠荞,更不用說,在測(cè)試集上的表現(xiàn)了帅掘,當(dāng)然是一個(gè)差字了得委煤。。修档。
# 分類器在測(cè)試集上的分類效果
plot_classifier(classifier,test_X,test_y)
target_names = ['Class-0', 'Class-1']
y_pred=classifier.predict(test_X)
print(classification_report(test_y, y_pred, target_names=target_names))
-------------------------------------輸---------出--------------------------------
precision recall f1-score support
Class-0 0.57 1.00 0.73 36
Class-1 1.00 0.31 0.47 39
avg / total 0.79 0.64 0.59 75
--------------------------------------------完-------------------------------------
3. 用SVM構(gòu)建非線性分類器
很明顯碧绞,用線性分類器解決不了這個(gè)數(shù)據(jù)集的判別問題,所以我們就上馬非線性分類器吧吱窝。
使用SVM構(gòu)建非線性分類器主要是考慮使用不同的核函數(shù)讥邻,此處指講述兩種核函數(shù):多項(xiàng)式核函數(shù)和徑向基函數(shù)。
# 從上面的性能報(bào)告中可以看出癣诱,分類效果并不好
# 故而我們使用SVM建立非線性分類器计维,看看其分類效果
# 使用SVM建立非線性分類器主要是使用不同的核函數(shù)
# 第一種:使用多項(xiàng)式核函數(shù):
classifier_poly=SVC(kernel='poly',degree=3) # 三次多項(xiàng)式方程
classifier_poly.fit(train_X,train_y)
# 在訓(xùn)練集上的表現(xiàn)為:
plot_classifier(classifier_poly,train_X,train_y)
target_names = ['Class-0', 'Class-1']
y_pred=classifier_poly.predict(train_X)
print(classification_report(train_y, y_pred, target_names=target_names))
-------------------------------------輸---------出--------------------------------
precision recall f1-score support
Class-0 0.92 0.85 0.89 114
Class-1 0.86 0.93 0.89 111
avg / total 0.89 0.89 0.89 225
--------------------------------------------完-------------------------------------
# 第二種:使用徑向基函數(shù)建立非線性分類器
classifier_rbf=SVC(kernel='rbf')
classifier_rbf.fit(train_X,train_y)
# 在訓(xùn)練集上的表現(xiàn)為:
plot_classifier(classifier_rbf,train_X,train_y)
target_names = ['Class-0', 'Class-1']
y_pred=classifier_rbf.predict(train_X)
print(classification_report(train_y, y_pred, target_names=target_names))
-------------------------------------輸---------出--------------------------------
precision recall f1-score support
Class-0 0.96 0.96 0.96 114
Class-1 0.96 0.95 0.96 111
avg / total 0.96 0.96 0.96 225
--------------------------------------------完-------------------------------------
########################小**********結(jié)###############################
1. 用SVM構(gòu)建非線性分類器很簡(jiǎn)單,只要使用不同的核函數(shù)就可以撕予。
2. 對(duì)于這個(gè)數(shù)據(jù)集而言鲫惶,使用了非線性分類器之后,分類效果得到了極大的改善实抡,這個(gè)可以從性能報(bào)告中看出欠母,而且,很明顯兩種非線性核函數(shù)吆寨,徑向基函數(shù)rbf的分類效果要比多項(xiàng)式核函數(shù)的效果更好一些赏淌。
3. 這個(gè)模型也許還可以繼續(xù)優(yōu)化一些超參數(shù),從而得到更好的分類效果啄清。
#################################################################
注:本部分代碼已經(jīng)全部上傳到(我的github)上六水,歡迎下載。
參考資料:
1, Python機(jī)器學(xué)習(xí)經(jīng)典實(shí)例辣卒,Prateek Joshi著掷贾,陶俊杰,陳小莉譯