1. 程式人生 > >機器學習演算法【感知機演算法PLA】【5分鐘讀完】

機器學習演算法【感知機演算法PLA】【5分鐘讀完】

本來想說3分鐘可以讀完的,但是想到自己的表達水平。我覺得可能需要多出2分鐘來理解我說的話。

感知機演算法

一開始這個名字,不懂的人覺得這個逼格很高,感覺很厲害的樣子,其實這個演算法很水的….

對於這個演算法,我們只需要知道下面這幾樣東西:
1. 這個演算法的名字:感知機演算法
2. 這個演算法的用途:分類
3. 這個演算法的實現:用一個曲線或者曲面來分隔空間。主要目的就是找到這個曲面或者曲線。 至於具體怎麼實現,會在下面說到。

演算法的實現

正如上面所說,這個演算法就是去找這樣的一個曲線,或者曲面,然後,認為在這個曲線的一面(或者一邊)是一類,另外一邊就是另外的一類。

那麼下面就講講怎麼找到這個曲線,或者曲面吧

最粗糙的方法:

Y=WX+b

就是上面的這個方程。
看起來是不是很蠢,這個東西,我們在高中的時候,大概都很少玩了吧….

但是呢,這個還是稍微高階一點點,就是這裡的都認為是向量來的~,當然啦,也可以是矩陣。

不過,矩陣在這也可以被概括為向量,所以,還是認為是向量,會比較通用

上面,我們很明顯是,可以通過一個一個算式,將輸入的X,加工一下,然後就得到了,我們的目標,Y

對於這個Y,我們這有別的用法
比如對這個Y進行加工

y={1Y>01Y<0

部分搞事的人就會問,這個0呢?


很抱歉,這個0就好像,你告訴了這個機器,在這個條件下,有50%的概率1,50%的概率是-1。所以…好像存在也蠻合理的對吧。

那這個函式改怎麼進化呢?

這裡重點強調 Wb 的變化。

迭代的方法很簡單,就是,不是有很多個測試案例麼?
我們就一個個檢查。
先隨機選這個初始值。 Wb

下面這個是我們的更新條件:
yi(WX+b)<0
乍一看好像很奇怪,但是其實非常容易理解。意思就是,我們推理的結果跟實際的結果不一致(符號相反)
因為,這裡只是考慮符號問題,所以,當然是遇到了不一致再發生改變。

怎麼變呢?

W>W+αyixi
b>b+αyi

其中α就是一個常數,我們自己給一個就好了,大小就是屬於(0,1)

對!就是像上面那樣改變!

在網上很多人,都喜歡直接說,這個就是對於錯誤例子的靠近。但是卻沒有一個人說清楚為什麼??
對此,我對他們是不是理解了這個演算法表示懷疑,但是感覺這樣的演算法…也不應該?? 算了,還是解釋一下吧

描述

這裡,我們假設算出來的新的值為yi1,之前的算出來的值是 yi0,而真實的結果是Yi,對應的,這時候的x值是xi

推理

根據我們給的定義,所以有yi0=Wxi+b。這就是所謂之前算出來的值。
後面算出來的值呢,就變成了yi1=(W+αYixi)xi+(b+αYi)

對於後面的方程,拆出來。就是, 再結合第一個式子,就得到下面

yi1yi0=αYi(xi2+1)

推理到這,我們就可以發現,要是Yi>0, 那麼新的值就會變大,否則會變小。
這裡其實,這裡,要強調一點,Yiyi0<0的,這個我們在之前也是有說到的。

正是上面的原因,所以導致了之前所說的,傳送錯誤時,往正確的結果的方向進行移動

這樣反反覆覆,就得到了我們最終想要的結果~

而上面的這個迭代過程,我們就稱之為 訓練。

插入程式碼,如果有興趣可以研究~

import pandas as pd
import numpy as np


def read(filename):
    """
    :param filename:
    :return:
    """
    df = pd.read_csv(filename)
    *data, label = list(map(list, zip(*df.values)))
    return list(zip(*data)), label


def train(data, label, TIME=10000, alpha=0.4):
    """
    :param data:
    :param label:
    :param TIME:
    :param alpha:
    :return:
    """
    w = np.random.rand(len(data[0]))
    b = np.random.random()
    data = np.array(data)
    for t in range(TIME):
        for di in range(len(data[0])):
            if (np.dot(w, data[di]) + b) * label[di] < 0:
                w = w + alpha * data[di] * label[di]
                b = b + alpha * label[di]
    return w, b


def predict(filename, w, b):
    """
    :param filename:
    :param w:
    :param b:
    :return:
    """
    data, label = read(filename)
    count = 0
    for di in range(len(data[0])):
        if (np.dot(w, data[di]) + b) * label[di] <= 0:
            count += 1
    print('%.3f' % (1 - count / len(data)))


if __name__ == '__main__':
    data, label = read('train.csv')
    w, b = train(data, label)
    predict('val.csv', w, b)