感知机是一种二类分类的线性分类模型,其输入为实例的特征向量,输出为实例的类别,+1代表正类,-1代表负类,是神经网络和支持向量机的基础。
例如一个典型的二分类问题:银行卡申请问题,对于顾客,决定是否给予信用卡
对于一个顾客的信息(年龄、薪资、当前债务等等),我们可以用一个向量表示。然后每个信息条目(维度)均对是否给他信用卡有着正面或者负面的影响,决定我们是否给他信用卡。我们把这些维度加权叠加计算出来,结果若大于某个阈值就给,否则就不给。
设
X
=
(
x
1
,
x
2
,
.
.
.
,
x
d
)
X = (x_1,x_2,...,x_d)
X=(x1,x2,...,xd)表示客人的信息,
W
=
(
w
1
,
w
2
,
.
.
.
,
w
d
)
W=(w_1,w_2,...,w_d)
W=(w1,w2,...,wd)代表对应的权重系数。则:
{
给
,
if
∑
i
=
1
d
w
i
x
i
>
t
h
r
e
s
h
o
l
d
不
给
,
if
∑
i
=
1
d
w
i
x
i
<
t
h
r
e
s
h
o
l
d
\begin{cases} 给, & \text{if }\sum_{i=1}^{d}{w_i x_i} > threshold \\ 不给, & \text{if }\sum_{i=1}^{d}{w_i x_i} < threshold \end{cases}
{给,不给,if ∑i=1dwixi>thresholdif ∑i=1dwixi<threshold
上式子还可以写成:
h
(
x
)
=
s
i
g
n
(
(
∑
i
=
1
d
w
i
x
i
)
−
t
h
r
e
s
h
o
l
d
)
=
s
i
g
n
(
(
∑
i
=
1
d
w
i
x
i
)
+
(
−
t
h
r
e
s
h
o
l
d
)
∗
(
+
1
)
)
=
s
i
g
n
(
∑
i
=
0
d
w
i
x
i
)
=
s
i
g
n
(
w
T
x
)
\begin{aligned} h(x) &= sign((\sum_{i=1}^{d}{w_i x_i}) - threshold) \\ &= sign((\sum_{i=1}^{d}{w_i x_i}) +(- threshold) * (+1)) \\ &= sign(\sum_{i=0}^{d}{w_i x_i})\\ &= sign(w^Tx) \end{aligned}
h(x)=sign((i=1∑dwixi)−threshold)=sign((i=1∑dwixi)+(−threshold)∗(+1))=sign(i=0∑dwixi)=sign(wTx)
这样就可以看成是二个向量的内积再套一个sign函数。
感知机的学习策略:
假设样本线性可分,感知机学习的目标就是求能将正负样本完全分开的分离超平面,即要寻找w,b(因为 w x + b = 0 wx+b=0 wx+b=0确定了分离超平面)。因此我们需要确定一个学习策略,即定义损失函数,并通过训练样本使其最小化。
损失函数的一个自然选择是误分类点的总数,但是,通过这种方式定义的损失函数对参数w,b来说不是连续可导函数,不易于优化。所有感知机采取的是误分类点到超平面S的总距离。损失函数的推到如下:
设训练集为 T = { ( x 1 , y 1 ) , ( x 2 , y 2 ) , . . . , ( x n , y n ) , } T = \{(x_1,y_1),(x_2,y_2),...,(x_n,y_n),\} T={(x1,y1),(x2,y2),...,(xn,yn),},其中 x i x_i xi就相当于我们示例中的客人信息(特征向量), y i y_i yi代表是否给信用卡(-1或+1)。则任意点 x i x_i xi到超平面的距离为 d = w ∗ x i + b ∣ ∣ w ∣ ∣ d = \frac{w*x_i +b}{||w||} d=∣∣w∣∣w∗xi+b
设超平面S的误分类点集合为M,则误分类点到S的总距离为:
s
=
−
1
∣
∣
w
∣
∣
∑
x
i
∈
M
y
i
∗
(
w
∗
x
i
+
b
)
=
−
∑
x
i
∈
M
y
i
∗
(
w
∗
x
i
+
b
)
,
1
∣
∣
w
∣
∣
可忽略
\begin{aligned} s &= - \frac{1}{||w||} \sum_{x_i\in M} y_i * (w * x_i + b)\\ &= - \sum_{x_i\in M} y_i * (w * x_i + b) ,\frac{1}{||w||}\text{可忽略} \end{aligned}
s=−∣∣w∣∣1xi∈M∑yi∗(w∗xi+b)=−xi∈M∑yi∗(w∗xi+b),∣∣w∣∣1可忽略
感知机学习问题转化为求解上述损失函数的最优化问题,这里可以通过随机梯度下降法来求解。
-
首先,任意选取一个超平面,然后用梯度下降法不断地极小化目标函数(损失函数) m i n L ( w , b ) = − ∑ x i ∈ M y i ∗ ( w ∗ x i + b ) minL(w,b) = - \sum_{x_i\in M}{} y_i * (w * x_i + b) minL(w,b)=−∑xi∈Myi∗(w∗xi+b)。极小化过程中一次随机选取一个误分类点使其梯度下降。
-
随机梯度下降:
-
对w求偏导:$\nabla w \ L(w,b) = - \sum_{x_i\in M} y_i * x_i $
-
对b求偏导: ∇ b L ( w , b ) = − ∑ x i ∈ M y i \nabla b \ L(w,b) = - \sum_{x_i\in M} y_i ∇b L(w,b)=−∑xi∈Myi
-
更新w,b
w ⟸ w − η ∗ ( − y i ∗ x i ) b ⟸ b − η ∗ ( − y i ) w \Longleftarrow w- \eta *(-y_i * x_i) \\ b \Longleftarrow b- \eta *(-y_i) w⟸w−η∗(−yi∗xi)b⟸b−η∗(−yi)
-
-
判断是否还有误分类点,有则继续,没有则训练结束
举个例子,这个是上课老师布置的作业题目,我们解决下:
方法一:直接Python 冲了它
import numpy as np
import matplotlib.pyplot as plt
import random
# 符号函数
def sign(v):
if v >= 0:
return 1
else:
return -1
def train(train_num, train_data, lr=0.5): # 原始训练部分
w = [1., 1.] # 初始化权重向量和偏置
b = -1
for i in range(train_num):
#x = random.choice(train_data)
for x in train_data:
x1, x2, y = x
if y * sign(x1 * w[0] + x2 * w[1] + b) <= 0:
w[0] += lr * y * x1
w[1] += lr * y * x2
b += lr * y
#print(w,b)
return w, b
# 画散点图
def plot_points(train_data, w, b):
plt.figure()
x1 = np.linspace(-1.5, 1.5, 100)
x2 = (-b - w[0] * x1) / w[1] # 化简 w1*x1 + w2*x2 + b =0 此时x2相当于竖轴坐标
plt.plot(x1, x2, color='r', label='y1 data')
datas_len = len(train_data)
for i in range(datas_len):
if train_data[i][-1] == 1:
plt.scatter(train_data[i][0], train_data[i][1], s=50)
else:
plt.scatter(train_data[i][0], train_data[i][1], marker='x', s=50)
plt.show()
if __name__ == '__main__':
train_data1 = [[-0.30,0.96,1],[1.49,0.25,1],[0.78,0.96,1]] # 正样本
train_data2 = [[-0.89,-1.62,-1], [0.06,-0.68,-1],[-1.13,0.14,-1]] # 负样本
data_set = train_data1 + train_data2 # 样本集
w, b = train(100, data_set, 0.5) # lr 学习率
plot_points(data_set, w, b)
结果如下:
输出 w = ( 0.85 , 1.48 ) b = − 0.5 w = (0.85, 1.48) \ b = -0.5 w=(0.85,1.48) b=−0.5
方法二: 手算呗…
已知初值
w
=
(
1
,
1
)
b
=
−
1
w = (1,1) \ b = -1
w=(1,1) b=−1,分别待入样本,当
x
=
−
0.3
,
y
=
0.96
x = -0.3,y =0.96
x=−0.3,y=0.96时不符合,则更新
w
和
b
w和b
w和b
w
=
w
+
η
(
−
0.3
,
0.96
)
=
(
0.85
,
1.48
)
b
=
b
+
η
∗
(
+
1
)
=
−
0.5
w = w + \eta(-0.3,0.96) = (0.85,1.48) \\ b = b + \eta *(+1) = -0.5
w=w+η(−0.3,0.96)=(0.85,1.48)b=b+η∗(+1)=−0.5
之后,继续进行训练,此时可能数据比较好,均通过了训练。训练结束…