python学习
本章为这个博客的代码学习
感知器
map用法:
map(function, iterable, ...)
- 参数:
function -- 函数
iterable -- 一个或多个序列
- 返回值
Python 2.x 返回列表。
Python 3.x 返回迭代器。
(所以用py3编写,map前要加list)
代码如下:
#coding=utf-8
from functools import reduce # for py3
class Perceptron(object):
def __init__(self, input_num, activator):
'''
初始化感知器,设置输入参数的个数,以及激活函数。
激活函数的类型为double -> double
'''
self.activator = activator
# 权重向量初始化为0
self.weights = [0.0 for _ in range(input_num)]
# 偏置项初始化为0
self.bias = 0.0
def __str__(self):
'''
打印学习到的权重、偏置项
'''
return 'weights\t:%s\nbias\t:%f\n' % (self.weights, 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求和
#list1 = list(self.weights)
#print ("predict self.weights:", list1)
return self.activator(
reduce(lambda a, b: a + b,
list(map(lambda x: x[0] * x[1], # HateMath修改
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: x[1] + rate * delta * x[0], zip(input_vec, self.weights)) ) # HateMath修改
# 更新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_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]))
线性单元和梯度下降
线性单元和感知器,两者的模型和训练规则是一样的(在上表中,线性单元的优化算法是SGD算法)。那么,我们只需要把感知器的激活函数进行替换即可。引用感知器的代码即可!
from perceptron import Perceptron
#定义激活函数
f=lambda x:x
class LinearUnit(Perceptron):
def __init__(self,input_num):
'''
初始化线性回归单元,设置输入参数的个数
'''
Perceptron.__init__(self,input_num,f)
def get_training_dataset():
'''
捏造5个人的收入数据
'''
#构建训练数据
#输入向量列表,每一项是工作年限
input_vecs=[[5],[3],[8],[1.4],[10.1]]
#期望的输出列表,月薪,与工作年限一一对应
labels=[5500,2300,7600,1800,11400]
return input_vecs,labels
def train_linear_unit():
'''
使用数据训练线性单元
'''
#创建感知器,输入参数的特征数为1(工作年限)
lu=LinearUnit(1)
input_vecs,labels=get_training_dataset()
lu.train(input_vecs,labels,10,0.01)
return lu
if __name__=='__main__':
'''
训练线性单元
'''
linear_unit=train_linear_unit()
#打印训练获得的权重
print(linear_unit)
#测试
print ('Work 3.4 years, monthly salary = %.2f' % linear_unit.predict([3.4]))
print ('Work 15 years, monthly salary = %.2f' % linear_unit.predict([15]))
print ('Work 1.5 years, monthly salary = %.2f' % linear_unit.predict([1.5]))
print ('Work 6.3 years, monthly salary = %.2f' % linear_unit.predict([6.3]))
完