1. 程式人生 > >感知機

感知機

上界 com 多維 true 實現 randint att class .com

一.感知機概述

感知機適用於:線性可分的數據,用於二分類

目的:找到分離超平面,完全分離不同的類

感知機公式:技術分享,一元多維的函數

感知機學習策略:通過求min(所有誤分類點到超平面距離),即損失函數,來確定權重和偏置

求解方法:梯度下降法

求解步驟:1.初始化權重和偏置

     2.任選點(x,y)

     3.若yi*(w*x+b)<=0,則更新w(new)=w(old)+eta*yi*xi,b(new)=b(old)+eta*yi ,其中0<eta<=1(這裏通常我們令eta=1)

叠代收斂說明:Novikoff定理證明出誤分類次數是有上界的,經有限次搜索可以找到分離超平面,感知機因初始值的選擇有很多解。

下面是具體代碼實現:

#感知機處理線性可分數據
import numpy as np
import random
import matplotlib.pyplot as plt
def getdata(num):#生成間隔大些的數據,需要輸入數據量
    xdata=[]
    for i in range(num):
        idata=[random.randint(0,20),random.randint(0,20)]
        if sum(idata)>=20:
            idata=[i+5 for i in idata]
        if not idata in xdata:
            xdata.append(idata)
    ydata=[1 if sum(i)>=20 else -1 for i in xdata]
    return xdata,ydata
def per(xdata,ydata,w,b):#求解w,b
    while any([ydata[i]*(w[0]*xdata[i][0]+w[1]*xdata[i][1]+b)<=0 for i in range(len(xdata))]):
        for i in range(len(xdata)):
            while ydata[i]*(w[0]*xdata[i][0]+w[1]*xdata[i][1]+b)<=0:
                    w=[w[j]+ydata[i]*xdata[i][j] for j in range(2)]
                    b=b+ydata[i]
    return w,b
def pic(w=[0,0],b=0,num=100):#畫圖
    xdata, ydata = getdata(num)
    xdata1 = [i[0] for i in xdata]
    xdata2 = [i[1] for i in xdata]
    plt.scatter(xdata1, xdata2, c=["r" if i == 1 else "b" for i in ydata],s=5)
    plot_x = [1, 25]
    w,b=per(xdata,ydata,w,b)
    plot_y = [(-1) * (b + w[0] * plot_x[0]) / w[1], (-1) * (b + w[0] * plot_x[1]) / w[1]]
    plt.plot(plot_x, plot_y)

  效果如圖所示:

技術分享

二.證明感知機不能處理異或問題

對於異或問題:

技術分享

首先,我們假設異或問題是線性可分的,則有:

技術分享

三,利用感知機處理異或問題

雖然感知機不能直接用來處理異或問題,但是我們可以通過激活函數來實現非線性問題的分類

技術分享

這裏我受到adaboost的啟發,即多個弱分類器組合成為一個強分類器,我們可以如下構造:

技術分享

下面是代碼實現:

#處理線性不可分數據,異或
import numpy as np
xdata=[[0,0,0,1],[0,1,1,1],[1,0,1,1],[1,1,1,0]]#初始化數據
ydata=[-1,1,1,-1]#初始化數據
def per(xdata,ydata,w=[0,0,0,0],b=0):#求解w,b
    while any([ydata[i]*(w[0]*xdata[i][0]+w[1]*xdata[i][1]+w[2]*xdata[i][2]+w[3]*xdata[i][3]+b)<=0 for i in range(len(xdata))]):
        for i in range(len(xdata)):
            while ydata[i]*(w[0]*xdata[i][0]+w[1]*xdata[i][1]+w[2]*xdata[i][2]+w[3]*xdata[i][3]+b)<=0:
                    w=[w[j]+ydata[i]*xdata[i][j] for j in range(4)]
                    b=b+ydata[i]
    return w,b

  結果為:

([-2, -1, 4, 3], -4)

感知機