機器學習作業---支持向量機SVM(一)了解SVM


推文:支持向量機通俗導論(理解SVM的三層境界)

----------------線性核函數-----------------

一:作業介紹

在本練習的前半部分,您將使用支持向量機。各種示例2D數據集。使用這些數據集進行實驗將幫助您直觀地了解支持向量機如何工作,以及如何使用支持向量機的高斯內核。

二:導入數據和數據可視化

(一)數據導入

data = sio.loadmat("ex6data1.mat")

X = data['X']
y = data['y'].flatten()
m = y.size

print(X.shape,y.shape)

(二)數據顯示

print("X:\n",X[:10,])
print("y:\n",y[:10])

(三)數據可視化

def plot_data(X,y):
    posX = X[np.where(y==1)]    #獲取正樣本
    negX = X[np.where(y==0)]    #獲取負樣本

    plt.scatter(posX[:,0],posX[:,1],c='b',marker='X')   #散點圖繪制 正樣本
    plt.scatter(negX[:,0],negX[:,1],c='r',marker='o')   #散點圖繪制 負樣本
plt.figure()
plot_data(X,y)
plt.show()

可以看出左上角的那個數據點為異常點(誤差點)。

(四)獲取橫軸、、豎軸最值。后面繪制決策邊界需要

print(np.min(X[:,0]),np.max(X[:,0]))    #0.086405 4.015
print(np.min(X[:,1]),np.max(X[:,1]))    #1.6177 4.6162

所以我們對於橫軸取值范圍為(-0.5,4.5),豎軸取值范圍為(1.3,5)

三:svm模塊之線性核函數 

sklearn提供了很多機器學習的庫,本次作業主要也是用它來解決SVM的問題

重點補充numpy.meshgrid()理解

https://blog.csdn.net/lllxxq141592654/article/details/81532855

(一)C=1時(C較小時,相當於入較大(平滑,泛化能力好),可能會導致欠擬合,高偏差),不因為一個異常點影響“大邊界”

1.獲取分類器的准確率

c = 1
clf = svm.SVC(c,kernel="linear",tol=1e-3)   #實例化分類器,C為誤差項懲罰系數,核函數選擇線性核,停止訓練的誤差值大小,默認為1e-3。https://blog.csdn.net/weixin_41990278/article/details/93137009
clf.fit(X,y)    #導入數據進行訓練

print(clf.score(X,y))   #分類器的准確率

2.繪制決策邊界《重點》

#繪制決策邊界
def plot_boundary(model):
    x_min,x_max = -0.5,4.5
    y_min, y_max = 1.3, 5 # 生成網格點坐標矩陣
    xx,yy = np.meshgrid(np.linspace(x_min,x_max,500),   #xx (500, 500) yy (500, 500)
                       np.linspace(y_min,y_max,500))
    # print(xx.shape,yy.shape)
    # print(np.c_[xx.flatten(), yy.flatten()].shape)  #(250000, 2)--->對應了網格點坐標矩陣中的每一個坐標點 # 用訓練好的分類器去預測各個坐標點中的數據的標簽為[1]的值(其他為0)---全為1的位置就是決策邊界
    z = model.predict(np.c_[xx.flatten(), yy.flatten()])    #z (250000,)
    # print(z.shape)
    # for i in range(z.size):   #z中全為0、1值
    #     if z[i] != 0:
    #         print(z[i])
    zz = z.reshape(xx.shape)    #將我們預測出來的z值有一維空間,轉換為二維網格坐標矩陣,便於在二維平面繪制決策邊界
    plt.contour(xx, yy, zz) #繪制決策邊界 xx,yy是矩陣坐標,zz是我們對各個坐標的賦值,其中為1 的地方就是我們要找的決策邊界
data = sio.loadmat("ex6data1.mat")

X = data['X']
y = data['y'].flatten()
m = y.size

c = 1
clf = svm.SVC(c,kernel="linear",tol=1e-3)   #實例化分類器,C為誤差項懲罰系數,核函數選擇線性核,停止訓練的誤差值大小,默認為1e-3。https://blog.csdn.net/weixin_41990278/article/details/93137009
clf.fit(X,y)    #導入數據進行訓練

plt.figure()

plot_boundary(clf)
plot_data(X,y)
plt.show()

c=1,此時不因為一個異常點影響“大邊界”,擬合效果較好

(二)c=100,可以很好的擬合正類和負類,但由於一個異常點造成過擬合,不能最大邊界

----------------高斯核函數-----------------

一:數據導入及可視化

(一)數據可視化

data = sio.loadmat("ex6data2.mat")

X = data['X']
y = data['y'].flatten()
m = y.size

plt.figure()

plot_data(X,y)
plt.show()

(二)獲取數據上下界

print(np.min(X[:,0]),np.max(X[:,0]))    #0.0449309 0.998848
print(np.min(X[:,1]),np.max(X[:,1]))    #0.402632 0.988596

所以我們繪制決策邊界時,取橫坐標從(0,1)。豎軸(0.4,1)

二:svm模塊之高斯核函數

使用高斯核函數解決線性不可分問題,並觀察 σ取值對模型復雜度的影響。

(一)簡單實現高斯核函數---測試

高斯核函數公式:

def gaussian_kernel(x1,x2,sigma=0.1):
    x1 = x1.flatten()
    x2 = x2.flatten()

    gk = np.exp(-np.sum(np.power((x1-x2),2))/(2*np.power(sigma,2)))

    return gk
x1 = np.array([1,2,1])
x2 = np.array([0,4,-1])
sigma = 2

print(gaussian_kernel(x1,x2,sigma))

(二)調用sklearn中的高斯核函數實現SVM算法

c = 1gamma = 1
clf = svm.SVC(c,kernel="rbf",gamma)   #實例化分類器,C為誤差項懲罰系數,核函數選擇高斯核,設置gamma字段為gamma,注意gamma不等於σ,但是兩者有關聯。https://blog.csdn.net/weixin_41990278/article/details/93137009
clf.fit(X,y)    #導入數據進行訓練

print(clf.score(X,y))   #分類器的准確率

補充:SVM算法中的gamma字段《重點》

此外大家注意RBF公式里面的sigma和gamma的關系如下:

(三)繪制決策邊界---修改坐標范圍即可

#繪制決策邊界
def plot_boundary(model):
 x_min,x_max = 0,1 y_min, y_max = 0.4, 1
    # 生成網格點坐標矩陣
    xx,yy = np.meshgrid(np.linspace(x_min,x_max,500),   #xx (500, 500) yy (500, 500)
                       np.linspace(y_min,y_max,500))
    # print(xx.shape,yy.shape)
    # print(np.c_[xx.flatten(), yy.flatten()].shape)  #(250000, 2)--->對應了網格點坐標矩陣中的每一個坐標點
    # 用訓練好的分類器去預測各個坐標點中的數據的標簽為[1]的值(其他為0)---全為1的位置就是決策邊界
    z = model.predict(np.c_[xx.flatten(), yy.flatten()])    #z (250000,)
    # print(z.shape)
    # for i in range(z.size):   #z中全為0、1值
    #     if z[i] != 0:
    #         print(z[i])
    zz = z.reshape(xx.shape)    #將我們預測出來的z值有一維空間,轉換為二維網格坐標矩陣,便於在二維平面繪制決策邊界
    plt.contour(xx, yy, zz) #繪制決策邊界 xx,yy是矩陣坐標,zz是我們對各個坐標的賦值,其中為1 的地方就是我們要找的決策邊界
plt.figure()

plot_boundary(clf)
plot_data(X,y)
plt.show()

可以看出當gamma=1時,擬合效果並不是很好!!!

(四)不同gamma的選取

1.gamma=1時

分類器的准確率如下:

2.gamma=50

分類器的准確率如下:

3.gamma=1000

分類器的准確率如下:

(五)結論:σ和gamma

sigma和gamma的關系如下:

這里面大家需要注意的就是gamma的物理意義,就是大家提到很多的RBF的幅寬,它會影響每個支持向量對應的高斯的作用范圍,從而影響泛化性能。

1.如果gamma設的太大,σ會很小,σ很小的高斯分布長得又高又瘦, 會造成只會作用於支持向量樣本附近,對於未知樣本分類效果很差,存在訓練准確率可以很高,(如果讓σ無窮小,則理論上,高斯核的SVM可以擬合任何非線性數據,但容易過擬合)而測試准確率不高的可能,就是通常說的過訓練;

2.而如果gamma設的過小,σ會很大,則會造成平滑效應太大,無法在訓練集上得到特別高的准確率,也會影響測試集的准確率。

----------------尋找最優參數 C 和 σ-----------------

一:SVM模型有兩個非常重要的參數C與σ

(一)其中 C是懲罰系數,即對誤差的寬容度。

1.c越高,入越小,容易過擬合。說明越不能容忍出現誤差,

2.C越小,入越大,容易欠擬合。說明可以容忍出現誤差,

C過大或過小,泛化能力變差

(二)σ隱含地決定了數據映射到新的特征空間后的分布

gamma是選擇RBF函數作為kernel后,該函數自帶的一個參數。

從gamma和σ之間關系,可以看出。gamma也隱含地決定了數據映射到新的特征空間后的分布

1.如果gamma設的太大,σ會很小,σ很小的高斯分布長得又高又瘦, 會造成只會作用於支持向量樣本附近,對於未知樣本分類效果很差,存在訓練准確率可以很高,(如果讓σ無窮小,則理論上,高斯核的SVM可以擬合任何非線性數據,但容易過擬合)而測試准確率不高的可能,就是通常說的過訓練;

2.而如果gamma設的過小,σ會很大,則會造成平滑效應太大,無法在訓練集上得到特別高的准確率,也會影響測試集的准確率。

二:加載數據及數據可視化

(一)繪制數據(訓練集數據)

def plot_data(X,y):
    posX = X[np.where(y==1)]    #獲取正樣本
    negX = X[np.where(y==0)]    #獲取負樣本

    plt.scatter(posX[:,0],posX[:,1],c='b',marker='X')   #散點圖繪制 正樣本
    plt.scatter(negX[:,0],negX[:,1],c='r',marker='o')   #散點圖繪制 負樣本
data = sio.loadmat("ex6data3.mat")

X = data['X']
y = data['y'].flatten()
X = data['X']
y = data['y'].flatten()
Xval = data['Xval']
yval = data['yval'].flatten()
m = y.size
plt.figure()

plot_data(X,y)
plt.show()

 

(二)獲取數據最值

print(np.min(X[:,0]),np.max(X[:,0]))    #-0.596774 0.297235
print(np.min(X[:,1]),np.max(X[:,1]))    #-0.657895 0.573392

這里我們取橫軸(-0.6,0.4),豎軸(-0.7,0.6)

三:根據驗證集評分獲取最優准確率和參數(C、σ)

def get_best_params(X,y,Xval,yval):
    # C 和 σ 的候選值
    Cvalues = [3, 10, 30, 100, 0.01, 0.03, 0.1, 0.3, 1]  # 9
    gammas = [1, 3, 10, 30, 100, 0.01, 0.03, 0.1, 0.3]  # 9

    best_score = 0  #用於存放最佳准確率
    best_params = (0,0) #用於存放參數C和σ

    for c in Cvalues:
        for gamma in gammas:
            clf = svm.SVC(c,kernel='rbf',gamma=gamma)
            clf.fit(X,y)    # 用訓練集數據擬合模型
            score = clf.score(Xval,yval)    # 用驗證集數據進行評分
            if score > best_score:
                best_score = score
                best_params = (c,gamma)

    return best_score,best_params
score, params = get_best_params(X,y,Xval,yval)
print("score:\n",score)
print("C gamma:\n",params)

注意:獲取到的最優參數組合不只有一組(可能有多組的評分一樣,都是最優,這里我們使用了>,所以只取了第一個最優的),更改候選值的順序,最佳參數組合及其對應的決策邊界也會改變。

四:根據我們獲得的最優參數,繪制決策邊界

#繪制決策邊界
def plot_boundary(model):
    x_min,x_max = -0.6,0.4
    y_min, y_max = -0.7,0.6
    # 生成網格點坐標矩陣
    xx,yy = np.meshgrid(np.linspace(x_min,x_max,500),   #xx (500, 500) yy (500, 500)
                       np.linspace(y_min,y_max,500))
    # print(xx.shape,yy.shape)
    # print(np.c_[xx.flatten(), yy.flatten()].shape)  #(250000, 2)--->對應了網格點坐標矩陣中的每一個坐標點
    # 用訓練好的分類器去預測各個坐標點中的數據的標簽為[1]的值(其他為0)---全為1的位置就是決策邊界
    z = model.predict(np.c_[xx.flatten(), yy.flatten()])    #z (250000,)
    # print(z.shape)
    # for i in range(z.size):   #z中全為0、1值
    #     if z[i] != 0:
    #         print(z[i])
    zz = z.reshape(xx.shape)    #將我們預測出來的z值有一維空間,轉換為二維網格坐標矩陣,便於在二維平面繪制決策邊界
    plt.contour(xx, yy, zz) #繪制決策邊界 xx,yy是矩陣坐標,zz是我們對各個坐標的賦值,其中為1 的地方就是我們要找的決策邊界
data = sio.loadmat("ex6data3.mat")

X = data['X']
y = data['y'].flatten()
Xval = data['Xval']
yval = data['yval'].flatten()

score, params = get_best_params(X,y,Xval,yval)

c = params[0]
gamma = params[1]
clf = svm.SVC(c,kernel="rbf",gamma=gamma)   #實例化分類器,C為誤差項懲罰系數,核函數選擇線性核,停止訓練的誤差值大小,默認為1e-3。https://blog.csdn.net/weixin_41990278/article/details/93137009
clf.fit(X,y)    #導入數據進行訓練

plt.figure()

plot_boundary(clf)
plot_data(X,y)
plt.show()

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM