参考:
统计学习方法(第二版) 李航著
目录
一、感知机的定义
假设输入空间(特征空间)是,输出空间是。输入表示实例的特征向量,对应与输入空间(特征空间)的点;输出表示实例的类别。由输入空间到输出空间的如下函数:
称为感知机。是符号函数,即
二、感知机模型
感知机是一个二分类的线性分类器,输入为特征向量,输出为实例的类别,属于判别模型。感知机模型的假设空间是定义在特征空间中的所有线性分类模型或线性 分类器,即函数集合。
通过学习得到感知机模型,对于新的输入实例给出其对应的输出类别。
三、感知机学习策略
假设训练数据是线性可分的,感知机的学习目标是求得一个能够将数据集正实例点和负实例点完全正确分开的超平面。为找出这样的超平面,需要确定感知机的模型参数 ,使得损失函数最小。
给定训练集
其中,,, = 1,2,3,···,N。感知机学习的损失函数定义为:
感知机学习的策略是在假设空间中选取使损失函数最小的模型参数,即感知机模型。
四、感知机学习算法
4.1感知机学习算法的原始形式
输入:训练数据集,其中其中,,, = 1,2,3,···,N ;学习率 ;
输出: ;感知机模型
- 选取初值 ;
- 在训练集中选取数据 ;
- 如果 :
- 转至2,直至训练集中没有误分类点
根据统计学习方法中的数据,得到如下的python代码
"""
感知机:
感知机是二分类的线性分类模型,输入为实例的特征向量,输出为实例的类别(+1和-1)
#0.输入数据集
#1.选取初值w、b
#2.在训练集中选取数据x_i,y_i
#3.如果y_i(w*x_i+b)<=0:
更新权重和偏置参数 w=w+eta*y_i*x_i
b=b+eta*y_i
#4.转至第二步,直至训练数据集中没有误分类的点
#5.输出w,b,感知机模型
"""
# 原始形态
import numpy as np
import matplotlib.pyplot as plt
x = np.array([[3, 3], [4, 3], [1, 1]]) # 样本集
y = np.array([1, 1, -1]) # 样本标签
w = np.array([0, 0]) # 权重
b = 0 # 偏置
eta = 1 # 学习率
num = 0 # 参数更新次数
flag = 0 # 设计一个标志,表示是否还有误分类点 0:无误分类点 1:有误分类点
# 设计一个函数来绘制直线
def plot_line(w_p, b_p):
x_p = np.linspace(0, 5, 10)
if w_p[1] == 0:
if w_p[0] == 0:
return # w_p[0]为0,什么直线都无法绘制,直接绘制散点图就行
else:
plt.axvline(x=-b_p, ls='--', c='green') # w_p[1]为0,可以绘制出垂直线
y_p = -(w_p[0] * x_p + b_p) / w_p[1] # 两个都不为0,正常绘制,w_p[0]*x+w[1]*y+b=0 等价 w*x+b=0
plt.plot(x_p, y_p, color='green')
while True:
for i in range(len(x)): # len(x)表示多少列,能表达出样本的数量
if y[i] * (np.inner(w, x[i]) + b) <= 0: # 两个向量的内积 使用np.inner(x1,x2)
w = w + eta * y[i] * x[i] # 这里是向量中每个元素单独计算,直接使用 * 就好
b = b + eta * y[i]
print(f'第{num + 1}次更新:w = {w}, b = {b}')
num = num + 1 # 参数更新次数+1
flag = 1 # 有误分类点标志
# =========可注释,不影响结果==================
# 增强可视化,绘制出样本集和直线
plt.figure()
for j in range(len(x)):
if y[j] == 1:
plt.plot(x[j][0], x[j][1], 'ro') # 红点
else:
plt.plot(x[j][0], x[j][1], 'bo') # 蓝点
plot_line(w, b) # 绘制出图像
plt.show()
# =========可注释,不影响结果==================
break # 有误分类点,结束本次遍历,进入下一次遍历样本集
if flag == 1:
flag = 0 # 更新标志
else: # 无误分点,结束循环
break
放出结果,与书本遍历结果一致:
第1次更新:w = [3 3], b = 1
第2次更新:w = [2 2], b = 0
第3次更新:w = [1 1], b = -1
第4次更新:w = [0 0], b = -2
第5次更新:w = [3 3], b = -1
第6次更新:w = [2 2], b = -2
第7次更新:w = [1 1], b = -3
迭代出的直线动态图:
4.2 感知机学习算法的对偶形式
输入:训练数据集,其中其中,,, = 1,2,3,···,N ;学习率 ;
输出: ;感知机模型
其中。
- 选取初值 ;
- 在训练集中选取数据 ;
- 如果 : ,
- 转至2,直至训练集中没有误分类点
其中表示第个实例点被误分的次数。
python代码如下:
"""
感知机:
感知机是二分类的线性分类模型,输入为实例的特征向量,输出为实例的类别(+1和-1)
#0.输入数据集
#1.选取初值alpha、b
#2.在训练集中选取数据x_i,y_i
#3.如果 y_i*{ (∑alpha[j]*y[j]*x[j]) * x_i + b } <= 0
更新参数 alpha[i] = alpha[i] + eta
b = b + eta * y_i
#4.转至第二步,直至训练数据集中没有误分类的点
#5.输出alpha,b,感知机模型
"""
# 对偶形态
import numpy as np
x = np.array([[3, 3], [4, 3], [1, 1]]) # 样本集
y = np.array([1, 1, -1]) # 样本标签
alpha = [0, 0, 0] # alpha[i]表示第i个样本点误分类的次数
b = 0 # 偏置
eta = 1 # 学习率
num = 0 # 参数更新次数
flag = 0 # 设计一个标志,表示是否有误分类点 0:无误分类点 1:有误分类点
Gram = np.dot(x, x.transpose()) # np.dot计算矩阵的乘法,能算出样本之间的内积
while True:
for i in range(len(x)): # len(x)表示多少列,能表达出样本的数量
sum_alpha = 0 # 判断是否为误分类点时,累计计算结果,每次遍历完要更新为0,避免影响下次遍历
for j in range(len(alpha)): # 遍历alpha,计算累计值
sum_alpha = sum_alpha + alpha[j] * y[j] * Gram[j, i] # Gram[j, i]表示的是x[j]与x[i]的内积
if y[i] * (sum_alpha + b) <= 0:
alpha[i] = alpha[i] + eta # 更新参数
b = b + eta * y[i]
print(f'第{num + 1}次更新:alpha = {alpha}, b = {b}')
num = num + 1
flag = 1 # 更新误分类点标志
break
if flag == 1:
flag = 0 # 更新误分类点标志
else:
break
结果如下:
第1次更新:alpha = [1, 0, 0], b = 1
第2次更新:alpha = [1, 0, 1], b = 0
第3次更新:alpha = [1, 0, 2], b = -1
第4次更新:alpha = [1, 0, 3], b = -2
第5次更新:alpha = [2, 0, 3], b = -1
第6次更新:alpha = [2, 0, 4], b = -2
第7次更新:alpha = [2, 0, 5], b = -3