神经网络-感知器
目录
前言
这是一篇神经网络最最最基础的博文!
讲解的是感知器和自适应性圣经元,为以后的深度学习打下基础。
本文章是阅览技术文档加以实现和理解。
原文地址:http://www.ranling.com/category/it/689240.html
感知器
感知器的最初概念来源于生物神经元类逼成带有二值输出的简单逻辑门。从生物学的角度来看,神经元相当于大脑中的神经网络的一个节点。当刺激抵达树突,输入信号就会在神经细胞体内进行聚集(因为树突有很多),当刺激超过一定的阈值的时候就会产生一个输出信号,然后继续传递下去。根据这个原理有人就提出了感知器这个概念。
Frank Rosenblatt感知器
这是以这个人的名字命名的感知器。这个感知器的思路特别简单,也是我们在书本上见到最多的。
用权重W(可以理解为每个树突的重要性不一样)向量点积特征向量x会得到一个值y,看看这个值y与阈值进行对比,如果超过阈值就说明产生了刺激。
这就是一个最简单的 二值分类器
Heaviside阶跃函数
也称为单位阶跃函数,就是一个**函数。
函数表达式为:
其中θ 是阈值
z就是上文中的x 点积 权重向量w
注意这里的权重是一个向量的,应该跟x向量拥有一样的列数。
明白了上面的概念,感知机就很简单了。画出它的函数图像。
反过头去看公式,我么可以做一下变换。
就是把θ 搬到左边来。还可以在w权重向量中,把第0个元素当作θ !
算法步骤
1、权重初始化
2、计算预测值
3、更新权重
4、更新阈值
算法模型为:
(因为公式的转换我们把阈值放进了w向量中,w0就是阈值(负的),所以模型图中的weight update 可以看作算法步骤3、4的结合)
下面就针对算法的步骤来看
权重初始化
初始化为0或者比较小的随机数。
计算预测值
z=dot(W,X) W为权重向量,X为输入向量。
z>0 ? 1 : -1;
更新权重
直接看公式
其中
η表示学习速率(0.0和1.0间的常数)
y’表示实际的标签值取值只有(-1,1)
y‘表示预测值 取值也只有(-1,1)
那么y-y` 的值域为{-2,0,2}
先看取0的时候
如果是0说明我们猜对了,那么权重应该保持不变。
取-2的时候
说明真实结果是-1,预测值为1。
我们的公式是z(i)=w(i)*x(i)。
出现这种情况只有一种原因:z(i) 就不应该超过阈值,那么我们设置的权重就太大了。我们可以变小一点。正好当前权值加上一个负数就会变小。
取2的时候
说明真实结果是1,预测值为-1。
根据上面的公式。
出现这种情况的只有一种原因:z(i)应该超过阈值,那么我们权重就太小了。正好当前权重加上一个正数2就会变大。
这种调整很明显可以正确的推向目标方向。
更新阈值
阈值也不是一次性写死的,需要学习的到。这里阈值的更新跟权重的更新几乎一模一样。直接上公式。
与权重跟新类似,阈值也会向目标方向推进!(无法理解的小伙伴一定要注意,w(0)存放的是-θ 是阈值的负数,上一节讲过的。不理解可以在纸上画一下)
代码部分
# -*- coding: utf-8 -*-
# @Time : 2017/11/17 上午10:10
# @Author : SkullFang
# @Email : aaa@qq.com
# @File : main.py
# @Software: PyCharm
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib.colors import ListedColormap
class Preceptron(object):
"""
内部变量 eta 学习率,
n_iter: 权重向量训练次数,
w_权重向量,
errors_错误队列
"""
def __init__(self,eta=0.01,n_iter=10):
"""
:param eta:学习率
:param n_iter: 权重向量
"""
self.eta=eta
self.n_iter=n_iter
pass
def fit(self,x,y):
"""
:param x:输入样本向量
:param y: 对应样本分类
:return:
"""
#初始化权重向量为0
#加一是因为还有个阈值把它设置成0
#x.shape[1]是列
self.w_=np.zeros(1+x.shape[1])
self.errors_=[]
for _ in range(self.n_iter):
errors=0
for xi,target in zip(x,y):
"""
zip会强行把两个列表变成一个元祖形式的例如
for x in zip([[1,2,3],[4,5,6]],[1,-5]):
print(x)
([1, 2, 3], 1)
([4, 5, 6], -5)
"""
#update=eta*(y-y')
update=self.eta * (target-
self.predict(xi))
#w(i)=w(i)+eta*(y-y')*x(i)
self.w_[1:]+=update*xi
#更新阈值
self.w_[0] += update
#错误次数
errors+=int(update!=0.0)
#把错误次数加到队列中
self.errors_.append(errors)
pass
pass
pass
def net_input(self,x):
"""
这个是为了输入向量和权重向量做一下点积
:param x: 输入向量
:return:
"""
return np.dot(x,self.w_[1:]+self.w_[0])
pass
def predict(self,x):
"""
算出分类结果
:param x:
:return:
"""
return np.where(self.net_input(x)>=0.0,1,-1)
pass
pass
这里有都注释,可以按照算法步骤一步一步的看。
调用代码
if __name__ == '__main__':
file = "data/irisdata.csv"
df=pd.read_csv(file,header=None)
#前10行
# print(df.head(10))
#加载0到100行第4列
y=df.loc[0:100,4].values
y=np.where(y=='Iris-setosa',-1,1)
#x要第0列和2列
x=df.loc[0:100,[0,2]].values
plt.scatter(x[:50, 0], x[:50, 1], color='red', marker='o', label='setosa')
plt.scatter(x[50:100, 0], x[50:100, 1], color='blue', marker='x', label='versicolor')
plt.legend(loc='upper left')
#作出感知器
pnn = Preceptron(eta=0.1, n_iter=10)
#训练
pnn.fit(x,y)
#画出结果
plot_decision_regions(x,y,pnn,resolution=0.02)
其中csv数据为最经典的莺尾花数据。
这是地址:
https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data
打开复制在本地创建csv数据即可。
这里使用了一个辅助画图的函数
def plot_decision_regions(x,y,classifier,resolution=0.02):
"""
用于结果展示
:param x:
:param y:
:param classifier:
:param resolution:
:return:
"""
makers=('s','x','o','v')
colors=('red','blue','lightgreen','gray','cyan')
cmap=ListedColormap(colors[:len(np.unique(y))])
x1_min,x1_max=x[:,0].min()-1,x[:,0].max()
x2_min,x2_max=x[:,1].min()-1,x[:,1].max()
print(x1_min,x1_max)
print(x2_min,x2_max)
xx1,xx2=np.meshgrid(np.arange(x1_min,x1_max,resolution),np.arange(x2_min,x2_max,resolution))
#预测结果
z=classifier.predict(np.array([xx1.ravel(), xx2.ravel()]).T)
#画分界线
z=z.reshape(xx1.shape)
plt.contourf(xx1, xx2, z, alpha=0.4, cmap=cmap)
plt.xlim(x1_min, x1_max)
plt.ylim(xx2.min(), xx2.max())
for idx, cl in enumerate(np.unique(y)):
plt.scatter(x=x[y==cl,0],y=x[y==cl,1],alpha=0.0,c=cmap(idx),marker=makers[idx],label=cl)
plt.show()
如果有哪里看不懂欢迎留言。大家一起学习一起进步。