代码地址
本代码是基于以上链接修改的,不是原创实现。
这个原本是python2的代码本人改成了python3实现
- 首先 创建一个感知机对象初始化的属性有:激活函数 权重 偏置
- 魔法方法(str)可以在打印对象是直接打印出来想要展示的数据
- 前向传播实现(传入x与w相乘+偏置b)
- 多次训练实现(通过调用单次训练)
- 一次训练的实现方法(调用前向传播和更新权重方法)
- 更新权重的方法(通过w= w+rate*(y-label)x,b=b+rate*(y-label)
- 激活函数 和生成数据
- 训练的实现方法
from functools import reduce
class Perceptron(object):
# 初始化 输入参数个数 激活函数 w 和b
def __init__(self, input_num, activator):
"""
初始化感知器,设置输入参数的个数和激活函数
:param input_num:
:param activator:
"""
self.activator = activator
self.weights = [0.0 for _ in range(input_num)]
# self.weights = [0.0,0.0]
# 偏置
self.bias = 0.0
# 打印出 实例中的想要输出的数据
def __str__(self):
"""
打印学习到的权重,和偏执项
:return:
"""
return 'weights\t:%s\nbias\t:%f\n' % (self.weights, self.bias)
def predict(self, input_vec):
'''
输入向量,输出感知器的计算结果
'''
return self.activator(
reduce(lambda a, b: a + b,
list(map(lambda x_w: x_w[0] * x_w[1],
zip(input_vec, self.weights)))
, 0.0) + self.bias)
def train(self, input_vecs, labels, iteration, rate):
'''
输入训练数据:一组向量、与每个向量对应的label;以及训练轮数、学习率
'''
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, label)
samples = zip(input_vecs, labels)
# 对每个样本,按照感知器规则更新权重
for (input_vec, label) in samples:
# 计算感知器在当前权重下的输出
output = self.predict(input_vec)
# 更新权重
self._update_weights(input_vec, output, label, 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 x_w: x_w[1] + rate * delta * x_w[0],
zip(input_vec,self.weights)))
# 更新bias
self.bias += rate * delta
# print(self.weights,self.bias)
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_perceptron():
'''
使用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感知器
and_perception = train_and_perceptron()
# 打印训练获得的权重
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]))