感知机的学习算法分为原始形式和对偶形式。
具体模型理论:统计学习——感知机
本文将书中的两个算法过程,利用python实现了一下。
进行机器学习算法实现的时候,可以利用功能强大的数学运算numpy库。但在这篇文章里,没有用numpy库。数据集以数组的方式输入,在进行相关的向量运算的时候,利用数组的下标来对数组中的数据进行运算。
1. 感知机学习算法的原始形式
def vectorInnerProduct(vector1,vector2): # 实现两个向量的內积
result = 0
length = len(vector1)
for i in range(length):
result += vector1[i] * vector2[i]
return result
def elementAddition(vector1,vector2): # 实现两个向量的对应元素相加
for i in range(len(vector1)):
vector1[i] += vector2[i]
return vector1
def numberMultiply(num,vector): # 实现向量的数乘
tempVector = []
for i in range(len(vector)):
tempVector.append(vector[i] * num)
return tempVector
# 不能直接修改原来的vector,要不然带入到感知机的主函数会一边修改权重和偏置,
# 一边修改原来的数据集
"""
上面三个函数,是为了方便对数据(向量)进行相关的运算,写的辅助函数。很简单
"""
def perceptron(bias,dataSet,learnRate):
# 感知机原始算法,需要输入三个变量,偏置,数据集以及学习率。
weightVector = [0 for i in range(len(dataSet[0][0]))] # 权重向量初始化为0
while True:
# 因为要不断遍历训练集,直到没有误分类点,因此利用一个while循环,和记录误分类点数量的变量errornum
errorNum = 0
for data in dataSet: # 一遍一遍的遍历数据集,进行迭代
if data[1] * (vectorInnerProduct(weightVector,data[0])+bias) <= 0:
errorNum += 1
weightVector = elementAddition(weightVector,numberMultiply(learnRate * data[1],data[0]))
bias += learnRate * data[1]
if errorNum == 0: # 如果没有误分类点,退出循环
break
return weightVector,bias # 返回模型参数
还可以继续往下,利用学习好的模型来判断任意一个实例点的分类。这个函数只需要一个简单的if语句即可实现。
bias = 0
dataSet = [[[3,3],1],[[4,3],1],[[1,1],-1]]
learnRate = 1
print(perceptron(bias,dataSet,learnRate))
# 这个例子是统计学习方法书中例子,返回结果为([1, 1], -3)
2. 感知机学习算法的对偶形式
在对偶算法的学习过程中中,训练集中的实例仅仅以內积的形式出现,可以事先将训练集中数据之间的內积计算出来,并以矩阵的方式存储,即Gram矩阵
def vectorInnerProduct(vector1,vector2): # 向量內积
result = 0
length = len(vector1)
for i in range(length):
result += vector1[i] * vector2[i]
return result
def gramMatrix(dataSet): # 计算gram矩阵
length = len(dataSet)
gramMatrix = [[0 for i in range(length)] for i in range(length)]
for i in range(length):
for j in range(length):
gramMatrix[i][j] = vectorInnerProduct(dataSet[i][0],dataSet[j][0])
return gramMatrix
def elementAddition(vector1,vector2): # 向量元素相加
for i in range(len(vector1)):
vector1[i] += vector2[i]
return vector1
def numberMultiply(num,vector): # 数乘
tempVector = []
for i in range(len(vector)):
tempVector.append(vector[i] * num)
return tempVector
def perceptron(dataSet,learnRate): # 对偶形式的变量为数据集和学习率,alpha和偏置在函数中设置成了0
n = len(dataSet)
alphaList= [0 for i in range(n)]
bias = 0
gram = gramMatrix(dataSet)
while True: # 具体的思路和原始算法一样,只是一些细节(判定条件和学习表达式)修改了一下
errorNum = 0
for i in range(n):
tempSum = 0
for j in range(n):
tempSum += alphaList[j] * dataSet[j][1] * gram[j][i]
if dataSet[i][1] * (tempSum + bias) <= 0:
errorNum += 1
alphaList[i] += learnRate
bias += learnRate * dataSet[i][1]
if errorNum == 0:
break
# 在学习过程中学习的是alpha,利用学习的alpha计算最终的权值向量
weightVector = numberMultiply(alphaList[0]*dataSet[0][1],dataSet[0][0])
for i in range(1,n):
weightVector = elementAddition(weightVector,numberMultiply(alphaList[i]*dataSet[i][1],dataSet[i][0]))
return weightVector,bias
dataSet = [[[3,3],1],[[4,3],1],[[1,1],-1]]
print(perceptron(dataSet,1))
# 仍是书中的例子,计算结果为 ([1, 1], -3)