机器学习(神经网络)

一、感知机(单个神经元)

感知机是基本的处理元素。它具有输入(其输入可以来自外部输入,也可以来自其他感知机)。与每个输入xi 相关联的

是一个链接权重(突触权重)wi,而输出y在最简单的情况下是这些输入的加权和(也可以是其他类型)

如上图所示就是一个简单的感知机。接收n个带权重的信号,将总输入值与阀值θ进行比较,通过激活函数f(*)产生输出;

二、激活函数

传统的激活函数是将输入值映射到0到1上的输出,如阶跃函数、Sigmoid函数、tanh函数、ReLU函数:

阶跃函数 sgn(x)

图像不连续且不光滑,sgn(x)=1,x≥0 反之为0

Sigmoid函数 sigmoid(x)

图像光滑平坦,但在x趋于∞时导数为0;

sigmoid(x)= 1 / ( 1+e^(-x) )

tanh函数 tanh(x)

值域在-1到1之间,图像连续可导。

tanh(x)= [ e^x - e^(-x) ] / [ e^x + e^(-x) ]

ReLU函数 ReLU(x)

在小于0的部分导数值为0,在大于0的部分导数值为常数k;

ReLU(x) = max( 0,kx )

单层感知机网络(包含输入层和输出层) 

只包含输入和输出两层,用于解决线性可分问题。

训练过程基本思想:(正向传播,反向更新)

1)正向计算模型预测值a; 2)比较预测值a与真实值之间的差异(作差); 3)利用差值求解(更新)参数;

实战—利用单层感知机实现(与  或  非问题)

import numpy as np            #导入numpy数据包
from matplotlib import pyplot as plt    #导pyplot
datasetX= np.array(
    [[0,0,1],[0,1,1],[1,0,1],[1,1,1]]
)                             #数据集X:前两列为x1和x2,最后一列为b
datasetY=np.array([0,1,1,1])    #数据集Y
np.random.seed(1)
w=np.random.random((1,3))        #系数(参数)

def sigmoid(x):
    return 1/(1+np.exp(-x))    #sigmoid函数

rate = 0.02                    #学习率
step = 1000                    #学习步长
for i in range(step):
    sum=np.dot(w,datasetX.T)
    error=sigmoid(sum)-datasetY
    w=w-rate*np.dot(error,datasetX)

#绘制图像
X=np.array([-0.2,0.55])
print(w)
plt.scatter(0,0,c='blue')        #以或问题为例子
plt.scatter([0,1,1],[1,0,1],c='r')
plt.plot(X,-(w[0][0]*X+w[0][2])/w[0][1],c='black')
plt.show()

运行结果:

    或问题训练图像;(源码以或问题为例)

    与问题训练图像 (改数据集和绘制区间即可);

    非问题训练图像,结合三幅图像与实际分类大体一致。

异或不同为1相同为0,可以结合或问题和与问题进行求解;

下面我们推到为什么可以通过此种方式求解参数:(结合下图的变化过程)

X为列向量(x1,x2,....,xn-1,1)^T ,Y为输出结果这里为单神经元故Y为常数(0,1),W为(1 X n)的矩阵;

Z=WX,A = f (Z) (这里的 f就为激活函数),这里定义误差函数为 L( A,y )= - ylnA - (1-y)ln( 1-A );(越小越好)

要结合梯度下降算法我们需要求解 △w并根据 w=w-α△w实现对w的更新。已知误差函数L我们可以求得其对A的偏导数

为 - ( y/A )+( 1-y )/( 1 - A )【化简整理的 ( A - y ) / ( 1 - A )A】,结合链式法则我们可以求得 △w=(A-y)*x

所以得出:wi = wi - α( A - y )xi;(注:这里的α为学习率,通常取值为0.01,0.02,0.03等)

结合或问题的实例,X为(3,4)矩阵,y为(1,4)矩阵,W为(1,3)矩阵(其导数与其维数相同)

W=W - α(A - y)X,这里的X为X的转置(4,3)矩阵。

显然只用一个神经元构造的网络职能解决线性问题,对于非线性问题单层模型无法解决。

三、多层前馈神经网络

多层前馈神经网络,也称为多层感知机,包含输入层(input layer)、隐含层(hidden layer)、输出层(output layer)

位于隐含层和输出层的神经元具有激活函数,通常输入层仅接受输入数据不具备处理功能。

多层神经网络可以解决“非线性”问题,相比单个神经元处理特征数据效果更好。

给定样本数据集D={(x1,y1),(x2,y2),....,(xn,yn)},其中 xi 属于 d 维空间,yi 属于 l 维空间;

如上图所示的两层神经网络有d个输入,hidden层有q个结点,产生l个输出,由输入层到hidden层要确定的参数

个数为 q x d个,由hidden层到输出层要确定的参数个数为 l x q个,故总共要求解的参数个数为 (d + l)q个。

误差反向传播算法(BP算法):类似于梯度下降算法,是一种迭代算法,每一次迭代实现对模型参数的更新。

在这里我们将样本的误差(error)定义为:

两层神经网络中出现的符号及含义
X输入特征值(输入集合) xi 表示输入层第i个结点对应的输入
Y输出值,yi表示输出层第i个结点对应的输出
V

由输入层到隐层(hidden layer)的参数矩阵

v【ih】表示输入层 i 结点到隐层 h 结点之间的连接权

W

由隐层(hidden layer)到输出层的参数矩阵

W【hj】表示隐层 h 结点到输出层 j 结点之间的连接权

这里的 i 属于【1,d】 h 属于【1,q】 j 属于【1,l】,不大于对应层

的结点个数且取值都为正整数

所谓的误差反向传播,就是从输出层开始回退,逐层实现每一层之间的连接权值的更新,更新推导如下:

更新W中对应的参数w【hj】同感知机相同,只需求出△w【hj】即可,结合误差函数

我们可以得到,下一步只需求解△Ek/△w【hj】,结合链式求导法则:

结合Sigmoid函数导数f(x)(1-f(x)),即上式子的中间部分可通过此替换,第三部分为b【h】可得gj梯度项:

 由此我们可以完成W参数矩阵的更新,下面继续反向传播,以类似的方法更新V参数矩阵。

我们只需求解eh即可,这里的 xi 为上一层的输入数据(学习率*梯度项*上一层输入

误差反向传播算法(BP算法)伪代码:

BP神经网络的优点与缺点:

优点:实现了一个从输入到输出的映射功能,可实现任何复杂非线性映射,网络能通过学习大量的正确实例

来逐步增强和完善自己。缺点:收敛速度较慢,所得到的结果未必是全局最优解;

实战:BP神经网络实现与或非问题:

import numpy as np#导入数据包
from matplotlib import pyplot as plt
from sklearn import datasets

def sigmoid(x):#sigmoid函数
    return 1.0/(1 + np.exp(-x))
def dsigmoid(Z):#sigmoid函数的导数
    return Z*(1-Z)

dataX=np.array([[0,0],[0,1],[1,0],[1,1]])
dataY=np.array([0,1,1,1]).reshape(4,1)#数据集X
learnrate=1                                    #学习率
studystep=2500                                   #最大迭代次数

#初始化网络结构
inputlayer_size=dataX.shape[1]                  #输入层结点个数
hiddenlayer_size=inputlayer_size+1              #隐含层结点个数
outputlayer_size=dataY.shape[1]                 #输出层结点个数

np.random.seed(1)#在0到1之间初始化各矩阵的连接权
V=np.random.random((hiddenlayer_size,inputlayer_size))    #V矩阵的随机初始化
W=np.random.random((outputlayer_size,hiddenlayer_size))  #W矩阵的随机初始化

#2-神经网络层次模型&训练
for i in range(studystep):
    #正常传递求解模型估计参数
    hiddenvalue=sigmoid(np.dot(V,dataX.T))                 #隐藏层输出值
    outputvalue=sigmoid(np.dot(W,hiddenvalue))             #模型预测值
    g=dsigmoid(outputvalue)*(outputvalue-dataY.T)
    e=dsigmoid(hiddenvalue)*(1-hiddenvalue)*np.dot(W.T,g)  #求解梯度
    W=W-learnrate*np.dot(g,hiddenvalue.T)                  #反向传递,最后更新
    V=V-learnrate*np.dot(e,dataX)                          #更新参数W和V

#模型结果预测
predict=sigmoid(np.dot(W,sigmoid(np.dot(V,dataX.T))))
print(predict.T)

这里以或问题为例,运行结果如下图所示:(对于与、非以及异或问题只需修改对应的数据集即可)

总体来说效果还是可以的,当然这仅仅是实现了一个简单神经网路,还有许多后序问题需要解决

比如在何处取得全局最优解,如何提高模型的速率,以及梯度消失(爆炸)的解决等;

针对全局最优解的求解现有的方法有:随机梯度下降、模拟退火、遗传以及蚁群算法等;

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值