今天把感知机的算法用Python实现了一下。
主要依据的算法流程是《统计学习方法》中关于感知机的算法过程,具体如下。
# -*- coding: utf-8 -*-
"""
Created on Sat Oct 13 11:09:02 2018
@author: Administrator
"""
import numpy as np
class MLP:
def generate_data(self, m, n):
'''
随机生成训练数据,测试数据也可同样方法生成
m:样本的个数
n:每个样本具有的特征维数
y: ±1
'''
x = np.random.random((m,n))
#x2 = np.random.random((m,n))
y1 = np.ones(m)
#y2 = np.ones(m)*(-1)
start = int(m / 2)
y1 [start:] = y1[start:] * (-1)
return x, y1
def judge_func(self, x, y, w, b):
'''
来判断是否对参数进行更新的函数
x: xi
y: yi
w: wi
b: bi
'''
value = y * (np.dot(w, x) + b)
#print(value)
return value
def mlp_train(self, x, y, w, b, yita):
'''
感知机
x: 输入数据矩阵
y:输入标签矩阵
'''
error_sample = []
error_label = []
for i in range(len(x)):
if self.judge_func(x[i], y[i], w, b) <= 0:
w = w + yita * y[i] *x[i]
b = b + yita * y[i]
error_sample.append(x[i])
error_label.append(y[i])
if len(error_sample) > 0:
self.mlp_train(error_sample,error_label, w, b, yita)
return w, b
def test(self, x_test, w, b):
y_pre = []
for i in range(len(x_test)):
value = np.dot(w, x_test[i].T) + b
y_temp = np.sign(value)
y_pre.append(y_temp)
return y_pre
def cal_accuracy(self, y_pre, y_test):
num = 0
for i in range(len(y_pre)):
if y_pre[i] == y_test[i]:
num += 1
accuracy = num / len(y_test)
return accuracy
if __name__ == '__main__':
m, n = 1000, 3 #输入生成样本的数量和维度
train = MLP()
x_train, y_train = train.generate_data(m, n)
#m, n = np.shape(x)
#print(y_train.shape)
#print((np.transpose(x_train[1])).shape)
w = np.zeros((1, n))
b = 0
yita = 0.1
w, b = train.mlp_train(x_train, y_train,w,b,yita)
x_test, y_test = train.generate_data(m, n)
y_pre = train.test(x_test, w, b)
print('感知机的准确率为: ', train.cal_accuracy(y_pre, y_test))
在实现的过程中其实有很长的时间在纠结关于参数w和b的维数的问题,因为不太清楚怎么确定。
后来想明白了,w的维数应该和每一个样本的维度是一样的,这样才能保证样本的在每一个特征上都有一个权重参数,而最终的目标也是对这些权重参数拟合,其实有点像多项式的系数。