感知机原始形式、对偶形式的Python实现

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

感知机学习的目标就是求得一个能够将训练数据集中正负实例完全分开的分类超平面

 

感知机原始形式

from __future__ import division
import random
import numpy as np
import matplotlib.pyplot as plt  


def sign(v):
    if v>=0:
        return 1
    else:
        return -1

def train(train_num,train_datas,lr):
    w=[0,0]
    b=0
    for i in range(train_num):
        x=random.choice(train_datas)
        x1,x2,y=x
        if(y*sign((w[0]*x1+w[1]*x2+b))<=0):
            w[0]+=lr*y*x1
            w[1]+=lr*y*x2
            b+=lr*y
    return w,b
def plot_points(train_datas,w,b):
    plt.figure()
    x1 = np.linspace(0, 8, 100)  
    x2 = (-b-w[0]*x1)/w[1]
    plt.plot(x1, x2, color='r', label='y1 data')
    datas_len=len(train_datas)
    for i in range(datas_len):
        if(train_datas[i][-1]==1):
            plt.scatter(train_datas[i][0],train_datas[i][1],s=50)  
        else:
            plt.scatter(train_datas[i][0],train_datas[i][1],marker='x',s=50)  
    plt.show()


if __name__=='__main__':
    train_data1 = [[1, 3, 1], [2, 2, 1], [3, 8, 1], [2, 6, 1]]  # 正样本
    train_data2 = [[2, 1, -1], [4, 1, -1], [6, 2, -1], [7, 3, -1]]  # 负样本
    train_datas = train_data1 + train_data2  # 样本集
    w,b=train(train_num=50,train_datas=train_datas,lr=0.01)
    plot_points(train_datas,w,b)

 

感知机对偶形式

感知机原始形式、对偶形式的Python实现_第1张图片

通俗理解“原问题难以求解或者求解的消耗较高,因而转为求解它的对偶问题”。

此处,对偶问题主要解决的是将感知机的对偶形式中对w,b的学习变成了对α,b的学习,原始形式中,w在每一轮迭代错分时都需要更新,而采用对偶形式时,对于某一点(xi,yi)发生错分时,我们只需要更新其对应的αi即可,即可一次计算出w. 

感知机原始形式、对偶形式的Python实现_第2张图片

 

另外,xj⋅xi仅以内积的形式出现,因此我们可以先计算出x的gram矩阵存储起来,这样正式训练时只需要查表就可以得到xj⋅xi的值,这样做可以方便程序的优化,提高运算的速度。 

相当于不断更新xj⋅xi之前的系数,而不用每次像原始形式那样去计算向量积。

from __future__ import division
import random
import numpy as np
import matplotlib.pyplot as plt  


def sign(v):
    if v>=0:
        return 1
    else:
        return -1

def train(train_num,train_datas,lr):
    w=0.0
    b=0
    datas_len = len(train_datas)
    alpha = [0 for i in range(datas_len)]
    train_array = np.array(train_datas)
    gram = np.matmul(train_array[:,0:-1] , train_array[:,0:-1].T)
    for idx in range(train_num):
        tmp=0
        i = random.randint(0,datas_len-1)
        yi=train_array[i,-1]
        for j in range(datas_len):
            tmp+=alpha[j]*train_array[j,-1]*gram[i,j]
        tmp+=b
        if(yi*tmp<=0):
            alpha[i]=alpha[i]+lr
            b=b+lr*yi
    for i in range(datas_len):
        w+=alpha[i]*train_array[i,0:-1]*train_array[i,-1]
    return w,b,alpha,gram

def plot_points(train_datas,w,b):
    plt.figure()
    x1 = np.linspace(0, 8, 100)
    x2 = (-b-w[0]*x1)/(w[1]+1e-10)
    plt.plot(x1, x2, color='r', label='y1 data')
    datas_len=len(train_datas)
    for i in range(datas_len):
        if(train_datas[i][-1]==1):
            plt.scatter(train_datas[i][0],train_datas[i][1],s=50)  
        else:
            plt.scatter(train_datas[i][0],train_datas[i][1],marker='x',s=50)  
    plt.show()

if __name__=='__main__':
    train_data1 = [[1, 3, 1], [2, 2, 1], [3, 8, 1], [2, 6, 1]]  # 正样本
    train_data2 = [[2, 1, -1], [4, 1, -1], [6, 2, -1], [7, 3, -1]]  # 负样本
    train_datas = train_data1 + train_data2  # 样本集
    w,b,alpha,gram=train(train_num=500,train_datas=train_datas,lr=0.01)
    plot_points(train_datas,w,b)

 

参考:http://blog.csdn.net/winter_evening/article/details/70196040

 

转载于:https://my.oschina.net/u/1462678/blog/1573579

你可能感兴趣的:(感知机原始形式、对偶形式的Python实现)