感知器(perceptron)1957年由Rosenblatt提出,是神经网络与支持向量机的基础。感知器是二类分类的线性分类模型,其输入为实例的特征向量,输出为实例的类别,取+1和-1二值。感知机对应于输入空间(特征空间)中将实例划分为正负两类的分离超平面,属于判别模型。感知机学习旨在求出将训练数据进行线性划分的分离超平面。
分离超平面分类法
分离超平面进行分类的过程是构造线性判定边界,试图显示的,更好的将数据分到不同的类中。
超平面分离定理
超平面分离定力是应用凸集到最优化理论的重要结果,这个结果在最优化理论中有重要的位置。所谓两个凸集分离,直观的就是讲两个凸集没有交叉和重合的部分在一张超平面上分隔开。
感知机模型
f(x)=sign(w∙x+b)
其中,w和b为感知机参数模型,w属于R空间叫做权值或权值向量,b属于R叫做偏置,w·x表示w和x的内积,sign是符号函数,即
损失函数式
感知机学习算法
感知机学习问题转换为求解损失函数式的最优化问题,最优化的方法是随机梯度下降法。
感知机算法的原始形式
输入: 训练数据集T={(x1, y1), (x2, y2), ……, (xn, yn)}, 其中xi属于R空间,yi取+1,-1, i = 1,2,……,n;学习率η (0<η<=1)
输出: w, b; 感知机模型 f(x)=sign(w∙x+b)
1. 选取初值w0, b0;
2. 在训练集中选取数据(xi, yi);
3. 如果yi(w·xi+b)<=0,
w <- w + ηyixi
b <- b + ηyi
4. 转至2,直至训练集中没有误分类点。
当一个实例点被误分类,即位于分离超平面的错误一侧时,则调整w, b的值,使分离超平面向该误分类点的一侧移动,以减少该误分类点与超平面间的距离,直至超平面越过该误分类点使其被正确分类。
感知机学习算法由于采用不同的初始值或选取不同的误分类点,解都可能不同。
对于线性可分数据集感知机学习算法原始形式收敛,即经过有限次迭代可以得到一个将训练集完全正确划分的分离超平面及感知机模型。
感知机算法的对偶形式
在感知机的原始形式中,对w,b的修正式
w <- w + ηyixi
b <- b + ηyi
逐步修改w,b,设修改n次,则w,b关于(xi, yi)的增量分别是 αiyixi和 αiyi, αi=niη,得到
实例点更新次数越多,意味着它距离分离超平面越近,也就越难正确分类。
输入: 训练数据集T={(x1, y1), (x2, y2), ……, (xn, yn)}, 其中xi属于R空间,yi取+1,-1, i = 1,2,……,n;学习率η (0<η<=1)
输出: a, b; 感知机模型 f(x)=sign(w∙x+b)
代码实现
# -*- coding: utf-8 -*-
import random
def sign(x):
if x>0:
return 1
else:
return -1
def training():
train_data1 = [[1, 3, 1], [2, 5, 1], [3, 8, 1], [2, 6, 1]] # 正样本
train_data2 = [[3, 1, -1], [4, 1, -1], [6, 2, -1], [7, 3, -1]] # 负样本
train_datas = train_data1 + train_data2
weight = [0, 0] # 权重
bias = 0 # 偏置量
learning_rate = 0.5 # 学习速率
train_num = int(raw_input("train num: "))
for i in range(train_num):
train = random.choice(train_datas)
x1, x2, y = train
predict = sign(weight[0]*x1 + weight[1]*x2 + bias)
if y*predict <= 0:
weight[0] = weight[0] + learning_rate*y*x1
weight[1] = weight[1] + learning_rate*y*y2
bias = bias + learning_rate*y
print("update weight and bias: "),
print(weight[0], weight[1], bias)
print("stop training: "),
print(weight[0], weight[1], bias)
return weight, bias
if __name__ == "__main__":
weight, bias = training()
while True:
test_data = []
data = raw_input('enter test data(x1, x2): ')
if data == 'q': break
test_data += [int(n) for n in data.split(',')]
predict = sign(weight[0] * test_data[0] + weight[1] * test_data[1] + bias)
print("predict ==> %d" % predict)