机器学习笔记1——感知机(分类)

1.模型

f ( x ) = s i g n ( w x + b )
其中, x 为输入向量。 w b 为感知机模型的参数, w 为权值向量, b 为偏置。
感知机就是一个单个的神经元,如下图所示


几何解释:线性方程 w x + b = 0 是定义在特征空间 R n 的一个超平面。其中 w 是超平面的一个法向量, b 是超平面的截距。

2 训练数据集

( x i , y i ) , i = 1 , 2 , , n ,其中 y i { + 1 , 1 }

3 损失函数:误分类点到超平面的总距离

输入空间中任意输入 x i 到超平面的距离为

1 | | w | | | w x i + b |
如果 x j 为误分类点,那么其到超平面的距离可以写为
1 | | w | | y j ( w x j + b )
那么感知机学习的损失函数为
L ( w , b ) = 1 | | w | | x j M y j ( w x j + b )
其中 M 为误分类点的集合。

4.学习算法 —— 梯度下降法

极小化过程中不是一次将所有误分类点的梯度下降,而是一次随机算去一个误分类点使其梯度下降

4.1 原始形式

需要注意的是,参数为 w b 。将损失函数分别对 w b 求偏导

w L ( w , b ) = x j M y j x j
b L ( w , b ) = x j M y j
每次选取一个点后,按照梯度的负方向更新参数即可,直到被正确分类。其实梯度下降的过程中,超平面在不断向误分类点的一侧移动。
w = w + η y j x j
b = b + η y j

4.2 对偶形式

在原始形式中,实例点更新次数越多,表明它离超平面越近,分类也就越难。在完成所有的学习之后,得到 w b 最终的表达式为

w = x j M n j η y j x j
b = x j M n j η y j
其中, n j 表示对于实例点 j 的学习次数,正确分类点 n j = 0 。在对偶形式中,学习的过程也就变为更新 n j 的过程。
这样感知机模型就可以表示为
f ( x ) = s i g n ( x j M n j η y j x j x + x j M n j η y j )
学习过程中只需要更新 n j 的优点还在于,对每次选择的实例点 x i x j x i 可以提前被离线计算,也就是Gram矩阵。这样可以大大降低运算量。

5 python实现
import numpy as np
import matplotlib.pyplot as plt
#训练数据集
TrainData_x = np.array([[3, 3], [4, 3], [1, 1]])
TrainData_y = np.array([1, 1, -1])
NumData = len(TrainData_x)
#训练数据可视化
plt.figure()
plt.scatter(TrainData_x[0:2,0], TrainData_x[0:2,1], color='r',label='positive')
plt.scatter(TrainData_x[2,0], TrainData_x[2,1], color='k',label='negative')
plt.title('perceptron')
plt.xlabel('x1')
plt.ylabel('x2')
plt.xlim([0,6])
plt.ylim([0,4])
plt.legend()

eta = 1              #步长or学习率
w = np.array([0, 0]) #法向量初始值
delta_w = np.array([[0,0],[0,0],[0,0]]) #法向量更新值
b = 0                #截距初始值
delta_b = np.zeros(NumData)
for index in range(NumData):
    delta_w[index] = eta*TrainData_x[index]*TrainData_y[index]
    delta_b[index] = eta*TrainData_y[index]
###学习过程###
CorrData = 0          #正确分类数据的数目
while 1 :
    for index in range(NumData):
        if  -TrainData_y[index]*(np.dot(w,TrainData_x[index])+b) >= 0 :   #误分类点需要更新法向量和截距                
            w = w + delta_w[index] 
            b = b + delta_b[index]     
        else:         #正确分类点无需操作
            CorrData = CorrData + 1
    if  NumData == CorrData :       #如果分类全部正确,跳出while,学习结束
        break
    else:                           #如果分类有错误,将CorrData置零,重新循环判断数据分类
        CorrData = 0 

print("w = ", w)
print("b = ", b)

line_x = [0, 6]
line_y = [0, 0]

for index in range(len(line_x)):
    line_y[index] = (-w[0] * line_x[index]- b)/w[1]

plt.plot(line_x, line_y)
plt.savefig("perceptron.png")
plt.show()

最终学习结果
w = [1 1]
b = -3.0
这里写图片描述

后记:第一次写python,从安装到调试环境到完成这段代码,比我想象多花了两倍的时间。主要是对python还不太熟悉,以后要多敲代码多练习。好好加油!

猜你喜欢

转载自blog.csdn.net/qsdzxp/article/details/79672882