感知机原理以及python实现

感知机原理以及python的实现

  • 感知机
    • 感知机的定义
    • 数据的线性可分
    • 损失函数
    • 感知机的原始算法
    • 原始算法的例题
    • 感知机原始算法的对偶形式
    • 对偶形式的算法过程
    • 对偶形式的优点
    • 感知机算法的python实现
    • 线性可分与凸壳
    • 参考资料

感知机

  感知机是一个二分类的线性分类模型,输入数据为实例的特征向量,输出为实例的分类,输出取+1和-1两个值。感知机是一个分类模型,旨在找出一个超平面,这个超平面能够正确的将输入数据分类。感知机是支持向量机和神经网络的基础。
感知机原理以及python实现_第1张图片

感知机的定义

  假设 x x x 表示为实例的特征向量,对应于输入空间的一个点,输出空间 f ( x ) f(x) f(x) 表示 x x x 的类别,那么从 x x x f ( x ) f(x) f(x) 的映射可以写为:

f ( x ) = s i g n ( w ⋅ x + b ) f(x) = sign (w·x + b ) f(x)=sign(wx+b)
  从输入空间到输出空间的映射称之为感知机,其中 x x x 表示为输入空间的一个实例, w w w b b b 为感知机的参数, w w w 相当于实例 x x x 的系数,也叫做权值。 b ∈ R b∈R bR 叫做偏移量。 s i g n sign sign 函数即为常见的+1 和 -1的判断函数。

数据的线性可分

  给定一个数据集 T
T = [ ( x 1 , y 1 ) , ( x 2 , y 2 ) , . . . . , ( x n , y n ) ] T = [(x_1,y_1),(x_2,y_2),....,(x_n,y_n)] T=[x1,y1),(x2,y2),....,(xn,yn]
  如果存在一个超平面,可以将数据集 T 中所有的向量完全正确的划分在超平面的两侧。那么就称这个数据集线性可分,否则,线性不可分。

损失函数

  假设一个数据集 T 是线性可分的,根据我们的数据,要寻找出一个能够将数据完全正确划分开的超平面。感知机的映射函数为
f ( x ) = s i g n ( w ⋅ x + b ) f(x) = sign (w·x + b ) f(x)=sign(wx+b)
  也就是我们需要确定 f ( x ) f(x) f(x) w w w b b b 的值。因此我们需要采取一个方法,即定义一个损失函数,并将损失函数极小化。
 损失函数的一个选择方法是选择误分类的点数。但是不能根据这样的方式推导出 w w w b b b 的值。另一个方法是选择误分类点到超平面 S S S的距离。一个点 x 0 x_0 x0到超平面 S S S的距离为:
1 ∣ ∣ w ∣ ∣ ∣ w ⋅ x 0 + b ∣ \frac{1}{||w||}|w·x_0 + b| w1wx0+b
  因为错误分类的点到超平面的距离与将改错误点正确分类到超平面的距离总是相反的,所以误分类的点到超平面的距离则是:
− 1 ∣ ∣ w ∣ ∣ y 0 ( w ⋅ x 0 + b ) -\frac{1}{||w||}y_0(w·x_0 + b) w1y0(wx0+b)
  假设分类错误的点的个数为N,因此所有错误的点到超平面的距离可以表示为:

− 1 ∣ ∣ w ∣ ∣ ∑ i = 1 N y i ( w ⋅ x i + b ) -\frac{1}{||w||} \sum_{i=1}^Ny_i(w·x_i + b) w1i=1Nyi(wxi+b)
这里对 1 ∣ ∣ w ∣ ∣ \frac{1}{||w||} w1进行删除的话,就得到了感知机的损失函数:
L ( w , b ) = − ∑ i = 1 N y i ( w ⋅ x i + b ) L(w,b) =-\sum_{i=1}^Ny_i(w·x_i + b) Lw,b=i=1Nyi(wxi+b)
  删除的原因一方面是我们追求的是损失函数为0的情况下的 w w w b b b
根据这个式子我们可以看出来,如果错误分类的数量为0,那么损失函数也为0,所以和系数没有多大的关系。并不影响最终结果。并且损失函数始终为正。并且损失函数为连续可导函数。

感知机的原始算法

给定一个数据集
T = [ ( x 1 , y 1 ) , ( x 2 , y 2 ) , . . . . , ( x n , y n ) ] T = [(x_1,y_1),(x_2,y_2),....,(x_n,y_n)] T=[x1,y1),(x2,y2),....,(xn,yn]
给定一个学习率 η \eta η(0 < η \eta η < 1)

  1. w w w b b b 赋初始值 w 0 w_0 w0 b 0 b_0 b0
  2. 选取一个数据点 ( x i , y i ) (x_i,y_i) (xi,yi),并判断是否分类正确。根据公式 y I ( w ∗ x i + b ) y_I(w*x_i+b) yI(wxi+b) 和0的大小来进行判断,大于0则分类正确。 如果分类错误
  3. 就对 w w w b b b进行更新,公式为:
    w = w + η x i y i w = w + \eta x_iy_i w=w+ηxiyi
    b = b + η y i b = b + \eta y_i b=b+ηyi
  4. 重复步骤2和步骤3,直到没有错误分类点。
  5. 最后我们就得到了感知机的参数 w w w b b b

原始算法的例题

x 1 = ( 3 , 3 ) , y 1 = 1 , x 2 = ( 4 , 3 ) , y 2 = 1 , x 3 = ( 1 , 1 ) , y 1 = − 1 x_1 = (3,3),y_1 = 1,x_2 = (4,3),y_2=1,x_3=(1,1),y_1=-1 x1=(3,3),y1=1,x2=(4,3),y2=1,x3=(1,1),y1=1组成的数据集 T = { ( x 1 y 1 ) , ( x 2 , y 2 ) , ( x 3 , y 3 ) } T=\lbrace(x_1y_1),(x_2,y_2),(x_3,y_3)\rbrace T={(x1y1),(x2,y2),(x3,y3)}
试构建感知机原始算法模型

  1. w w w b b b 赋初值为 w 0 = 0 , b 0 = 0 w_0=0,b_0=0 w0=0,b0=0。对 η \eta η 赋初值为 1.
  2. 选取数据点 ( x 1 , y 1 ) (x_1,y_1) (x1,y1),判断是否分类正确。
    y 1 ( w 0 ∗ x 1 + b 0 ) = 0 y_1(w_0*x_1+b_0) = 0 y1(w0x1+b0)=0 分类错误
  3. w w w b b b进行更新:
    w 1 = w 0 + η x 1 y 1 = ( 3 , 3 ) w_1 = w_0 + \eta x_1y_1 = (3,3) w1=w0+ηx1y1=(3,3)
    b 1 = b 0 + η y 1 = 1 b_1 = b_0 + \eta y_1 = 1 b1=b0+ηy1=1
  4. x 1 , x 2 x_1,x_2 x1x2进行判断,因为 y 2 ( w 1 ∗ x 2 + b 1 ) > 0 , y 1 ( w 1 ∗ x 1 + b 1 ) > 0 y_2(w_1*x_2+b_1)>0,y_1(w_1*x_1+b_1)>0 y2(w1x2+b1)>0,y1(w1x1+b1)>0所以这两个分类正确。
  5. x 3 x_3 x3进行判断,因为
    y 3 ( w 1 ∗ x 3 + b 1 ) < 0 y_3(w_1*x_3+b_1)<0 y3(w1x3+b1)<0 所以第三个数分类错误。
  6. w w w b b b进行更新:
    w 2 = w 1 + η x 3 y 3 = ( 2 , 2 ) w_2 = w_1 + \eta x_3y_3 = (2,2) w2=w1+ηx3y3=(2,2)
    b 2 = b 1 + η y 3 = 0 b_2 = b_1 + \eta y_3 = 0 b2=b1+ηy3=0
  7. 然后重复检查 x 3 x_3 x3,直到 x 3 x_3 x3套入公式后>0,然后重复步骤2-6。直到所有数据全部分类正确。
  8. 最终结果为 w 7 = ( 1 , 1 ) , b = − 3 w_7 = (1,1),b = -3 w7=(1,1),b=3

感知机原始算法的对偶形式

  在上面感知机的算法原理求解例题过程中,可以发现会检查很多次是否正确分类。假设修改了n次,则 w , b w,b w,b 每次修改的增量为 α i y i x i \alpha_iy_ix_i αiyixi α i y i \alpha_iy_i αiyi , 因为 η \eta η 为常数,所以整合为 α \alpha α ,即 α i = n η i \alpha_i = n\eta_i αi=nηi。那么最终的 w , b w,b w,b 可以分别表示为:
w = ∑ i = 1 N α i y i x i w = \sum_{i=1}^N\alpha_iy_ix_i w=i=1Nαiyixi
b = ∑ i = 1 N α i y i b = \sum_{i=1}^N\alpha_iy_i b=i=1Nαiyi
那么最终,感知机的对偶形式可以变化为:
f ( x ) = s i g n ( ∑ j = 1 N α j y j x j ⋅ x + b ) f(x) = sign (\sum_{j=1}^N\alpha_jy_jx_j · x + b ) f(x)=sign(j=1Nαjyjxjx+b)
这里用 j j j不用 i i i是因为要区分数据集中的 i i i

对偶形式的算法过程

  1. α \alpha α b b b 赋值为 0
  2. 选取数据集的 ( x i , y i ) (x_i,y_i) (xi,yi)
  3. 如果 y i ( ∑ j = 1 N α j x j y j ⋅ x i + b ) ≤ 0 y_i(\sum_{j=1}^N\alpha_jx_jy_j·x_i+b)\leq0 yi(j=1Nαjxjyjxi+b)0
    α i = α i + η \alpha_i = \alpha_i + \eta αi=αi+η
    b = b + η y i b= b + \eta y_i b=b+ηyi
  4. 重复步骤2-3 直到没有误分类数据。

对偶形式的优点

 假设按照感知机原始形式所有的参数更新一共需要n次,对偶形式就是把这n次分摊到i个样本中去,这样最终的参数可以展开使用每个样本点进行表示,这样在判断误分类的时候的计算就都可以展开成样本之间的点乘形式,这样就可以通过提前算好的Gram矩阵来大大降低计算量,因为仅仅计算了一次,后续全部通过查表就可以了。而反观原始形式,每次参数改变,所有的矩阵计算全部需要计算,导致计算量比对偶形式要大很多。

感知机算法的python实现

import numpy as np 
import matplotlib.pyplot as plt 
import time

def check(x,y,w,b): # 检查是否正确分类
    wx = w * x
    wx = sum(wx)
    result = y * (wx + b)
    if result > 0:
        return True
    else:
        return False

def regirt(x,y,n,w,b):# 将w, b 进行更新
    w = w + n*x*y
    b = b + n*y
    return w, b

def find_all(x_data, y_data, w, b): # 感知机流程
    data_len = len(x_data)
    i = 0
    while(i<data_len):
        print('正在测试',x_data[i], y_data[i])
        if check(x_data[i], y_data[i], w, b) == True:
            print(x_data[i], y_data[i], '分类正确')
            i += 1
        else:
            print( sum((w * x_data[i] + b) * y_data[i]), '< 0 ')
            w, b = regirt(x_data[i], y_data[i], n, w, b)
            print( 'w b 更新为:',w,b);
            i = 0
        print("\n")
    print('最终的w b 为:', w, b)
    return w, b 


if __name__ == "__main__":
    x_data = np.array([[3,3],[4,3],[1,1]])
    y_data = np.array([1,1,-1])
    w = 0
    b = 0
    n = 1
    find_all(x_data,y_data, w, b)

线性可分与凸壳

这里可以参考其他的博客,内容过多,以后再做详解。
https://blog.csdn.net/y954877035/article/details/52210734

参考资料

参考资料
[1]:https://www.zhihu.com/question/26526858
[2]:https://blog.csdn.net/weixin_43314519/article/details/106996639
[3]:https://blog.csdn.net/qq_29591261/article/details/77945561
[4]: 《统计学习方法》(第二版) 李航

你可能感兴趣的:(数据挖掘,机器学习,算法)