机器学习笔记——第2篇

来源:互联网 发布:开票软件怎么用 编辑:程序博客网 时间:2024/05/29 04:07

文章作者是我的一位大神学长陈雨学长~,征得学长同意后将文章转载到了我的blog上,特在此感谢学长~

代码在学长的github上:
https://github.com/unnamed2/MDL
欢迎猛击

  • 自己实现的机器学习2
    • 0 神经元
        • 00 模型
        • 01 activation激活函数
    • 1 更为复杂的模型
    • 2反向传播

自己实现的机器学习(2):

2.0 神经元

2.0.0 模型

历史上的某个伟人曾经用计算机里的神经元模拟大脑 试图构建高智能的AI: 虽然人脑中几十亿的神经元数量压倒性的战胜了当时计算机计算速度,但是这个方法被改进演化之后依旧广泛流传:神经元

他完成了这样的计算:其中W,B是矩阵

Output=activation(W˙x+B)

2.0.1 activation:激活函数

  • Sigmoid : Sigmoid(x)=11+ex 从无穷到概率的映射: Sigmoid
  • ReLU :ReLU(x)=max(0,x)Rectified linear unit 快速稳定的导数
  • Tanh:无穷到1 的映射: Tanh函数

激活函数可以视为对神经网络本身的输出值是一个进一步的处理,即特征的保留和删除,根据不同的模型,选择不同的激活函数,可以训练得到更好的模型.

线性代数的计算不会改变其线性的特点,比如对于在二维平面上某区间上随机数X来说 如果X服从均匀分布,那么无论X经过怎么样的线性变换,最终仍然会在某区间上服从均匀分布.

激活函数很大 的一个作用就是加入非线性因素来解决线性运算解决不了的问题.

2.1 更为复杂的模型

使用一个即兴的伪代码来说明一下上次的多项式模型:

featrue = InputVar({1,1});//多项式输入一个xlabel = InputVar({1,1});//同时输出一个值A = Parameter({3,1});//要被训练的参数Z = Polynomial(input,A);//计算多项式的值Err = SquareError(Z1 - label);//训练使用平方误差函数 

对应C++代码也很简单

现在 我们将要建立一个更复杂的模型来做一些更复杂的事情.

例如这样的一个网络模型:

三层神经网络

用这个网络分析一个28x28的图片:

input = InputVar({784,1});//输入是784 x 1的矩阵 或者叫向量,这个矩阵是输入的数据label = InputVar({10,1});//这个是标签数据 如果图片写的是5这个数字那么label[5] = 1.0f;                         //其他为0.0f;其余数字同理W0 = Parameter({30,784});//W0是一个30 x 784的矩阵 ,这个矩阵是将要学习的parameters之一B0 = Parameter({30,1});  //B0,W1,B1同上W1 = Parameter({10,15});B1 = Parameter({10,1});Z0 = Sigmoid(W0 * input + B0);//隐含层输出 * 是矩阵乘法Z1 = Sigmoid(W1 * Z0 + B1);//输出层输出 , Z1是我们的函数输出的结果Err = SquareError(Z1 , label);//平方误差函数 //......

一点一点的来看这个函数:

对于整个的hidden layer里的每个神经元的输出Zi:(假设hidden layer有M个神经元,input layer有N个神经元,它们的输出是input0inputN1)

Zj=Sigmoid(i=0N1inputi˙wji+bj)

这里wjiinput layer第i个神经元到hidden layer第j个神经元的输出.

写成向量式:

Z0=Sigmoid(W0˙input+B0);

这里W是输入层到隐含层的权重矩阵,b是hidden layer的偏置向量,Z是隐含层输出,同理 output layer的输出W1:
Z1=Sigmoid(W1˙Z0+B1)

2.2反向传播

对于这种复杂的模型 误差函数对每个parameter的偏导数并不是很容易求得 但是一点一点看每一个函数的偏导数:

Z0 = Sigmoid(W0 * input + B0);

这里令

aj=i=0N1inputi˙wji+bj

Z0j=Sigmoid(aj)

所以有:

dZ0jdaj=Sigmoid(aj)

ajwji=inputi;ajbj=1

Z0jwji=dZ0jdaj˙ajwji=Sigmoid(aj)˙inputi

把这个写成容易看的简洁的矩阵乘法就是

Z0W0=Sigmoid(a)inputTi;

我们根据链式法则推导出来Z0W0,B0的每个参数偏导数的计算方法.这种链式法则同样适用于各个部分,我们从下道上的一个函数一个函数的求他们对输入的偏导数:

ErrZ1=err=Z1labels

Z1W1=Sigmoid(a)(Z0)T;Z1Z0=Sigmoid(a)(W1)T;Z1B1=1;

Z0W0=Sigmoid(a)inputTi;Z0B0=1;

正因为求取偏导数的过程 是从结果(err)出发一点点的向前(先是Z1,再Z0)传播,和计算err的顺序正好相反,所以才叫反向传播.

利用反向传播,我们现在能够求出来Err对每一个参数的偏导数值,这样就可以使用梯度下降去更新参数了.

0 0
原创粉丝点击