学习笔记-《统计学习方法》-第二章-感知机
2 感知机
2.1 感知机模型
假设输入空间(特征空间)是,输出空间是,输入表示实例的特征向量,对应于输入空间的点;输出表示实例的类别,由输入到输出的如下函数
称为感知机。其中和为感知机模型参数。
2.2 学习策略
-
线性可分数据集:如果存在超平面
能够将数据集的正实例点和负实例点完全正确的划分到超平面的两侧,则称数据集为线性可分数据集(linearly separable data set)
-
由于空间中任意一点到超平面S的距离是
所有误分类点到超平面的总距离为
2.3 学习算法
2.3.1 原始形式
输入:训练数据集,其中;学习率;
输出:感知机模型
(1)选取初值
(2)在训练集中选取数据
(3)如果,
(4)转至(2),直至数据没有误分类点
2.3.2 算法收敛性的证明
首先将偏置也并入权重向量,记做,同样也将输入向量加以补充,加进常数1,记做,这样,显然,
Novikoff定理
设训练数据是线性可分,其中,则
(1)存在满足条件的超平面将训练集数据完全分开;且存在,对所有
(2)令,则感知机算法在训练数据集上的误分类次数满足不等式
证明:
(1)由于数据集是线性可分的,按照定义存在超平面可以将数据集完全正确分开,取超平面为,并使,因此对于有限的,均有
所以存在,
满足
(2)令是第个误分类实例之前的扩充权重向量,即
第个误分类实例的条件是
若是被误分类的数据,则
由此,推导两个不等式
由之前的式子可知
进一步递推得到
下一步证明
由前面的式子可得
结合2.12和2.13可得
所以得到
最终证明误分类次数存在上界,经过有限次搜索可以找到将训练数据完全正确分开的分离超平面。也就是说,当数据线性可分时,感知机算法是收敛的。
习题
2.1
假设二维平面,存在四个点,(1,1)、(1,-1)、(-1,1)、(-1,-1),根据异或的定义,(1,1)和(-1,-1)应被归为一类,但从二维空间看,并不存在这样一个平面,可以将这4个点,依据正负样本分隔开。
2.3
必要性:
样本线性可分->正实例点所构成的凸壳与负实例点所构成的凸壳互不相交
采用反证法
假设样本集线性可分,正实例点所构成的凸壳与负实例点所构成的凸壳相交,即存在某个元素,同时满足和。
首先样本线性可分,代表存在一个超平面,使得正、负实例处于超平面的两边,即对于所有的正实例来说,满足
根据凸壳的定义,对于中的元素,存在
同理,对于中的元素,均存在
那根据推理,不存在同时满足和。
充分性有点纠结...没有发现好理解的证明
感知机原始形式代码实现:
# 感知机的原始形式
import numpy as np
X = np.array([[3,3], [4,3], [1,1]]).T
y = np.array([1,1,-1]).T
# 构建模型
def predict(w, b, x):
f = np.dot(w , x) + b
return 1 if f > 0 else -1
# 模型训练
def train(lr=1):
# 初始化
w = np.array([0, 0])
b = 0
lr = lr
false_count = len(X)
iter_count = 0
# 迭代
while false_count != 0:
print(f"this is the {iter_count}th iter")
false_count = X.shape[1]
for x_p, y_p in zip(X.T, y):
print(f'the train set is {x_p}, {y_p}')
pre_y = predict(w, b, x_p)
# print(pre_y)
if pre_y * y_p <= 0:
w = w + lr * y_p * x_p
b = b + lr * y_p
print(w, b)
else:
false_count -= 1
print(f'false_count:{false_count}')
iter_count += 1
train()
感知机对偶形式代码实现
# 生成gram矩阵
def calculate_gram_matrix(X):
# 矩阵中不同样本是列向量
gram_matrix = np.dot(X.T, X)
return gram_matrix
#
def duality_predict(alpha, b, x_i, gram_matrix_p):
n = len(gram_matrix_p)
res = 0
for j, x_j_x_i in enumerate(gram_matrix_p):
res += alpha[j] * y[j] * x_j_x_i
res += b
return res
def duality_train():
# 初始化
alpha = np.array([0, 0, 0])
b = 0
false_count = len(X)
iter_count = 0
gram_matrix = calculate_gram_matrix(X)
# 迭代
while false_count != 0:
print(f"this is the {iter_count}th iter")
false_count = X.shape[1]
for i, (x_i, y_i) in enumerate(zip(X.T, y)):
print(f'the train set is {x_i}, {y_i}')
pre_y = duality_predict(alpha, b, x_i, gram_matrix[i])
# print(pre_y)
if pre_y * y_i <= 0:
alpha[i] += 1
b += y_i
print(alpha, b)
else:
false_count -= 1
print(f'false_count:{false_count}')
iter_count += 1
w = 0
for i, x_i in enumerate(X):
w += alpha[i] * y[i] * X[:,i]
duality_train()
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Obsidian + DeepSeek:免费 AI 助力你的知识管理,让你的笔记飞起来!
· 分享4款.NET开源、免费、实用的商城系统
· 解决跨域问题的这6种方案,真香!
· 一套基于 Material Design 规范实现的 Blazor 和 Razor 通用组件库
· 5. Nginx 负载均衡配置案例(附有详细截图说明++)