感覺機學習筆記
作者:一個興趣使然的程式員lvh
郵箱:[email protected]
最新更改時間:2019-10-19
原創文章,轉載請注明出處https://blog.csdn.net/qq_44899812/article/details/102635736
關于分類問題,最古老也是最簡單的算法就是1956年提出的感覺機了。是以感覺機也是學習分類問題的入門問題。
目錄
文章目錄
- 感覺機學習筆記
-
- 導引
-
- 二維平面上的線性二分類
- 二維以上空間的二分類
- 單個神經元
-
- 單個神經元的結構模型
- 符号說明
- 具體操作
-
- 如何判斷誤分類點
- 損失函數探索
-
- 以誤分類點個數為損失函數(了解就行)
- 以所有誤分類點到超平面的距離的和為損失函數
- 梯度下降法
-
- 步長η(學習率)
- 批量梯度下降法 BGD(Batch Gradient Descent)
- 随機梯度下降法 SGD(Stochastic Gradient Descent)
- 小批量梯度下降法MBGD(Mini-Batch Gradient Descent)
- 三種梯度下降法小結
- 利用梯度下降法使損失函數最小
- 學習性能,泛化性能,學習次數
- 算法設計
- 代碼實作
- 實驗樣例
-
- iris資料集
-
- 實驗1
- 實驗2
- 實驗3
- wine資料集
-
- 實驗4
- 實驗5
- 實驗6
- 實驗7
- 實驗8
- 異或實驗
導引
看完這個導引你大概就能知道感覺機是什麼,他是如何運作的了。
二維平面上的線性二分類
感覺機隻能解決線性可分問題,至于為什麼,後面會講到。
注解:線性可分:對于二維空間來說,線性可分是指用一條直線可以把兩種資料完全分類開來,在三維空間中就是指可以用一個平面把兩種資料完全分類開來,以此類推,在高維空間就是指用一個超平面把兩種資料完全分類開來。 假如有三類資料,在二維空間裡面如果可以用一條直線可以把某一類資料和其他兩類劃分開來,就稱這類資料是線性可分的
如下圖。如何把黑點和紅點區分開來?就是一個線性可分的二分類問題.
很簡單,一條直線不就可以把它們分開來嗎。(如下圖)
直線上方一類,下方一類。隻要判别這個點在上方還是下方就好了。
設這條直線方程是
w0+w1*x1+W2*x2=0
,假如
w0+w1*x1+W2*x2>0
所指區域是直線上方,
w0+w1*x1+W2*x2<0
就表示直線下方的區域。
我們就可以用
w0+w1*x1+W2*x2
的正負來判斷一個點是黑點還是紅點了。
注解:有的人可能有點不适應這種寫法,回想高中的y=kx+b,y>kx+b就是直線上方,y<kx+b就是直線下方,不是一樣的的嗎,隻是換了種寫法
那麼,
隻要能找到上圖這條直線,這個分類不就解決了嗎!
那怎麼找到這條直線呢?
對于人來說很簡單,因為我們有着複雜的大腦結構,但是如何教會機器去找這條直線呢?
機器的好處在于不厭其煩,我們可以讓他随便找一條直線,然後讓他朝着損失最小的方向不斷摸索。
首先讓機器随便做一個直線。如下圖,可以看出來錯誤百出,紅點分到黑的裡面,黑點分到紅的裡面。
接下來我們就要減小損失。
如果我們以誤分類點個數為損失函數,就會不知道朝哪個方向去減小損失。
是以我們換一種損失函數,以**
所有誤分類點到直線的總距離
**為損失函數。因為距離是非負的,是以損失函數最小值為0,取最小值時每個誤差點的誤差也必為0,即全部正确。
以所有誤分類點到直線的總距離為損失函數
有了這個損失函數之後,就開始一個點一個點的去減小損失。遇到錯誤的點就把直線往錯誤點那邊靠,來減小損失。遇到正确的就不動。
比如遇到了下圖淡紫色光暈的黑點,這個點帶入到直線方程
w0+w1*x1+W2*x2<0
,在直線下方的,但他的實際應該在直線上方 ,
w0+w1*x1+W2*x2應該大于0
。這就算分錯了。
發現這個點分錯了,就要朝損失函數最小的方向去調整。
我們想讓這個誤分類點到直線的距離減小,是以調整直線,讓直線往這個誤分點移動一些,如下圖。(這個樣子叫随機梯度下降法,一個點一個點的調,後面會具體講)
或者移動多了,發現這個點已經不是誤分類點了,這樣更好。
像這樣,遇到誤分類點就調整,遇到正确的點就不動。
慢慢的,直線就會移動到我們想要的樣子。
當沒有了誤分類點了,他也就不動了。(是以說感覺機是誤分類驅動的)
這,就是一個最簡單的感覺機。
當然,對平面上的點進行分類隻是具體問題的抽象罷了。
如果把橫坐标看成是一朵花的葉子長度,縱坐标看成是這朵花的花萼寬度,那麼我們是不是隻要知道了某朵花的這兩個特征,就可以用一條直線,對這朵花的種類進行分類了呢?
二維以上空間的二分類
實際中隻要兩個特征就能分類的東西很少,是以不能隻考慮二維分類。
二維空間裡面的二分類我們用的是直線,
w0+w1*x1+w2*x2=0
那三維空間的分類用平面不就好了嗎,
w0+w1*x1+w2*x2+w3*x3=0
那四維空間裡面,就用一個四維的超平面,
w0+w1*x1+w2*x2+w3*x3+w4*x4=0
(雖然人類很難想象高維空間,但是計算方法是一樣的啊,我們照樣計算)。
有了上面的鋪墊我們大概知道了,感覺機其實就是用超平面(偶爾退化成平面,直線),來進行線性分類。
n維的空間上,分類超平面就是
w 0 ∗ x 0 + w 1 ∗ x 1 + w 2 ∗ x 2 + . . . + w n ∗ x n = 0 w0*x0+w1*x1+w2*x2+...+wn*xn=0 w0∗x0+w1∗x1+w2∗x2+...+wn∗xn=0
超平面分出來的結果無非就是兩個:
點帶進去,
w0+w1*x1+w2*x2+w3*x3+...+wn*xn>0
,在超平面平面的一側
w0+w1*x1+w2*x2+w3*x3+...+wn*xn<0
,在超平面的另一側
(=0的情況比較少,不考慮)
我們把>0的一側的點叫做1類,<0的一側的點叫做-1類,
這樣從二維到n維的線性分類思路不就清晰了嗎?
單個神經元
上面講的超平面其實就是一個單個的神經元,多個神經元就是多個超平面,
我們這裡講的單層感覺機隻用了一個神經元。
單個神經元的結構模型
單個神經元就是一個超平面。
一個超平面的包含的元素不就是下圖這些嗎,
x1,x2,x3,…,xn ,n個自變量。
w1,w2,w3,…,wn是自變量前面的系數。
w1*x1+w2*x2+w3*x3+...+wn*xn
再加上一個
偏置
wo*x0
就是超平面的方程了。
w 0 + w 1 ∗ x 1 + w 2 ∗ x 2 + w 3 ∗ x 3 + . . . + w n ∗ x n = 0 w0+w1*x1+w2*x2+w3*x3+...+wn*xn=0 w0+w1∗x1+w2∗x2+w3∗x3+...+wn∗xn=0
(偏置相當于y=kx+b裡面的b,這裡x0是1,寫成x0是為了形式上統一)
再把具體的點帶進去,就有了>0和<0兩種情況,這兩種情況分别對應着1類和-1類。
單個神經元模型
整個過程可以簡寫成下面這種公式。(sign()代表到-1和1的映射)
f ( x ) = s i g n ( w i ⃗ ∗ x i ⃗ ) f(x)=sign(\vec {wi}*\vec {xi}) f(x)=sign(wi
∗xi
)
感覺機符号化
sign()函數圖像
(上面的式子化為友善起見,權重和用向量内積表示了)
w i ⃗ = ( w 0 , w 1 , w 2 , . . . , w n ) \vec {wi}=(w0,w1,w2,...,wn) wi
=(w0,w1,w2,...,wn)
x i ⃗ = ( x 0 , x 1 , x 2 , . . . , x n ) \vec {xi}=(x0,x1,x2,...,xn) xi
=(x0,x1,x2,...,xn)
( w 0 , w 1 , . . . w n ) ∗ ( x 0 , x 1 , . . . x n ) = w 0 ∗ x 0 + w 1 ∗ x 1 + . . . + w n ∗ x n (w0,w1,...wn)*(x0,x1,...xn)=w0*x0+w1*x1+...+wn*xn (w0,w1,...wn)∗(x0,x1,...xn)=w0∗x0+w1∗x1+...+wn∗xn
向量内積公式
符号說明
下面具體講解一下這些符号在實際問題中的含義。(符号說明可以先跳過,看不懂再回頭看)
- x1,x2,x3,x4…xn : 一個xi對應着樣本的一個特征。(例如iris資料集裡面的x1對應花萼長度,x2對應花萼寬度。。。)
- y: 樣本的實際類别,或者說标簽。這裡是二分類,是以y取-1,1(比如A花用1來表示,B花用-1來表示)。
- w1,w2,w3,w4…wn: 一個wi對應着一個特征的權值。
- x0,w0:
是偏置,w0*x0
。注意 x0并不是一個特征,x0取1
也可以寫成b,這樣設隻是為了形式上統一。w0*x0
- f(): 激活函數,這裡用的是
(符号函數),如下圖,sign隻是用來把權重和映射到-1和1上面而以。sign()
sign()
- -1,1: 類别,或者說标簽(計算出來的),這裡有兩類,用-1,1表示,當然也可以用别的方法表示,但是這麼表示比較友善。
具體操作
看過了導引,我們對感覺機的操作有了一個大概的了解,但具體怎麼操做,如何判斷一個點是不是誤分類點?如何計算距離?怎麼去調整參數?
下面來一個個的講解。
如何判斷誤分類點
w 0 + w 1 ∗ x 1 + w 2 ∗ x 2 + w 3 ∗ x 3 + . . . + w n ∗ x n = 0 w0+w1*x1+w2*x2+w3*x3+...+wn*xn=0 w0+w1∗x1+w2∗x2+w3∗x3+...+wn∗xn=0
超平面方程
我們令
w0+w1*x1+w2*x2+...+wn*xn>0
即
∑>0
的一側被分類為1,
w0+w1*x1+w2*x2+...+wn*xn<0
即
∑<0
的一側被分類為-1
如果說樣本實際标簽為1,代入點(x1,x2,x3,…,xn)到
超平面方程
,求出來,
w0+w1*x1+w2*x2+...+wn*xn>0
,那他就在标簽為1的一側,這就算分對了。
如果計算出來的權重和與實際标簽異号,比如實際标簽-1,但代入點(x1,x2,x3,…,xn)到
超平面方程
求出來∑>0,兩者異号,那肯定是分錯了。
注解:有的人可能會困惑,為什麼∑>0就是标簽為1,∑<0就是标簽為-1,為什麼不是反過來,其實這個反過來也是一樣的結果,可以假設一下,如果∑>0就是标簽-1,∑<0就是标簽1,那他求出來的分界線,不還是我們要的那個分界線嗎
那我們就可以把誤分類判斷總結為隻要滿足,
代入超平面方程和實際标簽異号的點
,就是誤分類點 。簡寫為下面的方程。
y ∗ ( w i ⃗ ∗ x i ⃗ ) < 0 y*(\vec {wi}*\vec {xi})<0 y∗(wi
∗xi
)<0
方程2 誤分類點判斷
損失函數探索
以誤分類點個數為損失函數(了解就行)
(這裡以誤分類點個數為損失函數是感覺機算法的思考曆程,如果隻是想應用現成算法可以跳過)
我們最開始的樸素的想法是,以誤分類點個數為損失函數,隻要損失函數為0,就代表全部分對了。
Q()是我們自己定義的一個用來計算誤分類點個數的函數,出現一個誤分類點(y*∑<0),就加1,如果不是,就加0。
∑ [ Q ( y ∗ w i ⃗ ∗ x i ⃗ ) ] \sum[Q(y*\vec {wi}*\vec {xi})] ∑[Q(y∗wi
∗xi
)]
損失函數1
Q ( x ) = { 1 , x < 0 0 , x > = 0 Q(x)= \begin{cases} 1,x<0\\ 0,x>=0 \end{cases} Q(x)={1,x<00,x>=0
Q()圖像
雖然這個想法看起來可以,可是這個損失函數是不可導的,難以對他求最小值點,是以我們隻能換一種思路。
以所有誤分類點到超平面的距離的和為損失函數
如果所有誤分類點到超平面的距離之和為0的話,不就等價于沒有誤分類點了嗎?那我們隻要朝着所有誤分類點的總誤差距離最小的方向調整參數,就能做到沒有誤分類點了。
點(x1,x2,x3,…,xn)到平面
w0+w1*X1+w2*X2+w3*X3+...+wn*Xn=0
的距離公式可以回憶高中知識
d = ∣ w 0 + w 1 ∗ x 1 + w 2 ∗ x 2 + . . . + w n ∗ x n ∣ w 1 2 + w 2 2 + . . . + w n 2 d=\frac{|w0+w1*x1+w2*x2+...+wn*xn|}{\sqrt{w1^2+w2^2+...+wn^2}} d=w12+w22+...+wn2
∣w0+w1∗x1+w2∗x2+...+wn∗xn∣
距離公式
因為誤分類點的y和∑異号,是以我們可以用y來去絕對值!
d = − y ∗ ( w 0 + w 1 ∗ x 1 + w 2 ∗ x 2 + . . . + w n ∗ x n ) w 1 2 + w 2 2 + . . . + w n 2 = − y ∗ ( x ⃗ ∗ w ⃗ ) ∣ ∣ w ⃗ ∣ ∣ d=\frac{-y*(w0+w1*x1+w2*x2+...+wn*xn)}{\sqrt{w1^2+w2^2+...+wn^2}}=\frac{-y*(\vec x*\vec w)}{||\vec w||} d=w12+w22+...+wn2
−y∗(w0+w1∗x1+w2∗x2+...+wn∗xn)=∣∣w
∣∣−y∗(x
∗w
)
距離公式改進版
(||w||是向量w的範數,也就是模)
M是誤分類點的集合,把誤分類的所有點到超平面的距離加起來就是我們的目标函數了。
∑ x ∈ M ( − y i ∗ ( w ⃗ i ∗ x ⃗ i ) ∣ ∣ w ⃗ i ∣ ∣ ) \sum_{x\in M}(\frac{-yi*(\vec wi*\vec xi)}{||\vec wi||}) x∈M∑(∣∣w
i∣∣−yi∗(w
i∗x
i))
損失函數2
現在我們的任務就是使損失函數2最小,自變量是參數**(w0,w1,w2,w3,…,wn)**。
(因為距離是非負數,是以最小值是0)
對于求最小值點,我們高中的常用方法是求導,找到導數為0的點就是最小值點。
但是那是對于初等函數而言,對于很多複雜的函數我們根本沒辦法求導。那就要用一些其他方法了。
方法又很多,這裡隻挑選了三種梯度下降法講解(感覺機用的是随即梯度下降法),有興趣的同學可以了解一下其他的優化方法。https://www.cnblogs.com/huangyc/p/9801261.html
梯度下降法
可以想象一個場景,一個盲人站在山上某一處,想盡快到達山的最低點,但他隻能感覺到自己腳下的路哪個方向是最陡峭的,是以他每次就沿着最陡峭的方向往下邁一步,如果他某一次往前邁出一步發現自己下降的非常小,小于一個門檻值,他就認為自己已經到了最低的地方了。
我們的損失函數求最小值過程不就可以類比盲人下山嗎,我們無法求出整個函數的導數(盲人),但我們總是有辦法對一個點求梯度[^注解1](找到最陡峭的方向),我們就沿着這個梯度方向的反方向(因為梯度方向是上升最快的方向)去改變參數(邁出一步),每次改變之後再繼續求梯度,再沿着梯度方向反方向改變參數,最終當有一次我們改變參數後發現改變的非常小,小于一個門檻值,我們就認為已經到低谷了(到達最低點)。
注解1:梯度,對于單變量函數來說就是斜率。對于多變量函數來說,就是各個自變量的偏導數組成的向量,是函數增加最快的方向,例如f(x,y)=x^2+y,在(x0,y0)點的梯度是(對x的偏導數,對y的偏導數),應該是(2x0,1)
圖檔來源于網絡
步長η(學習率)
下山的時候,要是步長太大可能會正好錯過最低點(如下圖,從左往右,快到最低點的時候因為步子太大了,就錯過了最低點),如果步長太小又走的太慢。
是以對于步長我們要綜合考慮速度和準确度。
批量梯度下降法 BGD(Batch Gradient Descent)
如果上面盲人下山的比喻你懂了,那你基本上懂了批量梯度下降法。
批量梯度下降法中,我們的算法就是這個盲人,損失函數就是大山,我們的目的就是找到損失函數的最小值。
這裡的損失函數是所有誤分類點的總誤差距離,是以說利用BGD求出來的下降方向,肯定總誤差下降最快的方向,所需要的步數肯定是最少的,從圖像上上看一般是比較合理的(如圖1,為一個等高線圖上面的下降路徑)。
圖1(BGD)
如果損失函數不是凸函數,有可能就會掉到一個局部最小值裡面,是以我們要多做幾次,比較最小值。(如下圖)
如果損失函數是凸函數的話那麼BGD的結果肯定是全局最小值(如下圖的凸函數)
雖然我們用所有誤差點的總誤差作為損失函數會讓計算出來的方向是對于全局最優的,但是這也面臨了一個問題:
每一次計算梯度都要考慮到所有的誤差點,從實際操作來看,每一次計算梯度都要把整個樣本集都過一遍才能得出一個梯度
如果樣本集特别大,那麼每過一遍都會花費大量的時間,我們肯定希望能夠快點到山下,不然天都黑了。是以對于量比較大的樣本集我們就必須找到其他方法。
随機梯度下降法 SGD(Stochastic Gradient Descent)
随機梯度下降法和批量梯度下降法的差別在于:
批量梯度下降法的損失函數是所有誤分類點的總誤差,而随機梯度下降法的損失函數是某一個誤差點的誤差
,也就是說我們每次隻考慮一個點誤差要最小,不考慮全局。
這樣的話,每遇到一個誤分類點都更新一下參數,更新的速度就很快,批量梯度下降法還在慢慢求梯度,随機梯度下降法已經走了好幾步了。
随機梯度下降法,實際是就是想用某個誤分類的誤差梯度來近似所有誤分類點的誤差梯度。
我們每次朝着一個點誤差下降最快的方向去變化,這樣有比較大機率總誤差減小了。
但這樣做自然是有缺陷的,某個點誤差減小最快方向,不一定是總誤差減小最快方向,極端情況有可能增加誤差(如下圖,原來是藍色線,變成了綠色線,為了讓黃色光暈的紅點誤差減小,讓黑色光暈的紅點誤分了,這就是随機梯度下降法的短視性)
如下圖,從圖像上看路線非常盲目,走了很多彎路,從實際操作來看,更新次數非常多(不是最短路徑,走的步數當然多)。
但是這樣速度非常快,雖然每一步走的不一定是對于全局最快的下降方向,但是他的步頻非常高,總的來看要比批量梯度下降法快的多。
SGD
但因為他的方向并不是全局最優,是以他可能到不了全局最優點,而是在最優點附件徘徊。準确度降低了。
小批量梯度下降法MBGD(Mini-Batch Gradient Descent)
小批量梯度下降法其實是批量梯度下降法和随機梯度下降法的折中。
我們把樣本均勻分成好多小組,每次考慮誤差的時候考慮一個小組的總誤差,這樣就緩解了隻考慮一個或者考慮所有的弊端。
三種梯度下降法小結
批量梯度下降法(BGD):
優點:準确度高(如果是凸函數則一定能到最優解),更新次數少。
缺點:疊代太慢(每走一步要找方向找半天),容易陷入局部最優。
随機梯度下降法(SGD):
優點:快。有可能碰巧跳出局部最小值。
缺點:準确度低(最後可能在最優解旁邊徘徊),疊代次數太多。
小批量梯度下降法(MBGD):
優缺點中和了BGD和SGD。
下面放一張圖,來大概對比一下這三種下降法的疊代過程。
利用梯度下降法使損失函數最小
回到主題,現在既然有了優化方法(随機梯度下降法),那我們就用随機梯度下降法的方式來下降**
損失函數2
**。
∑ x ∈ M ( − y i ∗ ( w ⃗ i ∗ x ⃗ i ) ∣ ∣ w ⃗ i ∣ ∣ ) \sum_{x\in M}(\frac{-yi*(\vec wi*\vec xi)}{||\vec wi||}) x∈M∑(∣∣w
i∣∣−yi∗(w
i∗x
i))
損失函數2
随機梯度下降法的思路是,每遇到一個誤分類點就更新一次參數,最終近似達到最優解。
現在開始訓練樣本集,假設這會碰上了一個被判斷為誤分類的點
y ∗ ∑ 0 n ( w i ∗ x i ) < 0 y*\sum_{0}^{n}(wi*xi)<0 y∗0∑n(wi∗xi)<0
方程2 誤分類點判斷
我們就對這個點的誤差點離超平面的距離求梯度
d = − y ∗ ( x ⃗ ∗ w ⃗ ) ∣ ∣ w ⃗ ∣ ∣ d=\frac{-y*(\vec x*\vec w)}{||\vec w||} d=∣∣w
∣∣−y∗(x
∗w
)
距離公式改進版
我們發現分母上的||w||運算起來很麻煩,其實他不是必要的,可以省略他。
注解:因為我們隻需要距離為0就可以了,d為0的時候分子為0,分母其實是無所謂的,換句話說,分母在整個距離公式裡面隻是起一個縮放效果,對梯度的方向沒有影響的(一個向量乘以或者除以一個不為0的數,方向不變)
那我們就忽略分母來表達距離,如下(這種距離表達又被稱作函數間隔)
d = − y ∗ ( x ⃗ ∗ w ⃗ ) d=-y*(\vec x*\vec w) d=−y∗(x
∗w
)
距離公式再改版 函數間隔
對各個wi求導
d = − y ∗ ( w 0 ∗ 1 + w 1 ∗ x 1 + w 2 ∗ x 2 + w 3 ∗ x 3 + . . . . + w n ∗ x n ) d=-y*(w0*1+w1*x1+w2*x2+w3*x3+....+wn*xn) d=−y∗(w0∗1+w1∗x1+w2∗x2+w3∗x3+....+wn∗xn)
展開來比較容易了解
Δ w i = − y ∗ x i \Delta wi=-y*xi Δwi=−y∗xi
這樣就求出了梯度
(-y*x1,-y*x2,-y*x3,...,-y*xn)
我們就把原來的參數減去步長η乘以梯度(因為梯度是上升最快方向,我們要的是下降最快方向,是以加上負的步長η乘以梯度),誤差距離就朝着減小的方向邁出了一步。
w i ⃗ − η ∗ Δ w i ⃗ \vec {wi}-\eta *\Delta \vec {wi} wi
−η∗Δwi
具體到每個wi
w i = w i − η Δ w i = w i + η ∗ y ∗ x i wi=wi-\eta\Delta wi=wi+η*y*xi wi=wi−ηΔwi=wi+η∗y∗xi
之是以乘以一個步長η前面說過,是為了控制步子不要太大或者太小。
我們就這麼一遍一遍的對着樣本集進行訓練,每遇到一個誤分類點就更新一次,所有樣本點都過了一遍了之後,就從頭開始再訓練一遍,直到某一遍,訓練下來一個誤分類點都沒有找到,訓練就可以結束了。
最後求出來的參數(w0,w1,w2,w3,…,wn)所組成的這個超平面,
w 0 + w 1 ∗ x 1 + w 2 ∗ x 2 + w 3 ∗ x 3 + . . . + w n ∗ x n = 0 w0+w1*x1+w2*x2+w3*x3+...+wn*xn=0 w0+w1∗x1+w2∗x2+w3∗x3+...+wn∗xn=0
就是我們要找的,能把所有資料點正确的一分為二的超平面。
我們訓練的目的是為了以後的分類,就像高中的時候我們做練習是為了聯考,練習做的正确率高并不能代表聯考能考得好,那我們怎麼評判我們做練習的效果呢?
模拟考試。一般我們會在訓練完訓練集之後再找一個測試集,這個測試集和模拟考一樣是有答案的,讓訓練好的超平面去分這個測試集,最後分完的結果和答案一比對,就知道學的怎麼樣了。
學習性能,泛化性能,學習次數
平時練習的正确率就是
學習性能
,考試的時候能表現出來的正确率就是
泛化性能
。我們希望的是平時正确率高,泛化的也好,最不希望的是平時練習好,泛化性能很低。
有的人一道題做一遍相當于别人一道題做十遍,不一樣的
學習次數
一樣的結果,這就是學習效率的問題。
評價一個學習還有很多方面要考慮,這裡感覺機我們先考慮這三個方面。
算法設計
我們來梳理一下整個的流程
簡單來說就是
- 輸入
- 訓練
- 測試
因為要看學習性能,泛化性能,學習次數,是以我們會另外加一些東西
再具體一些流程如下
- 初始化一個超平面。(随機設定參數)
- 輸入一個訓練集資料,訓練總數++。
- 用超平面對這個資料進行分類。
-
分類錯誤,按照随機梯度下降法更新參數,訓練樣本個數++。
分類正确,訓練正确次數++,訓練樣本個數++。
- 訓練集全輸入完。學習次數++。
- 判斷:如果這一遍什麼都沒有錯,或者大于最大學習次數(自己設定的),就結束學習。否則,從第2步到第6步再來一遍。
- 輸入測試集資料。
- 判斷正确,正确個數++。判斷錯誤,不做操作。
- 測試集全分類完。
- 輸出結果:學習性能(訓練正确數/訓練樣本個數),泛化性能(測試正确數/測試樣本個數),疊代次數(更新了幾次),學習次數(整個樣本集刷了幾遍)
下面是流程圖
代碼實作
#include<iostream>
#include<stdlib.h>
#include<cmath>
#include<time.h>
#include<conio.h>
using namespace std;
#define maxtime 100//最大學習次數
#define N 4//樣本特征數
int type;
double x[N];
double s;//激活前的值
int y;//激活後的值
double w[N],b;
long k;//疊代次數
long c;//學習次數
double rate=0.1;//學習率
//sign函數
int sign(double s)
{
if(s>0)
return 1;
else
return -1;
}
//輸入
void input(FILE *fp)
{
for(int i=0;i<N;i++)
fscanf(fp,"%lf",&x[i]);
}
//随機設定權值
void setw()
{
srand((unsigned int)time(NULL));//随機數
for(int i=0;i<N;i++)
w[i]=(double)(rand()%10)/10;//我把他設定在0.0到1.0之間,沒有特别要求
b=(double)(rand()%10)/10;
}
int main()
{
FILE *fp1,*fp2,*fp3;
fp1=fopen("iris_in.txt","r");//訓練集
fp2=fopen("theout.txt","w");//列印結果
fp3=fopen("iris_test.txt","r");//測試集
int i,j,m,p,q;
int flag;//用于判斷訓練要不要結束
int num;//訓練集樣本數
int tnum;//測試集樣本數
int right;//訓練正确數
int right2;//測試正确數
k=0;
c=0;
num=0;
tnum=0;
right=0;
right2=0;
setw();//初始化超平面
while(c<maxtime)//隻要小于最大訓練次數就一直訓練
{
flag=0;
c++;//訓練次數++
while(fscanf(fp1,"%d",&type)!=EOF)//隻要還有資料
{
input(fp1);//就輸入一組資料
num++;//訓練樣本數++
//求權重和
s=0;
for(i=0;i<N;i++)
s+=w[i]*x[i];
s+=b;
//判斷有沒有誤分類
if(type*s<0)//錯誤了,更新參數
{
flag=1;
for(i=0;i<N;i++)
w[i]+=rate*type*x[i];
b+=rate*type;
k++;//疊代次數++
}
else//正确了,正确數++
{
right++;
}
}
//如果一遍學習下來沒有錯誤,flag還是0,學習就結束了
if(flag==0)
{
break;
}
rewind(fp1);
}
right2=0;
//測試
while(fscanf(fp3,"%d",&type)!=EOF)
{
input(fp3);
tnum++;
s=0;
for(i=0;i<N;i++)
s+=w[i]*x[i];
s+=b;
if(type*s>0)
{
right2++;
}
}
fprintf(fp2,"學習率%lf 學習次數%ld 疊代次數%ld 學習性能%lf 泛化性能%lf \n",rate,c,k,(double)right/(double)num,(double)right2/(double)tnum);
return 0;
}
實驗樣例
實際應用才是我們研究算法的最終目的,我選取了UCI資料庫上面的一些資料來分類。
iris資料集
資料來源 https://archive.ics.uci.edu/ml/datasets/Iris
iris(鸢尾花)資料集是分類問題中非常經典的一個資料集。
我們利用某朵鸢尾花的幾個特征對這朵鸢尾花的品種進行細分。
uci上資料庫上的鸢尾花有三種 1.Setosa 2. Versicolour 3. Virginica 。
他的四個特征是:
sepal length in cm(花萼長度)
sepal width in cm(花萼寬度)
petal length in cm(花瓣長度)
petal width in cm(花瓣寬度)
我們從中選取了Setosa 的資料和 Versicolour 的資料,對這兩種花進行二分類
原始資料展示(隻展示二十行)
-1 7.00 3.20 4.70 1.40
-1 6.40 3.20 4.50 1.50
-1 6.90 3.10 4.90 1.50
-1 5.50 2.30 4.00 1.30
-1 6.50 2.80 4.60 1.50
-1 5.70 2.80 4.50 1.30
-1 6.30 3.30 4.70 1.60
-1 4.90 2.40 3.30 1.00
-1 6.60 2.90 4.60 1.30
-1 5.20 2.70 3.90 1.40
1 6.80 3.20 5.90 2.30
1 6.70 3.30 5.70 2.50
1 6.70 3.00 5.20 2.30
1 6.30 2.50 5.00 1.90
1 6.50 3.00 5.20 2.00
1 6.20 3.40 5.40 2.30
1 5.90 3.00 5.10 1.80
1 6.30 3.40 5.60 2.40
1 6.40 3.10 5.50 1.80
1 6.00 3.00 4.80 1.80
第一列是類别,1代表Setosa類鸢尾花,-1代表 Versicolour類鸢尾花。
後面四列分别對應鸢尾花的一個特征。
實驗1
資料集iris 特征數4 訓練資料量62 測試資料量22 最大學習次數1000
學習率(步長) | 學習性能 | 泛化性能 | 學習次數 | 疊代次數 |
---|---|---|---|---|
0.1 | 0.954774 | 0.954545 | 1000 | 2804 |
0.3 | 0.955306 | 0.954545 | 1000 | 2771 |
0.5 | 0.955516 | 0.954545 | 1000 | 2758 |
1.0 | 0.955242 | 1.000000 | 1000 | 2775 |
可以發現學習次數達到了最大學習次數,說明并沒有學習到可以把訓練樣本完全分開,是以我調整最大學習次數到10000,看看他能不能收斂。
實驗2
資料集iris 特征數4 訓練資料量62 測試資料量22 最大學習次數10000
學習率(步長) | 學習性能 | 泛化性能 | 學習次數 | 疊代次數 |
---|---|---|---|---|
0.1 | 0.939169 | 1.000000 | 10000 | 37715 |
0.3 | 0.939194 | 1.000000 | 10000 | 37700 |
0.5 | 0.939176 | 1.000000 | 10000 | 37711 |
1.0 | 0.939123 | 1.000000 | 10000 | 37744 |
泛化性能上升了,但并沒有收斂,我懷疑訓練樣本并不線性可分。
訓練數量的多少很多時候會影響泛化性能,我們改變訓練數量試一下。
實驗3
資料集iris 特征數4 訓練資料量30 測試資料量22 最大學習次數1000
學習率(步長) | 學習性能 | 泛化性能 | 學習次數 | 疊代次數 |
---|---|---|---|---|
0.1 | 0.934133 | 0.954545 | 125 | 247 |
0.3 | 0.934127 | 0.954545 | 126 | 249 |
0.5 | 0.934167 | 0.954545 | 120 | 237 |
1.0 | 0.934167 | 0.954545 | 120 | 237 |
減少了一些的訓練資料後發現隻學了一百多次,還沒有到最大學習次數就收斂了,說明這30個訓練資料是線性可分的。 不過泛化性能也打了折扣。
wine資料集
資料來源 https://archive.ics.uci.edu/ml/datasets/Wine
wine資料集是對意大利同一地區生産的三種酒,通過大量分析得出的資料。
這些資料包括了這三種酒的13種不同的成分,如下
Alcohol(酒精)
Malic acid(蘋果酸)
As(灰)
Alcalinity of ash(灰分的堿度)
Magnesium(鎂)
Total phenols(總酚)
Flavanoids(黃酮類化合物)
Nonflavanoid phenols(非黃烷類酚類)
Proanthocyanins(原花色素)
Color intensity(顔色強度)
Hue(色調)
OD280/OD315 of diluted wines(稀釋葡萄酒的OD280/OD315)
Proline(脯胺酸)
同樣我們選取其中兩種來做二分類。
原資料展示(隻展示20行)
-1 12.37 1.07 2.10 18.50 88.00 3.52 3.75 0.24 1.95 4.50 1.04 2.77 660.00
1 13.39 1.77 2.62 16.10 93.00 2.85 2.94 0.34 1.45 4.80 0.92 3.22 1195.00
1 13.30 1.72 2.14 17.00 94.00 2.40 2.19 0.27 1.35 3.95 1.02 2.77 1285.00
1 13.87 1.90 2.80 19.40 107.00 2.95 2.97 0.37 1.76 4.50 1.25 3.40 915.00
1 14.02 1.68 2.21 16.00 96.00 2.65 2.33 0.26 1.98 4.70 1.04 3.59 1035.00
1 13.73 1.50 2.70 22.50 101.00 3.00 3.25 0.29 2.38 5.70 1.19 2.71 1285.00
1 13.58 1.66 2.36 19.10 106.00 2.86 3.19 0.22 1.95 6.90 1.09 2.88 1515.00
1 13.68 1.83 2.36 17.20 104.00 2.42 2.69 0.42 1.97 3.84 1.23 2.87 990.00
1 13.76 1.53 2.70 19.50 132.00 2.95 2.74 0.50 1.35 5.40 1.25 3.00 1235.00
1 13.51 1.80 2.65 19.00 110.00 2.35 2.53 0.29 1.54 4.20 1.10 2.87 1095.00
-1 11.82 1.72 1.88 19.50 86.00 2.50 1.64 0.37 1.42 2.06 0.94 2.44 415.00
-1 12.51 1.73 1.98 20.50 85.00 2.20 1.92 0.32 1.48 2.94 1.04 3.57 672.00
-1 12.42 2.55 2.27 22.00 90.00 1.68 1.84 0.66 1.42 2.70 0.86 3.30 315.00
-1 12.25 1.73 2.12 19.00 80.00 1.65 2.03 0.37 1.63 3.40 1.00 3.17 510.00
-1 12.72 1.75 2.28 22.50 84.00 1.38 1.76 0.48 1.63 3.30 0.88 2.42 488.00
-1 12.22 1.29 1.94 19.00 92.00 2.36 2.04 0.39 2.08 2.70 0.86 3.02 312.00
-1 11.61 1.35 2.70 20.00 94.00 2.74 2.92 0.29 2.49 2.65 0.96 3.26 680.00
-1 11.46 3.74 1.82 19.50 107.00 3.18 2.58 0.24 3.58 2.90 0.75 2.81 562.00
-1 12.52 2.43 2.17 21.00 88.00 2.55 2.27 0.26 1.22 2.00 0.90 2.78 325.00
-1 11.76 2.68 2.92 20.00 103.00 1.75 2.03 0.60 1.05 3.80 1.23 2.50 607.00
第一列代表類别,1假設是A種酒,-1假設是B種酒。
後面的十三列分别是十三個特征的值
實驗4
資料集wine 特征數13 訓練資料量93 測試資料量37 最大學習次數1000
學習率(步長) | 學習性能 | 泛化性能 | 學習次數 | 疊代次數 |
---|---|---|---|---|
0.1 | 0.974000 | 0.594595 | 1000 | 2418 |
0.3 | 0.974000 | 1.000000 | 1000 | 2418 |
0.5 | 0.974011 | 0.594595 | 1000 | 2417 |
1.0 | 0.973989 | 0.594595 | 1000 | 2419 |
發現學習性能非常高,泛化性能很差。(除了學習率是0.3的)
我懷疑是學習率不合理或者是學習次數不夠或者訓練樣本的問題,下面分别做兩個實驗來驗證
實驗5
多調幾次的學習率,試圖找到學習率上面的問題。
資料集wine 特征數13 訓練資料量93 測試資料量37 最大學習次數1000
學習率(步長) | 學習性能 | 泛化性能 | 學習次數 | 疊代次數 |
---|---|---|---|---|
0.01 | 0.973978 | 0.594595 | 1000 | 2420 |
0.03 | 0.973968 | 0.594595 | 1000 | 2421 |
0.05 | 0.973978 | 0.972973 | 1000 | 2420 |
0.07 | 0.974000 | 0.594595 | 1000 | 2418 |
0.09 | 0.973989 | 0.621622 | 1000 | 2419 |
0.20 | 0.974000 | 1.000000 | 1000 | 2418 |
0.25 | 0.974011 | 0.594595 | 1000 | 2417 |
0.35 | 0.974000 | 1.000000 | 1000 | 2418 |
0.40 | 0.974000 | 1.000000 | 1000 | 2418 |
0.50 | 0.973989 | 0.594595 | 1000 | 2419 |
0.60 | 0.973989 | 0.594595 | 1000 | 2419 |
0.70 | 0.973989 | 0.594595 | 1000 | 2419 |
0.80 | 0.973989 | 0.594595 | 1000 | 2419 |
我試圖改變學習率來找到最佳學習率,發現調學習率就像調焦一樣,變化非常大,我認為這裡面偶然因素比較大。
實驗6
增加學習次數上限,看看能不能收斂。
資料集wine 特征數13 訓練資料量93 測試資料量37 最大學習次數50000
學習率(步長) | 學習性能 | 泛化性能 | 學習次數 | 疊代次數 |
---|---|---|---|---|
0.1 | 0.968665 | 0.972973 | 50000 | 145709 |
0.3 | 0.968657 | 1.000000 | 50000 | 145744 |
0.5 | 0.968666 | 0.918919 | 50000 | 145705 |
1.0 | 0.968673 | 1.000000 | 50000 | 145672 |
增加了學習次數上限後,雖然訓練還沒有收斂,但在50000次的學習下泛化性能普遍上升了。
實驗7
實驗6
讓我懷疑這個資料集可能是線性可分的,但大量的學習太耗費時間,是以我選擇了0.3的學習率單獨做一組大次數的學習。
資料集wine 特征數13 訓練資料量93 測試資料量37 最大學習次數500000
學習率(步長) | 學習性能 | 泛化性能 | 學習次數 | 疊代次數 |
---|---|---|---|---|
0.3 | 0.970060 | 1.000000 | 500000 | 1392197 |
雖然沒有能收斂,但在足夠大的學習次數下泛化性能還是可靠的。
實驗8
因為我訓練樣本裡面類别為1的聚在一起,為-1的聚在一起,我猜想是這個原因使得
實驗1
的學習性能虛高而泛化性能極差.
就像一個學生做練習的時候一直重複做一種題目,會導緻在練習的時候這種題目的正确率很高,但到了考試的時候各種各樣的題目他就難以适應了。
是以我把訓練集打亂再做了一次。
資料集wine打亂 特征數13 訓練資料量93 測試資料量37 最大學習次數1000
學習率(步長) | 學習性能 | 泛化性能 | 學習次數 | 疊代次數 |
---|---|---|---|---|
0.1 | 0.893645 | 0.945946 | 1000 | 9891 |
0.3 | 0.893495 | 0.810811 | 1000 | 9905 |
0.5 | 0.893785 | 0.972973 | 1000 | 9878 |
1.0 | 0.893269 | 0.972973 | 1000 | 9926 |
實驗8
是用打亂的資料集做的。
實驗4
(下圖)是用沒有打亂的資料集,用一樣的學習率,一樣的最大學習次數做的。
[外鍊圖檔轉存失敗,源站可能有防盜鍊機制,建議将圖檔儲存下來直接上傳(img-ur9Nc7x5-1571450311250)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1571386502207.png)]
對比可以發現,同樣的條件下,打亂資料集學習性能稍微差了謝,但泛化性能普遍上升,從疊代次數可以看出來,打亂資料集在學習中不停的遇到錯誤,磕磕絆絆,而未打亂的資料集疊代次數少很多,但也是以未打亂的泛化比不過打亂的。
實驗9
前面
實驗6
做了50000次的學習也沒有收斂,實驗8打亂資料集,提高了泛化能力,讓我猜想,如果用打亂的資料集做,是不是會很快的收斂呢?
資料集wine 特征數13 訓練資料量93 測試資料量37 最大學習次數50000
學習率(步長) | 學習性能 | 泛化性能 | 學習次數 | 疊代次數 |
---|---|---|---|---|
0.1 | 0.932495 | 1.000000 | 50000 | 313899 |
0.3 | 0.932515 | 1.000000 | 50000 | 313805 |
0.5 | 0.932504 | 1.000000 | 50000 | 313857 |
1.0 | 0.932500 | 1.000000 | 50000 | 313875 |
異或實驗
你可以用一條直線把紅點和藍點完全分開嗎?
你可以發現,無論你做哪一條直線都沒有辦法把紅點和藍點完全分開來。
這就是感覺機的最大缺陷,
隻能處理線性可分問題
。
異或問題是感覺機算法的當頭一棒。讓上世紀六十年代的人從感覺機的熱潮中冷靜過來,一大批的學者也是以對人工智能表示失望,認為人們對于人工智能的假想隻不過是玩玩罷了。人工智能也在那個時候陷入冷門。
抱着複現曆史難題的目的我自己捏了一個異或的資料。資料分布如下圖。
原資料展示(隻展示20行)
36.48 9.67 -1
33.64 8.39 -1
33.64 7.95 -1
30.32 7.63 -1
27.68 7.39 -1
25.92 7.31 -1
25.32 7.07 -1
24.88 5.79 -1
24.36 3.55 -1
24.24 1.39 -1
24.68 21.11 1
24.52 19.55 1
24.52 17.63 1
26.68 16.07 1
28.00 15.59 1
30.48 15.27 1
26.36 20.39 1
26.32 19.43 1
27.48 18.35 1
29.24 17.47 1
前面兩列是點的橫縱坐标,第三列是點的類别。
資料集lvh1 特征數2 訓練資料量108 測試資料量42 最大學習次數1000
學習率(步長) | 學習性能 | 泛化性能 | 學習次數 | 疊代次數 |
---|---|---|---|---|
0.1 | 0.938339 | 0.604651 | 1000 | 6721 |
0.3 | 0.938275 | 0.604651 | 1000 | 6728 |
0.5 | 0.939073 | 0.534884 | 1000 | 6641 |
1.0 | 0.937495 | 0.534884 | 1000 | 6813 |
學習性能虛高應該是因為資料集沒有打亂紅點聚在一起,黑點聚在一起導緻的。泛化性能和預期的差不多,接近0.5。
線性不可分問題困擾了人們很久,因為感覺機的輸出是離散的(-1,1),沒有辦法用基于梯度的方法來優化。
這個問題直到感覺機提出後近30年才被人解決(bp算法的提出),分類算法的才得以破冰,之是以這麼久沒有人想出來,是因為人們很難跳出離散輸出的定式思維。這是理念上的變革。
就像bengio說:可見很多看起來顯而易見的想法隻有在事後才變得顯而易見。
如果在閱讀中有疑惑或者發現有寫的不對的地方,歡迎大家提出來。
我的郵箱:[email protected]
轉載請注明出處https://blog.csdn.net/qq_44899812/article/details/102635736