基于python的感知机学习算法实现

感知机的学习算法分为原始形式和对偶形式。

具体模型理论:统计学习——感知机
本文将书中的两个算法过程,利用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)

猜你喜欢

转载自blog.csdn.net/ggdhs/article/details/92803970