1. 程式人生 > >SVM支援向量機-SKlearn實現與繪圖(8)

SVM支援向量機-SKlearn實現與繪圖(8)

瞭解了SVM的基本形式與演算法實現,接下來用SKlearn實現支援向量機分類器.

1.函式定義與引數含義

先看一下SVM函式的完全形式和各引數含義:

SVC(C=1.0kernel=’rbf’degree=3gamma=’auto’coef0=0.0shrinking=Trueprobability=Falsetol=0.001cache_size=200class_weight=Noneverbose=Falsemax_iter=-1decision_function_shape=’ovr’random_state=None)

這裡只介紹一部分,其餘引數可以參考SKlearn.SVM

C:懲罰係數,default = 1.0,同軟間隔中的鬆弛因子

kernel:核函式選擇,default = "rbf",可選 ‘linear’(線性核函式), ‘poly’(多項式核函式), ‘rbf’(高斯核函式), ‘sigmoid’(siigmoid核函式), ‘precomputed’

degree:多項式核函式poly的項數,只有使用poly核函式才會呼叫,其他核函式會忽略

class_weight:{dict,'balanced'},樣本權重,預設均等權重

decision_function_shape:拆分策略,預設ovr,ovo一對一1策略被捨棄

random_state:隨機數生成種子

2.線性可分情況的SVM

                        

1)匯入相關庫與資料讀取函式

#Sklearn SVM支援向量機
from sklearn.svm import SVC
import matplotlib.pyplot as plt
import numpy as np
from sklearn.model_selection import train_test_split

def loadDataSet(fileName):
    dataMat = []; labelMat = []
    fr = open(fileName)
    for line in fr.readlines():
        lineArr = line.strip().split('\t')
        dataMat.append([float(lineArr[0]), float(lineArr[1])])
        labelMat.append(float(lineArr[2]))
    return dataMat,labelMat

2)通過SKlearn返回的引數繪製超平面

def plot_point(dataArr,labelArr,Support_vector_index,W,b):
	for i in range(np.shape(dataArr)[0]):
		if labelArr[i] == 1:
			plt.scatter(dataArr[i][0],dataArr[i][1],c='b',s=20)
		else:
			plt.scatter(dataArr[i][0],dataArr[i][1],c='y',s=20)
	
	for j in Support_vector_index:
		plt.scatter(dataArr[j][0],dataArr[j][1], s=100, c = '', alpha=0.5, linewidth=1.5, edgecolor='red')

	x = np.arange(0,10,0.01)
	y = (W[0][0]*x+b)/(-1*W[0][1])
	plt.scatter(x,y,s=5,marker = 'h')
	plt.show()

3)主函式

if __name__ == "__main__":
	#讀取資料,針對二維線性可分資料
	dataArr,labelArr = loadDataSet('testSet.txt')
	#定義SVM分類器
	clf = 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)
	#fit訓練資料
	clf.fit(dataArr, labelArr) 

	#獲取模型返回值
	n_Support_vector = clf.n_support_#支援向量個數
	Support_vector_index = clf.support_#支援向量索引
	W = clf.coef_#方向向量W
	b =  clf.intercept_#截距項b

	#繪製分類超平面
	plot_point(dataArr,labelArr,Support_vector_index,W,b)

clf.n_support_返回支援向量個數1,會返回一個1x2的列表,分別表示決策函式兩邊各有幾個支撐向量

clf.suspport_返回支援向量的索引,通過對應索引,即可在圖中標記支援向量

clf.coef_返回方向向量W,即超平面引數

clf.intercept_返回超平面截距項b

tips:這裡幾種用法只有kernel=“linear”才可以上使用,而其他幾種核函式無法呼叫,所以我們這裡只能在二維繪製超平面.

4)執行結果

                    

3.線性不可分情況的SVM

                    

1)匯入相關庫與讀取資料

#Sklearn SVM支援向量機
from sklearn.svm import SVC
import matplotlib.pyplot as plt
import numpy as np
from sklearn.model_selection import train_test_split

def loadDataSet(fileName):
    dataMat = []; labelMat = []
    fr = open(fileName)
    for line in fr.readlines():
        lineArr = line.strip().split('\t')
        dataMat.append([float(lineArr[0]), float(lineArr[1])])
        labelMat.append(float(lineArr[2]))
    return dataMat,labelMat

2)標記支援向量

def plot_point(dataArr,labelArr,Support_vector_index):
	for i in range(np.shape(dataArr)[0]):
		if labelArr[i] == 1:
			plt.scatter(dataArr[i][0],dataArr[i][1],c='b',s=20)
		else:
			plt.scatter(dataArr[i][0],dataArr[i][1],c='y',s=20)
	
	for j in Support_vector_index:
		plt.scatter(dataArr[j][0],dataArr[j][1], s=100, c = '', alpha=0.5, linewidth=1.5, edgecolor='red')
        plt.show()

由於沒有使用線性核函式,所以沒有呼叫w,b,只標記支援向量

3)主函式

if __name__ == "__main__":
	#讀取資料,針對二維線性不可分資料
	dataArr,labelArr = loadDataSet('testSetRBF.txt')
	for i in range(np.shape(dataArr)[0]):
		if labelArr[i] == 1:
			plt.scatter(dataArr[i][0],dataArr[i][1],c='b',s=20)
		else:
			plt.scatter(dataArr[i][0],dataArr[i][1],c='y',s=20)
	plt.show()
	#交叉驗證劃分資料集,train:test = 0.8 : 0.2
	X_train, X_test, y_train, y_test = train_test_split(dataArr,labelArr, test_size=.2,random_state = 0)
	#初始化模型引數
	clf = SVC(cache_size=200, class_weight=None, coef0=0.0,C=1.0,
	    decision_function_shape='ovr', degree=3, gamma='auto', kernel='rbf',
	    max_iter=-1, probability=False, random_state=None, shrinking=True,
	    tol=0.001, verbose=False)
	clf.fit(X_train,y_train)
	#預測X_test
	predict_list = clf.predict(X_test)
	#預測精度
	precition = clf.score(X_test,y_test)
	print('precition is : ',precition*100,"%")
	#獲取模型返回值
	n_Support_vector = clf.n_support_#支援向量個數
	print("支援向量個數為: ",n_Support_vector)
	Support_vector_index = clf.support_#支援向量索引
	plot_point(dataArr,labelArr,Support_vector_index)

這裡採用交叉驗證和rbf高斯核函式,對線性不可分資料進行預測,訓練集與測試集劃分比例為0.8:0.2

clf.predict:給定資料集,預測資料集類別

clf.score:給予訓練集與訓練集標籤獲取預測精度

4)執行結果

precition is :  100.0 %
支援向量個數為:  [27 26]
[Finished in 3.8s]

精度為100%,支援向量共53個,一邊27個,一邊26個支援向量.

                        

總結:

這裡精度達到100%,說明分類效果不錯,不過一般情況下不會出現100%的預測精度,這裡只是簡單的介紹了二維線性可分和二維線性不可分資料集,對於更高維的資料,支援向量機也總能發揮出比較好的效能,可以改造load_data函式實現資料讀取然後用svm預測,而對於多分類問題,可以使用整合學習,構建多個支援向量分類器提高效能,一般預設先使用rbf高斯核,然後再嘗試其他核函式,用交叉驗證法評價分類效果.SVM相關就先寫到這,這裡只寫了8篇,但對於支援向量機而言,可能80篇也寫不完,所以還有更多的知識需要學習探索~