from __future__ import print_function
from functools import reduce
class VectorOp(object):
"""
这里不用numpy,手写实现向量的基本操作
"""
@staticmethod
def element_multiply(x,y):
"""
将两个向量x和y按照元素相乘
"""
# 首先把x[x1,x2,x3...]和y[y1,y2,y3...]打包在一起
# 变成[(x1,y1),(x2,y2),(x3,y3),...]
# 然后利用map函数计算[x1*y1,x2*y2,x3*y3,...]
return list(map(lambda x_y:x_y[0]*x_y[1],zip(x,y)))
@staticmethod
def dot(x,y):
"""
计算两个向量的内积
"""
# 首先把x[x1,x2,x3...]和y[y1,y2,y3...]按元素相乘
# 变成[x1*y1,x2*y2,X3*y3]
# 然后reduce求和
return reduce(lambda a,b:a+b,VectorOp.element_multiply(x,y))
@staticmethod
def element_add(x,y):
"""
将两个向量x和y的元素相加
"""
# 首先把x[x1,x2,x3...]和y[y1,y2,y3...]打包在一起
# 变成[(x1,y1),(x2,y2),(x3,y3),....]
# 然后利用map函数计算[x1+y1,x2+y2,x3+y3,...]
return list(map(lambda x_y:x_y[0]+x_y[1],zip(x,y)))
@staticmethod
def scala_multiply(v,s):
"""
将向量v中的每个元素与标量s相乘
"""
return map(lambda x:x*s,v)
class Perceptron(object):
def __init__(self,input_num):
"""
初始化感知机,设置输入参数的个数
"""
# 权重向量初始化为0
self.weights = [0.0]*input_num
# 偏置初始化为0
self.bias = 0.0
def __str__(self):
"""
打印学习到的权重
"""
str_ = "weight \t:{}\n bias:\t {}".format(self.weights,self.bias)
return str_
def predict(self,input_vec):
"""
输入向量,输出感知机的计算结果
"""
# 计算向量 input_vector[x1,x2,x3,...]和weights[w1,w2,w3,...]的内积
# 然后加上bias
value = VectorOp.dot(input_vec,self.weights)+self.bias
if value >0:
return 1
else:
return 0
def train(self,input_vecs,labels,iteration,rate):
"""
输入训练数据:一组向量与每个向量对应的label;已经训练的轮数、学习率
"""
for i in range(iteration):
str_ = "iterating: weight: \t{} bias:\t {}".format(self.weights,self.bias)
print(str_)
self._one_iteration(input_vecs,labels,rate)
def _one_iteration(self,input_vecs,labels,rate):
"""
一次迭代,把所有的训练数据过一遍
"""
# 把输入和输出打包在一起,成为样本的列表[(input_vex,label),....]
# 而每个训练样本是(input_vec,label)
samples = zip(input_vecs,labels)
# 对每个样本,按照感知机规则更新权重
for (input_vec,label) in samples:
# 计算感知机在当前权重下的输出
output = self.predict(input_vec)
# 更新权重
self._updata_weight(input_vec,output,label,rate)
def _updata_weight(self,input_vec,output,label,rate):
"""
按照感知机的规则更新权重
"""
# 首先计算本次更新的delta
# 然后把input_vec[x1,x2,x3,..]向量中的每个值乘上delta,得到每个权重更新
# 最后再把权重更新元素加到原来的weights[w1,w2,w3,..]上
delta = label - output
self.weights = VectorOp.element_add(self.weights,VectorOp.scala_multiply(input_vec,rate*delta))
self.bias = self.bias + rate*delta
"""
基于and真值表构建训练数据
"""
# 构建训练数据
# 输入向量列表
input_vecs = [[1,1],[0,0],[1,0],[0,1]]
# 期望的输出列表,注意要与输入一一对应
labels = [1,0,0,0]
# 创建感知机
and_perception = Perceptron(2)
and_perception.train(input_vecs,labels,10,0.1)
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]))
iterating: weight: [0.0, 0.0] bias: 0.0
iterating: weight: [0.0, 0.1] bias: -0.1
iterating: weight: [0.0, 0.1] bias: -0.2
iterating: weight: [0.1, 0.1] bias: -0.2
iterating: weight: [0.1, 0.2] bias: -0.2
iterating: weight: [0.1, 0.2] bias: -0.2
iterating: weight: [0.1, 0.2] bias: -0.2
iterating: weight: [0.1, 0.2] bias: -0.2
iterating: weight: [0.1, 0.2] bias: -0.2
iterating: weight: [0.1, 0.2] bias: -0.2
weight :[0.1, 0.2]
bias: -0.2
1 and 1 = 1
0 and 0 = 0
1 and 0 = 0
0 and 1 = 0
"""
基于 or 真值表构建训练数据
"""
# 构建训练数据
# 输入向量列表
input_vecs = [[1,1],[0,0],[1,0],[0,1]]
# 期望的输出列表,注意要与输入一一对应
labels = [1,0,1,1]
# 创建感知机
and_perception = Perceptron(2)
and_perception.train(input_vecs,labels,10,0.1)
print(and_perception)
# 测试
print('1 or 1 = %d' % and_perception.predict([1, 1]))
print('0 or 0 = %d' % and_perception.predict([0, 0]))
print('1 or 0 = %d' % and_perception.predict([1, 0]))
print('0 or 1 = %d' % and_perception.predict([0, 1]))
iterating: weight: [0.0, 0.0] bias: 0.0
iterating: weight: [0.1, 0.1] bias: 0.0
iterating: weight: [0.1, 0.1] bias: 0.0
iterating: weight: [0.1, 0.1] bias: 0.0
iterating: weight: [0.1, 0.1] bias: 0.0
iterating: weight: [0.1, 0.1] bias: 0.0
iterating: weight: [0.1, 0.1] bias: 0.0
iterating: weight: [0.1, 0.1] bias: 0.0
iterating: weight: [0.1, 0.1] bias: 0.0
iterating: weight: [0.1, 0.1] bias: 0.0
weight :[0.1, 0.1]
bias: 0.0
1 or 1 = 1
0 or 0 = 0
1 or 0 = 1
0 or 1 = 1
"""
感知机解决不了的异或问题,找不到超平面
"""
# 构建训练数据
# 输入向量列表
input_vecs = [[1,1],[0,0],[1,0],[0,1]]
# 期望的输出列表,注意要与输入一一对应
labels = [0,0,1,1]
# 创建感知机
and_perception = Perceptron(2)
and_perception.train(input_vecs,labels,10,0.1)
print(and_perception)
# 测试
print('1 -- 1 = %d' % and_perception.predict([1, 1]))
print('0 -- 0 = %d' % and_perception.predict([0, 0]))
print('1 -- 0 = %d' % and_perception.predict([1, 0]))
print('0 -- 1 = %d' % and_perception.predict([0, 1]))
iterating: weight: [0.0, 0.0] bias: 0.0
iterating: weight: [0.1, 0.0] bias: 0.1
iterating: weight: [0.1, 0.0] bias: 0.2
iterating: weight: [0.1, 0.0] bias: 0.2
iterating: weight: [0.1, 0.0] bias: 0.2
iterating: weight: [0.1, 0.0] bias: 0.2
iterating: weight: [0.1, 0.0] bias: 0.2
iterating: weight: [0.1, 0.0] bias: 0.2
iterating: weight: [0.1, 0.0] bias: 0.2
iterating: weight: [0.1, 0.0] bias: 0.2
weight :[0.1, 0.0]
bias: 0.2
1 -- 1 = 1
0 -- 0 = 1
1 -- 0 = 1
0 -- 1 = 1
图片.png
网友评论