天天看點

【統計學習方法】感覺機前言感覺機程式實作

【統計學習方法】感覺機

  • 前言
  • 感覺機
    • 概念簡述
    • 學習算法
      • ① 随機梯度下降法
      • ② 對偶形式
        • Gram矩陣
  • 程式實作
    • 自程式設計實作
    • sklearn實作

前言

寫這個文章也是為了督促自己把短時間學到的知識搞清楚,也把記在筆記上的,書上的,程式上的知識整合一下,據說挂深度之眼的名,後續還能領點東西,就寫上了,目标還是寫一個自己能給自己講明白的學習筆記。

感覺機

概念簡述

(1)訓練一個感覺機模型,試着用我的話總結一下,就是用一條線(稱為超平面,二維是一條線,三維是一個面)來将平面中已知的正&負點(二分類)分隔開來的工作。

感覺機的數學模型(所有超平面的集合)如下:

【統計學習方法】感覺機前言感覺機程式實作

(2)那麼一上來随便標明的初始超平面一定是不準的,怎麼衡量好壞呢,就涉及到了損失函數,表示為:誤分類點到超平面的總距離,數學表示如下:

【統計學習方法】感覺機前言感覺機程式實作

(3)有了初始的不準确超平面,怎麼一步一步得到準确超平面呢,就涉及到了感覺機的學習算法:

學習算法

① 随機梯度下降法

其實就是感覺機的原始方法,給定初始學習率η,以及權值w,偏置b的初值,在輸入的訓練資料集中随機選出一個點,看在目前超平面劃分下,這個點是不是分對了,對了就不做改動,再選一個,錯了就更改超平面參數,數學表示如下:

【統計學習方法】感覺機前言感覺機程式實作
【統計學習方法】感覺機前言感覺機程式實作

當周遊了所有的點,一個感覺機模型就訓練好了,這也解釋了兩個問題:

1.想要用感覺機模型,輸入訓練集必須是線性可分的,要不然二維平面中輸入一大堆不可分的點,用來分割的這條線可能會在訓練集中來回跳動,直到最大疊代次數了,也不會把所有的點分開;

2.模型不是唯一的,因為一旦所有的點全分對了,這條線就不動了,那麼正序判斷到第n個點停止,與倒序判斷到第一個點停止,所得的模型顯然是不同的。

② 對偶形式

在我看來,對偶形式是原始形式在計算邏輯上進行優化的結果,對偶形式瞄準的是w和b在周遊所有點之後的增量,對偶形式的參數更新數學表示如下:

【統計學習方法】感覺機前言感覺機程式實作

那麼就進行如下更新:

【統計學習方法】感覺機前言感覺機程式實作

最終學習結束後展現到w,b上的數學表示如下:

【統計學習方法】感覺機前言感覺機程式實作

其中:

【統計學習方法】感覺機前言感覺機程式實作

對偶形式的邏輯,我的了解這樣的:

在原始形式下,計算的邏輯是先找錯誤分類點,找到了則對超平面更新,然後循環到結束。這裡在找誤分類點以及更新的時候都需要進行一些重複備援的計算(相比于對偶形式)

而對偶形式,相當于是一次把所有的誤分類點都找一遍,最後把所有誤分類點的更新進行加和,一次性更新,另外,從α(i)的更新規則可以看出,這是一個計數形式的更新,每多一個點,就增加一個步長(學習率η),在計算上,确實省下了很多功夫。

Gram矩陣

這個矩陣的來源是用w,b判斷誤分類點時,需要用wx(j),而在計算更新w值時,用到了w = w + ηy(i)*x(i),也就是說涉及到了x元素的一個内積,就是下圖紅框中的這部分:

【統計學習方法】感覺機前言感覺機程式實作

那麼如果提前把整個内積算出來,就省下了很多的計算成本,也就是Gram矩陣了。

程式實作

這也是我第一次接觸python程式設計,是以程式是完全或者部分參考示例程式給出的,目的是弄懂整個程式設計的思想以及學會各個庫的使用

程式設計的題目如下:

【統計學習方法】感覺機前言感覺機程式實作

使用工具:PyCharm & Anaconda

自程式設計實作

用到的庫:

import numpy as np
import matplotlib.pyplot as plt
           

預測函數(類):

class MyPerceptron:
	def __init__(self):
	    self.w = None
	    self.b = 0
	    self.l_rate = 1
           

這裡w參數的次元是與輸入的x的次元相關的,是以需要先定義為None,b是常數設定為0,學習率設定為1。

def fit(self,X_train,y_train):
	    #用樣本點的特征數更新初始w,如x1=(3,3)T,
	    #有兩個特征,則self.w=[0,0]
	    self.w=np.zeros(X_train.shape[1])
	    i=0
	    while i<X_train.shape[0]:
	        X=X_train[i]
	        y=y_train[i]
	        # 如果y*(wx+b)≤0 說明是誤判點,更新w,b
	        if y*(np.dot(self.w, X) + self.b) <= 0:
	            self.w = self.w + self.l_rate * np.dot(y, X)
	            self.b = self.b + self.l_rate * y
	            i=0 #如果是誤判點,從頭進行檢測
	        else:
	            i+=1
           

這裡涉及到numpy的一些基礎知識,我也是邊看邊學的:

np.zeros()函數:定義一個全0數組,大小由輸入參數指定;

np.dot()函數:傳回兩向量的内積(對應元素乘積後求和)或者是傳回兩矩陣的乘積(正常的矩陣乘法)

繪圖函數:

對應語句分别加了注釋

def draw(X, w, b):
    # 産生分離超平面上的兩點
    X_new = np.array([[0], [6]])
    y_predict = -b - (w[0] * X_new) / w[1]   
    
    plt.plot(X[:2, 0], X[:2, 1], "g*", label="1")   # 畫正執行個體散點
    plt.plot(X[2:, 0], X[2:, 1], "rx", label="-1")  # 畫負執行個體散點
    plt.plot(X_new, y_predict, "b-")  # 畫出超平面
    plt.axis([0, 6, 0, 6])  # 設定坐标軸範圍
    plt.xlabel('x1')  # X軸标簽
    plt.ylabel('x2')  # Y軸标簽
    plt.title('Day2_test')  # 圖檔标題
    plt.legend()  # 顯示圖例(圖例由上邊"label"給出)
    plt.show()    # 顯示圖像
           

最後是主函數:

def main():
    # 構造訓練資料集
    X_train=np.array([[3,3],[4,3],[1,1]])
    y_train=np.array([1,1,-1])
    # 建構感覺機對象,對資料集繼續訓練
    perceptron=MyPerceptron()
    perceptron.fit(X_train,y_train)  # 預測函數中定義
    print(perceptron.w)
    print(perceptron.b)
    # 結果圖像繪制
    draw(X_train,perceptron.w,perceptron.b)
           

sklearn實作

用到的庫:

import numpy as np
from sklearn.linear_model import Perceptron
           

其中sklearn庫是從Anaconda中搜尋scikit-learn庫得到的。

代碼如下:

X_train = np.array([[3, 3], [4, 3], [1, 1]])
y = np.array([1, 1, -1])
perceptron = Perceptron(max_iter=1000, tol=1e-3)
perceptron.fit(X_train, y)
print("w:", perceptron.coef_, "\n", "b:", perceptron.intercept_, "\n", "n_iter:", perceptron.n_iter_) 
# n_iter:總的疊代次數
res = perceptron.score(X_train, y)
print("correct rate:{:.0%}".format(res))
           

其中涉及到的perceptron類的一些參數及方法如下:

【統計學習方法】感覺機前言感覺機程式實作

上述(屬性-變量)是perceptron類的輸出參數;

【統計學習方法】感覺機前言感覺機程式實作

上圖中涉及到的參數就是在調用perceptron類時,可以傳入的參數;

另注:L1&L2正則化

【統計學習方法】感覺機前言感覺機程式實作

運作結果如下:

【統計學習方法】感覺機前言感覺機程式實作

繼續閱讀