代码参考了零基础入门深度学习(1) - 感知器这篇文章,我只对代码里可能存在的一些小错误进行了更改。至于感知机的原理以及代码里不清楚的地方可以结合该文章理解。
from functools import reduce
class Perceptron:
def __init__(self,input_num,activator):
'''
param input_num: 初始化感知机,设置输入参数的个数
param activator: 初始化感知机,设置激活函数
'''
self.activator = activator
# 权重向量初始化为0
self.weights = [0.0 for i in range(input_num)]
# 偏置项初始化为0
self.bias = 0.0
def __str__(self):
'''
打印学习到的权重,偏置项
'''
return 'weights\t:{}\nbias\t:{}\n'.format(str(self.weights),str(self.bias))
def predict(self,input_vec):
'''
输入向量,输出感知机的计算结果
'''
# 把input_vec[x1,x2,x3...]和weights[w1,w2,w3,...]打包在一起
# 变成[(x1,w1),(x2,w2),(x3,w3),...]
# 然后利用map函数计算[x1*w1,x2*w2,x3*w3,...]
# 最后利用reduce求和
zipped = zip(input_vec,self.weights)
map_result = map(lambda ele:ele[0]*ele[1],list(zipped))
sum_result = reduce(lambda a,b:a+b,map_result,0.0)
return self.activator(sum_result+self.bias)
def train(self,input_vecs,labels,iteration,rate):
'''
:param input_vec: 一组向量
:param labels: 与每个向量对应的label
:param iteration: 训练轮数
:param rate: 学习率
:return:
'''
for i in range(iteration):
self._one_iteration(input_vecs,labels,rate)
def _one_iteration(self, input_vecs, labels, rate):
'''
一次迭代,把所有的训练数据过一遍
'''
# 把输入和输出打包在一起,成为样本的列表[(input_vec,label),...]
# 而每个训练样本是(input_vec,labels)
samples = zip(input_vecs,labels)
# 对每个样本,按照感知机规则更新权重
for ele in list(samples):
# 计算感知机在当前权重下的输出
output = self.predict(ele[0])
# 更新权重
self._update_weights(ele[0],output,ele[1],rate)
def _update_weights(self, input_vec, output, label, rate):
'''
按照感知机规则更新权重
随机梯度下降法。
'''
# 把input_vec[x1,x2,x3,...]和weights[w1,w2,w3,...]打包在一起
# 变成[(x1,w1),(x2,w2),(x3,w3),...]
# 然后利用感知机规则更新权重
delta = label - output
self.weights = list(map(lambda ele:ele[1]+rate*delta*ele[0],zip(input_vec,self.weights)))
# 更新bias
self.bias += rate*delta
def f(x):
'''
定义激活函数f
'''
return 1 if x > 0 else 0
def get_training_dataset():
'''
基于and真值表构建训练数据
'''
# 构建训练数据
# 输入向量列表
input_vecs = [[1,1],[0,0],[1,0],[0,1]]
# 期望的输出列表,注意要与输入一一对应
# [1,1] -> 1, [0,0] -> 0, [1,0] -> 0, [0,1] -> 0
labels = [1,0,0,0]
return input_vecs,labels
def train_and_perception():
'''
使用and真值表训练感知机
'''
# 创建感知机,输入参数个数为2(因为and是二元函数),激活函数为f
p = Perceptron(2,f)
# 训练,迭代10轮,学习速率为0.1
input_vecs,labels= get_training_dataset()
p.train(input_vecs,labels,10,0.1)
# 返回训练好的感知机
return p
'''
if __name__ == '__main__':
# 训练感知机
and_perception = train_and_perception()
# 打印训练获得的权重
print(and_perception)
# 测试
print('1 and 1 = %d' %and_perception.predict([1,1]))
print('0 and 0 = %d' %and_perception.predict([0,0]))
print('1 and 0 = %d' %and_perception.predict([1,0]))
print('0 and 1 = %d' %and_perception.predict([0,1]))
'''