1. 程式人生 > >機器學習回顧篇(10):感知機模型

機器學習回顧篇(10):感知機模型

 

注:本系列所有部落格將持續更新併發布在github和gitee上,您可以通過github、gitee下載本系列所有文章筆記檔案。

 

1 引言¶

感知機是一種簡單且易於實現的二分類判別模型,主要思想是通過誤分類驅動的損失函式結合梯度下降發求解一個超平面將線性可分的資料集劃分為兩個不同的類別(+1類和-1類)。
在神經網路、支援向量機等演算法盛行的當下,感知機模型應用得並不多,但必須承認,感知機卻是神經網路和支援向量機的基礎,所以還是很有必要學習一下的,本文接下來的內容將從感知機數學描述、損失函式、兩種不同學習形式等方面詳細介紹感知機,最後使用Python實現感知機兩種學習形式。

 

2 感知機模型及損失函式¶

2.1 數學描述¶

對於給定訓練樣本資料集$D = \{ ({x_i},{y_i})\} _{i = 1}^m$,${x_i} \in X \subseteq {R^n}$表示訓練樣本的特徵向量,${y_i} \in Y = \{ + 1, - 1\} $表示樣本類別。$x$與$y$之間的如下函式關係: $$y = f(x) = sign(w \cdot x + b)$$ 稱為感知機。其中,$w \in {R^n}$稱為感知機的權值係數或者權值向量,$b \in R$稱為偏置,$sign$是符號函式,有: $$sign = \left\{ {_{ - 1, x < 0}^{ + 1, x \geqslant 0}} \right.$$ 從定義上可以看出,感知機最終目標就是求解出$w$和$b$。我們可以從幾何上對感知機進行理解,如果以$w$為法向量,以$b$為截距,可以確定一超平面: $$w \cdot x + b = 0$$ 通過這一超平面,可以順利將對資料集進行劃分。以二維資料為例,如下圖所示,當樣本點$x$剛好落在超平面上時,有$w \cdot x + b = 0$,當$x$落在超平面下方時,有$w \cdot x + b < 0$,通過$sign$函式後輸出為$-1$,也就是標記為$-1$類;當$x$落在超平面上方時,有$w \cdot x + b > 0$,通過$sign$函式後輸出為$+1$,也就是標記為$+1$類。注意,這樣的超平面一般不唯一,也就是說感知機最終解可以有很多個,受引數初始值、訓練樣本輸入順序等因素的影響,每次訓練時所獲得的超平面都可能不一樣。

 

2.2 損失函式¶

為了求解引數$w$和$b$,確定最終的分割超平面,我們需要定義一個目標函式或者說損失函式,通過最小化損失函式來達到目的。在感知機模型中,以誤分類的樣本物件與分割超平面間的距離之和最為損失函式。我們高中時學過,對於點$({x_0},{y_0})$,到平面$A \cdot x + B \cdot y + C = 0$的距離為: $$dist = \frac{{|A \cdot {x_0} + B \cdot {y_0} + C|}}{{\sqrt {{A^2} + {B^2}} }} $$ 將這一公式擴充套件到超平面中,對於超平面$w \cdot x + b = 0$,誤分類點$x_i$到超平面的距離為: $$dist = \frac{{|w \cdot xi + b|}}{{\left\| w \right\|}} $$ 式中,${\left\| w \right\|}$是$w$的$L_2$範數,等同於上面的${\sqrt {{A^2} + {B^2}} }$。 為了方便計算,我們需要將分子中的絕對值去掉,怎麼去掉呢?因為$({x_i},{y_i})$是誤分類樣本點,$y_i$與${w \cdot xi + b}$一定是異號的,所以: $$ - {y_i} \cdot (w \cdot x_i + b) > 0 $$ 且因為$|{y_i}| = 1$,所以: $$ - {y_i} \cdot (w \cdot x_i + b) = |w \cdot x_i + b| $$ 於是,$({x_i},{y_i})$到超平面的距離可以表示為: $$\frac{{ - {y_i} \cdot (w \cdot x_i + b)}}{{\left\| w \right\|}} $$ 假設$M$是所有誤分類點組成的集合,那麼所有誤分類點到超平面距離總和為: $$\sum\limits_{{x_i} \in M} {\frac{{ - {y_i} \cdot (w \cdot {x_i} + b)}}{{\left\| w \right\|}}} \tag{1}$$ 這就是我們需要的損失函式的雛形了,之所以說是雛形,是因為我們還可以通過令$\left\| w \right\|{\text{ = }}1$對上式進一步化簡,於是有: $$L(w,b) = \sum\limits_{{x_i} \in M} { - {y_i} \cdot (w \cdot {x_i} + b)} \tag{2}$$ $L(w,b)$就是我們最終需要的損失函式。 為什麼可以直接令$\left\| w \right\|{\text{ = }}1$來化簡式(1)呢?

我們可以在權值向量$w$中新增一個$w_0$元素,在特徵向量$x_i$中新增一個第0緯度${x^{(0)}} = 1$,令偏置$b = {w_0} \cdot {x^{(0)}}$,這樣,我們就把偏置$b$也放進了權值向量$w$中,那式(1)就變為: $$\sum\limits_{{x_i} \in M} {\frac{{ - {y_i} \cdot w \cdot {x_i}}}{{\left\| w \right\|}}} $$ 此時,分子和分母都含有$w$,當分子的$w$擴大$N$倍時,分母的$L_2$範數也會擴大N倍。也就是說,分子和分母有固定的倍數關係。那麼我們可以固定分子或者分母為1,然後求分母的倒數或者分子自己的最小化作為損失函式,這樣可以簡化我們的損失函式。在感知機模型中,採用的是保留分子的策略。
另一種解釋,當把偏置$b$包含進$w$後,超平面表示式也簡化成$w \cdot {x_i} = 0$,無論是把$w$擴大多少倍、縮小多少倍,都對超平面沒有影響(就像$x + y - 1 = 0$與$2x + 2y - 2 = 0$始終表示同一條直線),那麼我們總能找到一個倍數,將$w$縮小到滿足${\left\| w \right\|}=1$,但並不影響我們獲得最終的超平面,但是令${\left\| w \right\|}=1$後卻有助於我們化簡和求解。

 

3 優化方法¶

上一節中,我們介紹了感知機模型損失函式$L(w,b)$的由來,接下來就要說說怎麼通過優化損失函式來獲得最終的超平面。在感知機模型中,有兩種優化方式:原始形式和對偶形式。

3.1 原始形式¶

原始形式採用的是梯度下降法進行求解,如果對梯度下降法不瞭解,可以參看前面寫過的一篇部落格。這裡需要注意的是,在上一小節中說過,感知機是基於誤分類驅動的一種模型,所以不能使用整個資料集進行梯度下降優化,只能對誤分類樣本集合$M$採用隨機梯度下降法或者小批量梯度下降法進行優化。 對損失函式$L(w,b)$求偏導: $$\frac{{\partial L(w,b)}}{{\partial w}} = - \sum\limits_{{x_i} \in M} {{y_i} \cdot {x_i}} $$ $$\frac{{\partial L(w,b)}}{{\partial b}} = - \sum\limits_{{x_i} \in M} {{y_i}} $$ 那麼,$w$的梯度下降迭代公式為: $$w = w + \alpha \cdot \sum\limits_{{x_i} \in M} {{y_i} \cdot {x_i}} $$ 偏置$b$的梯度下降迭代公式為: $$b = b + \alpha \cdot \sum\limits_{{x_i} \in M} {{y_i}} $$ 式中,$\alpha $是學習率。 感知機模型中,一般採用隨機梯度下降法進行優化,每次使用一個誤分類樣本點進行梯度更新。假設$(x_i,y_i)$是$M$中的一個誤分類點,進行梯度更新: $$w = w + \alpha \cdot {y_i}{x_i} \tag{3}$$ $$b = b + \alpha \cdot {y_i} \tag{4}$$ 總結一下原始形式優化步驟。 輸入:訓練樣本資料集$D = \{ ({x_i},{y_i})\} _{i = 1}^m$,${x_i} \in X \subseteq {R^n}$,${y_i} \in Y = \{ + 1, - 1\} $,學習率% $\alpha \in (0,1)$
輸出:$w$,$b$;感知機模型$f(x) = sign(w \cdot x + b) $
(1)初始化$w_0$,$b_0$;
(2)在$D$中選取任意點$(x_i,y_i)$;
(3)通過${y_i} \cdot (w \cdot {x_i} + b)$的值判斷是否是誤分類點,如果是,使用式(3)、(4)更新引數;
(4)回到步驟(2)直到準確率滿足條件。

3.2 對偶形式¶

對偶形式時原始形式在執行效率上的優化。通過3.1小節中,我們知道,每當一個樣本點$x_i$被錯誤分類一次時,都會使用式(3)(4)更新一次引數,那麼,如果樣本點$x_i$在迭代過程中被錯誤分類多次(假設$n_i$次),那麼就回有$n_i$次參與到引數更新中,我們假設引數$w$和$b$的初始值都為0向量,那麼,最終獲得的引數$w$和$b$為: $$w = \sum\limits_{i = 1}^N {{\beta _i} {y_i}{x_i}} \tag{5}$$ $$b = \sum\limits_{i = 1}^N {{\beta _i} {y_i}} \tag{6}$$ 這是在對偶形式中的引數更新方式,式中,${\beta _i} ={n_i}\alpha$。另外,在原始形式中,我們使用${y_i}(w \cdot {x_i} + b) \leqslant 0$來判斷樣本點$x_i$是否被錯誤分類,將式(5)(6)代入這一判別式中,得: $${y_i}(\sum\limits_{i = 1}^N {{\beta _i} {y_i}{x_i}} \cdot {x_j} + \sum\limits_{i = 1}^N {{\beta _i} {y_i}}) \leqslant 0 \tag{7}$$ 在對偶形式中,採用式(7)判斷樣本點是否正確分類,觀察後可以發現,式(7)中有兩個樣本點$x_i$和$x_j$內積計算,這個內積計算的結果在下面的迭代過程中需要多次被重複使用,如果我們事先用矩陣運算計算出所有的樣本之間的內積,那麼在演算法迭代過程中, 僅僅一次的矩陣內積運算比原始形式中每遍歷一個樣本點都要計算$w$與$x_i$的內積要省時得多,這也是對偶形式的感知機模型比原始形式優的原因。
在感知機模型中,樣本的內積矩陣稱為Gram矩陣,它是一個對稱矩陣,記為$G = {[{x_i},{x_j}]_{m \times m}}$。
總結一下對偶形式的步驟。
輸入:訓練樣本資料集$D = \{ ({x_i},{y_i})\} _{i = 1}^m$,${x_i} \in X \subseteq {R^n}$,${y_i} \in Y = \{ + 1, - 1\} $,學習率% $\alpha \in (0,1)$
輸出:$w$,$b$;感知機模型$f(x) = sign(w \cdot x + b) $
(1)初始化所有$n_i$值為0;
(2)計算Gram矩陣;
(3)在$D$中選取任意點$(x_i,y_i)$;
(4)如果${y_i}(\sum\limits_{i = 1}^N {{\beta _i} {y_i}{x_i}} \cdot {x_j} + \sum\limits_{i = 1}^N {{\beta _i} {y_i}}) \leqslant 0 $,令${\beta _i} = {\beta _i} + \alpha $;
(5)檢查是否還有誤分類樣本點,如果有,回到步驟(2);如果沒有,(5)(6)計算$w$、$b$最終值。

 

4 演算法實現¶

In [14]:
import numpy as np
import matplotlib.pyplot as plt 
import copy
In [15]:
# 先來製造一批資料
a = np.random.normal(20,5,300)
b = np.random.normal(15,5,300)
cluster1 = np.array([[x, y, -1] for x, y in zip(a,b)])
In [16]:
a = np.random.normal(45,5,300)
b = np.random.normal(40,5,300)
cluster2 = np.array([[x, y, 1] for x, y in zip(a,b)])
In [17]:
dataset = np.append(cluster1,cluster2, axis=0)
In [95]:
for i in dataset:
    plt.scatter(i[0], i[1],c='black',s=6)
plt.show()
  In [93]:
len(dataset)
Out[93]:
600
In [175]:
class Perception(object):

    def __init__(self):
        """
        感知機模型
        """
        self.w = 0
        self.b = 0
    
    def fit_raw_mod(self, train_data, lr=1, max_epoch=None, min_error_rate=0):
        """
        原始模式的感知機訓練方法,當達到最大迭代次數或錯誤率降到最小範圍退出
        train_data:訓練資料集
        lr:學習率
        max_epoch:最大迭代次數
        min_error_rate:最小錯誤率
        """
        self.w = np.zeros(train_data.shape[1]-1)  # 根據訓練集維度初始化權重係數
        epoch = 1  # 記錄迭代次數
        while True:
            error_count = 0  # 記錄錯誤分類樣本數
            for sample in train_data:
                xi = sample[0:-1]
                yi = sample[-1]
                distance = yi * (self.w @ xi + self.b)  # yi*(w⋅xi*+b)
                if distance <= 0: # 對於判斷錯誤的樣本點
                    self.w += lr * sample[-1] * sample[0:-1]
                    self.b += lr * sample[-1]
                    error_count += 1
            # 每完成一次迭代之後,驗證一次準確率,準確率達標則退出
            current_error_rate = float(error_count) / train_data.shape[0]
            # print('epoch {0},current_error_rate: {1}'.format(epoch+1, current_error_rate))
            # print('w:{0}, b:{1}'.format(self.w, self.b))
            # self.show_graph(train_data)  # 每一次迭代都展示一次影象
            if current_error_rate <= min_error_rate:
                break
            if isinstance(max_epoch, int) and epoch >= maxepoch:
                break
            epoch += 1
        print('w:{0}, b:{1}'.format(self.w, self.b))
        self.show_graph(train_data)
        
    def fit_dual_mod(self,train_data,lr=1):
        """
        對偶模式的感知機訓練方法
        train_data:訓練資料集
        lr:學習率
        """
        x_train = train_data[:,:-1]
        y_train = train_data[:,-1]
        num_samples, num_features = x_train.shape
        beta = np.zeros((num_samples,))
        self.b = 0

        # 計算 Gram 矩陣
        gram = np.dot(x_train, x_train.T)

        while True:
            error_count = 0
            for i in range(num_samples):
                inner_product = gram[i]
                y_i = y_train[i]
                
                distance = y_i * (np.sum(beta * y_train * inner_product) + self.b)
                # 對於誤分類點,修正 beta 和 偏置b,跳出本層迴圈,重新遍歷資料計算,開始新的迴圈
                if distance <= 0:
                    error_count += 1
                    beta[i] = beta[i] + lr
                    self.b = self.b + lr * y_i
                    break  
            # 資料沒有誤分類點,跳出 while 迴圈
            if error_count == 0:
                break
        self.w = np.sum(beta * y_train * x_train.T, axis=1)  # 計算w引數最終值
        print('w:{0}, b:{1}'.format(self.w, self.b))
        self.show_graph(train_data)  # 展示影象

        
    def predict(self, sample):
        """
        輸入一個樣本點,判斷是-1類還是+1類
        sample:樣本點
        """
        output = self.w @ sample + self.b
        return 1 if output >= 0 else -1
    
    def show_graph(self, train_data):
        """
        把訓練出來的超平面影象展示出來

        """
        for sample in train_data:
            if sample[-1] == 1:
                plt.scatter(sample[0], sample[1],c='black',s=6)
            else:
                plt.scatter(sample[0], sample[1],c='red',s=6)
        x = np.linspace(0.,60.,200)
        y = -(self.w[0]*x + self.b) / self.w[1]
        plt.plot(x,y)
        plt.show()
In [176]:
model = Perception()
model.fit_raw_mod(dataset, lr=1)
 
w:[8.54367705 9.34962314], b:-542.0
 

相關推薦

機器學習回顧10感知模型

  注:本系列所有部落格將持續更新併發布在github和gitee上,您可以通過github、gitee下載本系列所有文章筆記檔案。   1 引言¶ 感知機是一種簡單且易於實現的二分類判別模型,主要思想是通過誤分類

機器學習回顧2最小二乘法

1 引言 在機器學習常用的優化演算法中,梯度下降法和最小二乘法佔盡了風騷。梯度下降法上一篇中已經詳細介紹過了,那麼這一篇,我們繼續說一說最小二乘法。 2 什麼是最小二乘法 描述預測模型準確程度有多重不同的方法: (1)誤差和最小化。這種方法存在的問題是正負誤差會相互抵消,導致描述不準確。 (2)誤差

機器學習回顧4邏輯迴歸

1 引言 邏輯不邏輯,迴歸非迴歸。 回想當年初次學習邏輯迴歸演算法時,看到”邏輯迴歸“這個名字,第一感覺是這是一個與線性迴歸類似的迴歸類別的演算法,只不過這個演算法突出”邏輯“,或者與某個以”邏輯“命名的知識點有關。可後來卻發現,這是

機器學習回顧5樸素貝葉斯演算法

1 引言 說到樸素貝葉斯演算法,很自然地就會想到貝葉斯概率公式,這是我們在高中的時候就學過的只是,沒錯,這也真是樸素貝葉斯演算法的核心,今天我們也從貝葉斯概率公式開始,全面擼一擼樸素貝葉斯演算法。 2 貝葉斯概率公式 2.1 聯合概率與全概率公式 定義1:完備事件組 ${A_1} \cup {A_2

機器學習回顧6KNN演算法

  1 引言¶   本文將從演算法原理出發,展開介紹KNN演算法,並結合機器學習中常用的Iris資料集通過程式碼例項演示KNN演算法用法和實現。

機器學習回顧7決策樹演算法ID3、C4.5

  注:本系列所有部落格將持續更新併發布在github上,您可以通過github下載本系列所有文章筆記檔案。   1 演算法概述¶

機器學習回顧8CART決策樹演算法

注:本系列所有部落格將持續更新併發布在github和gitee上,您可以通過github、gitee下載本系列所有文章筆記檔案。 1 引言 上一篇部落格中介紹了ID3和C4.5兩種決策樹演算法,這兩種決策樹都只能用於分類問題,而本文要說的CART(classification and regression

機器學習回顧11支援向量SVM

  1. 引言¶ SVM,Support Vector Machine,也就是我們中文名的支援向量機,我相信,只要是與機器學習有過照面的童鞋或多或少都聽說過這個名字。作為機器學習家族中的老牌成員,其經典自不必說。從原理和特性上講,SVM

機器學習回顧12整合學習之Bagging與隨機森林

  1 引言¶ 整合學習演算法是當下炙手可熱的一類演算法,在諸多機器學習大賽中都頻繁出現它的身影。準確來說,整合學習演算法並不是一個單獨的機器學習演算法,而是通過構建多個學習器,博採眾家之長,共同求解問題的一種思想。古語有云:&ldquo

機器學習回顧13整合學習之AdaBoost

  在上一篇部落格中,我們總結了整合學習的原理,並展開介紹了整合學習中Bagging和隨機森林這一分枝演算法,在本篇部落格中,我們繼續介紹另一個分枝——Boosting,並對Boosting系列中的經典演算法Adaboost

機器學習回顧14主成分分析法PCA

  1 引言¶ 在展開資料分析工作時,我們經常會面臨兩種困境,一種是原始資料中特徵屬性太少,“巧婦難為無米之炊”,很難挖掘出潛在的規律,對於這種情況,我們只能在收集這一環節上多下功夫;另一種困境剛好相反,那就是特徵

機器學習回顧15整合學習之GDBT

          1 引言¶ 梯度提升樹演算法(Gradient Boosting Decision Tree,GBDT)是一個非常經典的機器學習演算法,和我們前面介紹過的Adaboost演算法一樣,都是提

機器學習回顧16蒙特卡洛演算法

          蒙特卡羅(MC,Monte Carlo)方法是一種隨機取樣模擬求解的方法,又被稱統計試驗方法或者統計模擬方法。起初,蒙特卡羅方法的提出是20世紀40年代馮·諾伊曼,

機器學習實戰教程線性回歸基礎

學習 reg style spa 目標 pub auto 機器 輸入 一 什麽是回歸?   回歸的目的是預測數值型的目標值,最直接的辦法是依據輸入,寫入一個目標值的計算公式。   假如你想預測小姐姐男友汽車的功率,可能會這麽計算:               Ho

機器學習實戰教程決策樹實戰之為自己配個隱形眼鏡

原文連結:cuijiahua.com/blog/2017/1… 一、前言 上篇文章機器學習實戰教程(二):決策樹基礎篇之讓我們從相親說起講述了機器學習決策樹的原理,以及如何選擇最優特徵作為分類特徵。本篇文章將在此基礎上進行介紹。主要包括: 決策樹構建 決策樹視覺化 使用決

機器學習實戰教程樸素貝葉斯實戰之新浪新聞分類

原文連結: Jack-Cui,https://cuijiahua.com/blog/2017/11/ml_5_bayes_2.html 一、前言 上篇文章機器學習實戰教程(四):樸素貝葉斯基礎篇之言論過濾器講解了樸素貝葉斯的基礎知識。本篇文章將在此基礎上進行擴充套件,你將看到以下內容: 拉普拉

機器學習實戰教程樸素貝葉斯基礎之言論過濾器

word 最可 dog 一個 mac github上 開課 和數 基礎上 原文鏈接: Jack-Cui,https://cuijiahua.com/blog/2017/11/ml_4_bayes_1.html 一、前言 樸素貝葉斯算法是有監督的學習算法,解決的是分類問題,

深入理解java虛擬機器系列初為什麼要學習JVM?

前言 本來想著關於寫JVM這個專欄,直接寫知識點乾貨的,但是想著還是有必要開篇講一下為什麼要學習JVM,這樣的話讓一些學習者心裡有點底的感覺比較好... 原因一:面試 不得不說,隨著網際網路門檻越來越高,JVM知識也是中高階程式設計師階段必問的一個話題!現在不像以前了,以前會點html都好找工作,現在由於學習

中國mooc北京理工大學機器學習第二周分類

kmeans 方法 輸入 nump arr mod 理工大學 each orm 一、K近鄰方法(KNeighborsClassifier) 使用方法同kmeans方法,先構造分類器,再進行擬合。區別是Kmeans聚類是無監督學習,KNN是監督學習,因此需要劃分出訓練集和測試

我的機器學習之旅回歸與工程應用

多個 算法 ati function RR numpy pen 圖片 bsp 內容:線性回歸;邏輯回歸,應用場景。 一、線性回歸 有監督學習,根據學習樣本{x->y},學習一個映射f:X->Y(線性相關),輸出預測結果y_i。最簡單的例子:y=ax+b 重要組成