原始感知机+对偶感知机的实现(python版)

本文是参照:李航《统计学习方法》实现,如果遇到问题请参看书。

感知机

感知机是二分类的线性分类模型,在许多的机器算法模型中都可以找到它的影子,更是神经网络和支持向量机的基础,所以理解感知机模型就变得非常重要。

输入:实例的特征向量

输出:实例的类别(取值为+1,-1)

感知机学习目的:训练出一个分离超平面,将数据可以进行线性划分。

感知机学习策略:根据目的,我们可以导入基于误分类的函数,利用梯度下降法求误分类函数的极小化,进而得到感知机模型。

感知机模型

定义:假设特征空间(输入空间)是 χRn χ ⊆ R n ,输出空间是 γ={+1,1} γ = { + 1 , − 1 } ,输入 yγ y ∈ γ 表示实例的类别,由输入空间到输出空间的函数如下:

f(x)=sign(wx+b) f ( x ) = s i g n ( w ⋅ x + b )

称其为感知机,其中我 w w b b 为感知机模型参数, wRn w ⊆ R n 叫做权值或权值向量, bR b ⊆ R 叫做偏置, wx w ⋅ x 表示 w w x x 的內积, sign s i g n 是符号函数.

原始感知机算法

输入: 训练数据集 T={(x1,y1),,(xN,yN)} T = { ( x 1 , y 1 ) , ⋅ ⋅ ⋅ , ( x N , y N ) } 其中 xiχ=Rn,yiγ={1,+1},i=1,2,,N; x i ∈ χ = R n , y i ∈ γ = { − 1 , + 1 } , i = 1 , 2 , ⋅ ⋅ ⋅ , N ; 学习率 η(0<η1) η ( 0 < η ≤ 1 )

输出 w,b w , b 感知机模型 f(x)=sign(wx+b) f ( x ) = s i g n ( w ⋅ x + b )

(1)选取初值 w0,b0 w 0 , b 0

(2)在训练集中选取数据 (xi,yi) ( x i , y i )

(3)如果 yi(wx+b)0 y i ( w ⋅ x + b ) ≤ 0

ww+ηyixi w ← w + η y i x i

bb+ηyi b ← b + η y i

转至(2),直至训练集中没有误分类点

算法解释

在当一个实例点被误分类,就是当其位于分离超平面的错误的一侧,就是根据梯度下降的方法对 w,b w , b 进行调整,让分离超平面移动,使得它中所有的训练数据都被正确分类,

Python实现原始感知机算法

正实例点 x1=(3,3),x2=(4,3) x 1 = ( 3 , 3 ) , x 2 = ( 4 , 3 )

负实例点 x3=(1,1) x 3 = ( 1 , 1 )

import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline


x = np.array([[3, 3], [4, 3], [1, 1]])
y = np.array([[1], [1], [-1]])
w = [0,0]
b = 0


def train(x,y,w,b):
    length = x.shape[0]
    j = 0
    while True:
        count = 0  # 记录误分类点的数目
        for i in range(length):
            # 对矩阵进行运算


            print("迭代次数:%d w:%d %d b:%d"%(j,w[0],w[1],b))
            m = np.dot(w,x[i]) + b
            # 如果是误分类点, 0 恰好在平面上
            if m * y[i] <= 0:
                w = w + y[i]*x[i]
                b = b + y[i]
                count += 1
                j += 1
        if count == 0:
            print("\n最优参数",w,b)
            f = "f(x) = sign(%d*x+%d*y+(%d)"%(w[0],w[1],b)
            print("\n感知机模型:\n%s\n"%f)
            return w, b, f

w,b,f = train(x,y,w,b )

# 绘图
def fun(x):
    y = (-b -w[0] * x) / w[1]
    return y
x_data = np.linspace(0, 5, 100)  # 创建等差数组
y_data = fun(x_data)
plt.plot(x_data, y_data, color='r', label='y1 data')
plt.title("test")

for i in range(x.shape[0]):

    if y[i] < 0:
        plt.scatter(x[i][0], x[i][1], marker='x', s=50)
    else:
        plt.scatter(x[i][0], x[i][1], s=50)
plt.show()
迭代次数:0 w:0 0 b:0
迭代次数:1 w:3 3 b:1
迭代次数:1 w:3 3 b:1
迭代次数:2 w:2 2 b:0
迭代次数:2 w:2 2 b:0
迭代次数:2 w:2 2 b:0
迭代次数:3 w:1 1 b:-1
迭代次数:3 w:1 1 b:-1
迭代次数:3 w:1 1 b:-1
迭代次数:4 w:0 0 b:-2
迭代次数:5 w:3 3 b:-1
迭代次数:5 w:3 3 b:-1
迭代次数:6 w:2 2 b:-2
迭代次数:6 w:2 2 b:-2
迭代次数:6 w:2 2 b:-2
迭代次数:7 w:1 1 b:-3
迭代次数:7 w:1 1 b:-3
迭代次数:7 w:1 1 b:-3

最优参数 [1 1] [-3]

感知机模型:
f(x) = sign(1*x+1*y+(-3)

原始感知机+对偶感知机的实现(python版)_第1张图片

对偶感知机的实现

对偶感知机的策略和原始感知机的策略是一致的,唯一不同的是对 w,b w , b 两个参数的调整:

通过上面原始的感知机的练习我们很清晰的知道了求超平面,其实就是在不同修改函数系数 w,b w , b ,经过n次的修改后 w,b w , b 关于 xiyi ( x i , y i ) 的增量变为了 αiyixi,αiyi α i y i x i , α i y i ,其中 αi=niη α i = n i η ,所以:

w=i=1Nαiyixi w = ∑ i = 1 N α i y i x i

b=i=1Nαiyi b = ∑ i = 1 N α i y i

这样更新的的式子就可以变为,如果 yi{Nj=1αjyjxjxi+b}0 y i { ∑ j = 1 N α j y j x j ⋅ x i + b } ≤ 0

αiαi+η α i ← α i + η

bb+ηyi b ← b + η y i

技巧

在对偶形式训练数据以內积的形式出现,为了方便可以先对其內积做计算,以矩阵的形式存储起来,用的时候调用即可。这个矩阵就是Gram矩阵

G=[xixj]NN G = [ x i ⋅ x j ] N ∗ N

import numpy as np
import matplotlib.pyplot as plt


x = np.array([[3, 3], [4, 3], [1, 1]])
y = np.array([[1], [1], [-1]])

# 创建gram矩阵
z = np.transpose(x)
m = np.dot(x,z)
print("构建的Gram矩阵为:\n",m)
print("-------------------------")
a = np.zeros((x.shape[0], 1))
b = 0


def train(x,y,m,a,b):
    length = x.shape[0]
    while True:
        count = 0  
        for i in range(length):           
            n = np.dot(m[i], a * y ) + b           
            if n* y[i] <= 0:
                a[i] = a[i] + 1
                b = b + y[i]
                count += 1
        if count == 0:
            w = np.sum(x * a* y, axis=0)
            print(w,b)
            print("感知机模型:\nf(x) = sign(%dx+%dy+(%d))\n"%(w[0],w[1],b))
            return w,b
w,b = train(x,y,m,a,b)

def fun(x):
    y = (-b -w[0] * x) / w[1]
    return y
x_data = np.linspace(0, 5, 100)  # 创建等差数组
y_data = fun(x_data)
plt.plot(x_data, y_data, color='r', label='y1 data')
for i in range(x.shape[0]):

    if y[i] < 0:
        plt.scatter(x[i][0], x[i][1], marker='x', s=50)
    else:
        plt.scatter(x[i][0], x[i][1], s=50)


plt.show()
构建的Gram矩阵为:
 [[18 21  6]
 [21 25  7]
 [ 6  7  2]]
-------------------------
[1. 1.] [-3]
感知机模型:
f(x) = sign(1x+1y+(-3))

原始感知机+对偶感知机的实现(python版)_第2张图片


End

你可能感兴趣的:(机器学习)