感知机
感知机
一、感知机模型(感知机的目标是:求一个能够将训练集正实例和负实例完全正确分开的的超平面。)
感知机是二分类线性模型,输入是实例的特征向量,输出为实例的类别,取+1和-1。感知机学习算法简单易学分为原始形式和对偶形式。
假设输入空间X\(\subseteq\)Rn,输出空间是Y={+1,-1},输入x\(\subseteq\)X表示实例的特征量,对应于输入空间的点,输出y\(\in\)Y表示实例的类别,由输入空间到输出空间的如下数:
称为感知机。其中w和b为感知机模型参数,sign(\(\cdot\))是符号函数。感知机是一种线性分类器模型,属于判别模型。感知机模型的假设空间是定义在特征空间中所有的线性分类器模型或线性分类器。感知机有如下集合解释:线性方程
对应于特征空间Rn中的一个超平面S,其中w是S的法向量,b是S的截距。S被划分为两个部分。S中两个部分的点被分为正、负两类。因此,S被称为分离超平面。

感知机学习,由训练数据集
其中,xi\(\subseteq\)X=Rn,yi\(\subseteq\)Y={+1,-1},i=1,2,\(\cdots\),N,求得感知机。通过感知机预测,对于一个新的输入会给出对应的输出。
二、感知机学习策略
在这里我们将感知机形象化。针对平面上(如图2)一群随机的点,找到一条合适的直线\(y=w{\cdot}x+b\),将这群点分为两大类。

产生图2的代码如下:
# 2022.9.13
# 一只野生小小钱
# 随机生成点
import numpy as np
import matplotlib.pyplot as plt
x = []
y = []
num = 1000
# numpy.random.normal(loc, scale, size=None) loc均值,scale标准差, size输出值的维度
x1 = np.random.normal(20, 10, int(num / 2))
y1 = np.random.normal(20, 10, int(num / 2)) # 在点 (20, 10) 周围生成点
x2 = np.random.normal(60, 10, int(num / 2))
y2 = np.random.normal(60, 10, int(num / 2)) # 在点 (60, 10) 周围生成点,保证生成的点是可被划分的
for i in range(num):
if i < num / 2:
x.append([x1[i], y1[i]])
y.append(-1)
else:
x.append([x2[int(i - num / 2)], y2[int(i - num / 2)]])
y.append(1)
data = np.array(x)
label = np.array(y)
# np.where(condition,x,y) 当where内有三个参数时,第一个参数表示条件,当条件成立时where方法返回x,当条件不成立时where返回y
# np.where(condition) 当where内只有一个参数时,那个参数表示条件,当条件成立时,where返回的是每个符合condition条件元素的坐标,返回的是以元组的形式
idx_p = np.where(label == 1)
idx_n = np.where(label == -1)
data_p = data[idx_p]
data_n = data[idx_n]
plt.scatter(data_p[:, 0], data_p[:, 1], color='red')
plt.scatter(data_n[:, 0], data_n[:, 1], color='blue')
# plt.savefig("2.png")
plt.show()
在图2中寻找一条直线,以将图1中红蓝点分开。

产生图3的代码如下:
# 2022.9.13
# 一只野生小小钱
# 随机生成点
import numpy as np
import matplotlib.pyplot as plt
data_set = []
data_label = []
num = 1000
x1 = np.random.normal(20, 10, int(num / 2))
y1 = np.random.normal(20, 10, int(num / 2)) # 在点 (20, 10) 周围生成点
x2 = np.random.normal(60, 10, int(num / 2))
y2 = np.random.normal(60, 10, int(num / 2)) # 在点 (60, 10) 周围生成点,保证生成的点是可被划分的
for i in range(num):
if i < num / 2:
data_set.append([x1[i], y1[i]])
data_label.append(-1)
else:
data_set.append([x2[int(i - num / 2)], y2[int(i - num / 2)]])
data_label.append(1)
data = np.array(data_set)
label = np.array(data_label)
w = np.array([1, 1])
b = -100
f = (np.dot(data, w.T) + b) * label
idx = np.where(f <= 0)
x00 = np.arange(9, 100, 1)
y0 = (w[0] * x00 + b) / (-w[1])
idx_p = np.where(label == 1)
idx_n = np.where(label == -1)
data_p = data[idx_p]
data_n = data[idx_n]
plt.scatter(data_p[:, 0], data_p[:, 1], color='red')
plt.scatter(data_n[:, 0], data_n[:, 1], color='blue')
# plt.savefig("1.png")
plt.plot(x00, y0)
# plt.savefig("2.png")
plt.show()
从图3中可以看到这条直线的分离效果并不好。那么我们判断好与不好的依据就是直线的下方都是蓝色的点,直线的上方都是红色的点,如何实现这种方法呢?这里使用损失函数极小化的方法。为此,输入空间上的点x0到S上的距离可以定义为(这里为什么不是\(d={\frac{\mid{w{\cdot}x_0+b-y_0}\mid}{\sqrt{w^2+1}}}\),是因为有个映射的过程,如果想不通欢迎评论区留言共同讨论):
其次,对于分类错误的点(xi,yi)来说,有:\(-y_i(w{\cdot}x_i+b)>0\)(值得注意的是\(y_i{\in}\{+1,-1\}\))。错误点到S的距离可以表示为:
所有错误点距离的总和可以表示为:
已知训练集(xi,yi)\(\in\)M,通过训练集训练迭代不断调整\(w和b\),使\(d_i\)最小化。
三、算法流程
算法的大致可以描述为:目标是找到一个平面S让一组数据\(T=\{(x_1,y_1),(x_2,y_2),\cdots,(x_n,y_n)\}\)分成两大类,其中\(x_i{\in}X=R^n\),\(y_i=\{+1,-1\}\),\(i=1,2,\cdots,N\)。上述问题可以转化为下面公式的解:
\(M\)是错误点的集合。算法步骤可以表示为:首先,任意选取一个超平面(确定\(w和b\)的初始值\(w_0和b_0\)),然后使用梯度下降法不断优化目标函数。
假设\(M\)是固定不变的,那么损失函数的梯度可以表示为:
通过\((x_i,y_i)\)不断对\(w和b\)进行更新:
其中\(\eta\)就是学习率(也是步长),这样就不断迭代达到让目标函数最小的目的。
伪代码大致流程如下:
输入:训练集\(T=\{(x_1,y_1),(x_2,y_2),{\cdots},(x_n,y_n)\}\),其中\(x_i=X{\in}R^n\),\(y_i{\in}\{+1,-1\}\),\(i=1,2,3,{\cdots},N\),学习率\(\eta(0<{\eta}<1)\)。
输出:\(w,b\)。感知机模型\(f(x)=sign(w{\cdot}x+b)\)。
-
选取任意的\(w、b\);
-
在训练集中选取任意的\((x_i,y_i)\);
-
如果\(y_i(w{\cdot}x_i+b){\leqslant}0\),
\[w{\leftarrow}w+{\eta}y_ix_i \]\[b{\leftarrow}b+{\eta}y_i \]
4.转至(2)直到训练集中没有有误分类点。
四、对偶形式
这里对感知机的对偶形式不过多介绍,后面会有相应的感知机的对偶形式,有兴趣的评论区留言,本人也会给补上。
五、总结
与其无休止的抬杠,不如来一次思想火花的碰撞。
期待各位的批评指正和交流。
骂完博主记得给个关注!!!
浙公网安备 33010602011771号