from __future__ import print_function
from functools import reduce
class VectorOp(object):
def dot(x, y):
"""
计算两个向量x和y的内积
"""
return reduce(lambda a, b: a + b, VectorOp.element_multiply(x, y), 0.0)
@staticmethod
def element_multiply(x, y):
"""
将两个向量x和y按元素相乘
"""
return list(map(lambda x_y: x_y[0] * x_y[1], zip(x, y)))
@staticmethod
def element_add(x, y):
"""
将两个向量x和y按元素相加
"""
return list(map(lambda x_y: x_y[0] + x_y[1], zip(x, y)))
def scala_multiply(v, s):
"""
将向量v中的每个元素和标量s相乘
"""
return map(lambda e: e * s, v)
class Perceptron(object):
def __init__(self, input_num, activator):
"""
初始化感知器,设置输入参数的个数,以及激活函数。
激活函数的类型为double -> double
"""
self.activator = activator
self.weights = [0.0] * input_num
self.bias = 0.0
def __str__(self):
"""
打印学习到的权重、偏置项
"""
return 'weights\t:%s\nbias\t:%f\n' % (self.weights, self.bias)
def predict(self, input_vec):
"""
输入向量,输出感知器的计算结果
"""
return self.activator(
VectorOp.dot(input_vec, self.weights) + 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):
"""
一次迭代,把所有的训练数据过一遍
"""
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):
"""
按照感知器规则更新权重
"""
delta = label - output
self.weights = VectorOp.element_add(
self.weights, VectorOp.scala_multiply(input_vec, rate * delta))
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]]
labels = [1, 0, 0, 0]
return input_vecs, labels
def train_and_perceptron():
"""
使用and真值表训练感知器
"""
p = Perceptron(2, f)
input_vecs, labels = get_training_dataset()
p.train(input_vecs, labels, 10, 0.1)
return p
if __name__ == '__main__':
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]))
weights :[0.1, 0.2]
bias :-0.200000
1 and 1 = 1
0 and 0 = 0
1 and 0 = 0
0 and 1 = 0