!感知机的理论,应用,博客,书籍多的是。 看机器学习算法的时候总是觉得感知机简单,大致粗过一遍就了事。对,我是来交后悔费的!哈。
!感知机是支持向量机和神经网络的基础。嗯~~,
!前提知识,如果童靴对 python 中的 reduce(),map(),copy() 不是特别了解的话,建议大家先去看一下这些知识。因为下面的感知机算法会用到。
!感知机学习算法是误分类驱动,二分类的线性分类的判别模型~,他的学习算法有两种形式,~ 原始形式,对偶形式~
原始形式的感知机学习算法模型搭建
代码奉上~
"""
作者:jsionz
创作时间: 2019/12/14
联系邮箱:jsionz@163.com
希望跟大家一块探讨~~
"""
# 感知机学习算法 《统计学习方法》 李航
from functools import reduce
import copy
class Perceptron:
def __init__(self,train_set_x,train_set_y,rate):
"""
感知机初始化
:param train_set_x: 训练集 features [[features1(list)],[features2(list)],....]
:param train_set_y: 训练集 label list --->[label1,label2,label3,....]
:param rate: 学习率
"""
self.weights = [0.0 for _ in range(len(train_set_x[0]))]
self.bias = 0.0
self.train_x = copy.copy(train_set_x)
self.train_y = copy.copy(train_set_y)
self.rate = copy.copy(rate)
def model_predict(self,input_vector):
"""
感知器输出预测结果, y = sign(w*x + b) sign >= 0 ---> 1 ; < 0 ---> -1 激活函数 1 if x>=0 -1
"""
return 1 if ((reduce(lambda a,b:a+b,map(lambda w,x: w * x,self.weights,input_vector))) + self.bias) >=0 else -1
def model_train(self):
"""
模型训练过程
"""
# 第一次计算
miss_example_index = []
for i in range(len(self.train_x)):
value = (self.train_y[i]) * (reduce(lambda c,d:c + d ,list(map(lambda a,b:a * b,self.weights,self.train_x[i] ))) + self.bias)
if value <= 0:
miss_example_index.append(i)
door = True
while door:
if miss_example_index:
index = miss_example_index[0]
# w , b 系数更新
PD_rate = [self.rate * x_feature * self.train_y[index] for x_feature in self.train_x[index]]
self.weights = list(map(lambda a,b:a + b,self.weights,PD_rate))
self.bias = self.bias + (self.rate * self.train_y[index])
while miss_example_index:
miss_example_index.pop()
# 重新计算 误分类点
for i in range(len(self.train_x)):
value = (self.train_y[i]) * (reduce(lambda c, d: c + d, list(
map(lambda a, b:
a * b, self.weights, self.train_x[i]))) + self.bias)
if value <= 0:
miss_example_index.append(i)
else:
door = False
if __name__ == "__main__":
test_ex = Perceptron([[3,3],[4,3],[1,1]],[1,1,-1],1)
test_ex.model_train()
print(test_ex.model_predict([3,3]))
print(test_ex.weights)
对偶形式的感知机学习算法模型搭建:
!在原始形式的感知机学习算法中,可以看到 权重值w和偏置项b的更新依赖于 训练数据。若我们在训练的开始,权重和偏置项初始化时,都为零~,那么,w,b的最终结果也只跟训练集有关~(见李航统计学习方法)
对偶形式就是把在某一刻的误分类点进行的权重跟新累加起来。就是这样~。arfa这个东西是可以看作计数器,只不是乘以了一个学习率。
# 感知机学习算法 《统计学习方法》 李航
from functools import reduce
import copy
class Perceptron:
def __init__(self,train_set_x,train_set_y,rate):
"""
感知机初始化
:param train_set_x: 训练集 features [[features1(list)],[features2(list)],....]
:param train_set_y: 训练集 label list --->[label1,label2,label3,....]
:param rate: 学习率
"""
self.weights = [0.0 for _ in range(len(train_set_x[0]))]
self.bias = 0.0
self.train_x = copy.copy(train_set_x)
self.train_y = copy.copy(train_set_y)
self.rate = copy.copy(rate)
self.arfa = [0.0 for _ in range(len(train_set_x))] # 对偶形式 需要用到的 阿尔法 的保存
def gram_matrix(self):
"""
感知机对偶形式训练数据用到的Gram矩阵
:return:
"""
gram_matrix = []
for i in range(len(self.train_x)):
current_list = []
for j in range(len(self.train_x)):
current_list.append(reduce(lambda c,d:c + d,list(map(lambda a,b: a * b,self.train_x[i],self.train_x[j]))))
gram_matrix.append(current_list)
return gram_matrix
def model_train_dualForm(self):
"""
感知机对偶形式的训练
:return:
"""
gram_matrix_list = self.gram_matrix()
miss_example_index = []
for i in range(len(self.train_x)):
value = self.train_y[i] * reduce(lambda e,f:e + f ,list(map(lambda c,d:c * d,list(map(lambda a,b:a *b,
self.arfa,self.train_y)),gram_matrix_list[i])))
if value <= 0:
miss_example_index.append(i)
door = True
while door:
if miss_example_index:
index = miss_example_index[0]
# arfa , b 系数更新
self.arfa[index] = self.arfa[index] + self.rate
self.bias = self.bias + (self.rate * self.train_y[index])
while miss_example_index:
miss_example_index.pop()
# 重新计算 误分类点
for i in range(len(self.train_x)):
value = self.train_y[i] * reduce(lambda e, f: e + f,list(map(lambda c, d: c * d,
list(map(lambda a, b: a * b,self.arfa, self.train_y)),gram_matrix_list[i])))
if value <= 0:
miss_example_index.append(i)
print(self.arfa)
print(self.bias)
else:
door = False
def model_dualForm_predict(self, input_vec):
"""
对偶形式感知机模型的预测
:param input_vec:
:return:
"""
new_list = []
value_arfXY_list = list(map(lambda a, b: a * b, self.arfa, self.train_y)) # arda * y_i
# arfa * y_i (n X 1) * train_x(n * 未知列) 见公式
for i in range(len(self.train_x)):
proed_list = [value * value_arfXY_list[i] for value in self.train_x[i]]
new_list.append(proed_list)
final_list = [0.0 for _ in range(len(new_list[0]))]
while new_list:
final_list = list(map(lambda a, b: a + b, final_list, new_list.pop()))
return reduce(lambda c, d: c + d, list(map(lambda a, b: a * b, input_vec, final_list)))
终于完结了~!,对偶性时的代码有点问题,但是整体思路,以及代码逻辑是没有问题的~,最近忙着要开题~我还有功夫搞这个~~哈。搞开题去咯,欢迎指正错误之处~ 如果代码或者想法对您有帮助~那就谢谢打赏丫