感知机
来源:互联网 发布:知乎页面显示不正常 编辑:程序博客网 时间:2024/05/01 09:10
感知机学习算法的对偶形式:http://blog.csdn.net/qq_29591261/article/details/77945561
本文省略推理过程,直接上算法过程和代码,想看原理推导的请参考原文:http://www.hankcs.com/ml/the-perceptron.html
概念
感知机是二分类模型,输入实例的特征向量,输出实例的±类别。
定义
假设输入空间是,输出空间是,x和y分属这两个空间,那么由输入空间到输出空间的如下函数:
称为感知机。其中,w和b称为感知机模型参数,叫做权值或权值向量,叫做偏置,w·x表示向量w和x的内积。sign是一个函数:
感知机的几何解释是,线性方程
将特征空间划分为正负两个部分:
感知机学习算法
感知机算法代码
为了理解起来更容易些,我自己加了一部分注释。
- # -*-coding:utf-8 -*-
- #Filename: train2.1.py
- # Author:hankcs
- # Date:2015/1/30 16:29
- import copy
- from matplotlib import pyplot as plt
- from matplotlib import animation
- training_set= [[(1, 2), 1], [(2, 3), 1], [(3, 1), -1], [(4, 2), -1]] #我在这里修改了原文数据,原数据让线看起来像平移
- w = [0, 0] #参数初始化
- b = 0
- history = [] #用来记录每次更新过后的w,b
- def update(item):
- """
- 随机梯度下降更新参数
- :param item: 参数是分类错误的点
- :return: nothing 无返回值
- """
- global w, b,history #把w, b, history声明为全局变量
- w[0] += 1 * item[1] * item[0][0] #根据误分类点更新参数,这里学习效率设为1
- w[1] += 1 * item[1] * item[0][1]
- b += 1 * item[1]
- print w, b #输出每次更新过后的w,b以供观察
- history.append([copy.copy(w), b]) #将每次更新过后的w,b记录在history数组中
- def cal(item):
- """
- 计算item到超平面的距离,输出yi(w*xi+b)
- (我们要根据这个结果来判断一个点是否被分类错了。如果yi(w*xi+b)>0,则分类错了)
- :param item:
- :return:
- """
- res = 0
- for i in range(len(item[0])): #迭代item的每个坐标,对于本文数据则有两个坐标x1和x2
- res += item[0][i] * w[i]
- res += b
- res *= item[1] #这里是乘以公式中的yi
- return res
- def check():
- """
- 检查超平面是否已将样本正确分类
- :return: true如果已正确分类则返回True
- """
- flag = False
- for item in training_set:
- if cal(item) <= 0: #如果有分类错误的
- flag = True #将flag设为True
- update(item) #用误分类点更新参数
- if not flag: #如果没有分类错误的点了
- print "RESULT: w: " + str(w) + "b: " + str(b) #输出达到正确结果时参数的值
- return flag #如果已正确分类则返回True,否则返回False
- if __name__ == "__main__":
- for i in range(1000): #迭代1000遍
- if not check(): break #如果已正确分类,则结束迭代
- #以下代码是将迭代过程可视化
- #首先建立我们想要做成动画的图像figure, 坐标轴axis,和plot element
- fig = plt.figure()
- ax = plt.axes(xlim=(0, 2), ylim=(-2, 2))
- line, = ax.plot([], [], 'g', lw=2) #画一条线
- label = ax.text([], [], '')
- # initialization function: plot the background of each frame
- def init():
- line.set_data([], [])
- x, y, x_, y_ = [], [], [], []
- for p in training_set:
- if p[1] > 0:
- x.append(p[0][0]) #存放yi=1的点的x1坐标
- y.append(p[0][1]) #存放yi=1的点的x2坐标
- else:
- x_.append(p[0][0]) #存放yi=-1的点的x1坐标
- y_.append(p[0][1]) #存放yi=-1的点的x2坐标
- plt.plot(x, y, 'bo', x_, y_, 'rx') #在图里yi=1的点用点表示,yi=-1的点用叉表示
- plt.axis([-6, 6, -6, 6]) #横纵坐标上下限
- plt.grid(True) #显示网格
- plt.xlabel('x1') #这里我修改了原文表示
- plt.ylabel('x2') #为了和原理中表达方式一致,横纵坐标应该是x1,x2
- plt.title('Perceptron Algorithm (www.hankcs.com)') #给图一个标题:感知机算法
- return line, label
- # animation function. this is called sequentially
- def animate(i):
- global history, ax, line, label
- w = history[i][0]
- b = history[i][1]
- if w[1] == 0: return line, label
- #因为图中坐标上下限为-6~6,所以我们在横坐标为-7和7的两个点之间画一条线就够了,这里代码中的xi,yi其实是原理中的x1,x2
- x1 = -7
- y1 = -(b + w[0] * x1) / w[1]
- x2 = 7
- y2 = -(b + w[0] * x2) / w[1]
- line.set_data([x1, x2], [y1, y2]) #设置线的两个点
- x1 = 0
- y1 = -(b + w[0] * x1) / w[1]
- label.set_text(history[i])
- label.set_position([x1, y1])
- return line, label
- # call the animator. blit=true means only re-drawthe parts that have changed.
- #print history #我在这里把这行注释掉了,因为在更新参数的时候已经输出了一遍
- anim = animation.FuncAnimation(fig, animate,init_func=init, frames=len(history),interval=1000, repeat=True, blit=True)
- plt.show()
- anim.save('perceptron.gif', fps=2, writer='imagemagick') #这里并没有保存成功,我自己找了个软件截了图
运行结果
- [1, 2] 1
- [-2, 1] 0
- [-1, 3] 1
- [-4, 2] 0
- [-3, 4] 1
- RESULT: w: [-3, 4] b: 1
可视化
阅读全文
1 0
- 感知机
- 感知机
- 感知机
- 感知机
- 感知机
- 感知机
- 感知机
- 感知机
- 感知机
- 感知机
- 感知机
- 感知机
- 感知机
- 感知机
- 感知机
- 感知机
- 感知机
- 感知机
- Linux环境安装imagemagick
- 【异常解决】jxl.write.biff.JxlWriteException: Attempt to modify a referenced format
- 百度地图小区边界(轮廓)处理
- 编译安装环境部署Nextcloud私有云
- java 值类型和引用类型
- 感知机
- 通过Stringbuffer实现io流读一行,行中位置的内容修改
- 输入一个数组,用二分法查找Java实现
- maven mybatis反向工程插件
- 八大排序算法-Python
- 单点登录之cas4.2.7服务端数据库配置(读数据库验证用户并对密码进行加密)
- SVN服务器搭建--Subversio与TortoiseSVN的配置安装
- druid学习-安装
- 学习笔记之面向对象编程13(StringBuffer类)