神经网络小白篇

综述

刚刚开始接触深度学习,先搭框架再不断的丰富起来是我一贯的习惯。本文主要讲解神经网络的模型并拿出特例来讲解。不过真是醉了,一些教育机构出的视频真是五花八门刚开始还真信了他们的。白白浪费我的时间。

神经元模型

这里写图片描述

如上图所示就是我们常见的神经元结构。其中:‘x’代表从上一个节点传输过来的数据。‘w’是该条连接的权重值。‘b’是偏置值。’activation’是激活函数。’h’是这个神经元的输出结果。

向前传播

之前研究机器学习时我们总要遵循设计模型,设计损失函数,设计优化策略等步骤。在这里我们选用下面这个模型:

这里写图片描述

在对于上面一个神经元运行时遵循下面的公式:

f(x,w)=(i=1nwixi)+b

通过这个公式得到了该神经元的中间结果,观察结构还有一个‘activation’单元。这个单元我们称为“激活函数”,那么激活函数有什么作用呢?

其实我们设计的深度学习每一个模型都是线性的,我们知道线性的模型分类能力是有限的。所以我们把每一个部分的输出通过激励函数的映射使得增加了非线性的因素,也就是使得原来的直线或者平面发生了弯曲。这样多条线或者面就会组成很复杂的分类界面。使得神经网络的分类能力得到了很大的提升。

那么为什么加入激活函数就可以加入非线性因素呢?问题很好理解的,因为激活函数本身就是个非线性的。非线性的函数图像自然是曲线啊,这个时候要调整看问题的空间。推荐博文:https://www.zhihu.com/question/22334626

但是激活函数有很多,我们应该选择哪一个呢?之前看过一篇文章说,这也是深度学习一直让人诟病的地方。没法解释为什么选了这个激活函数性能就能得到很大的提升。

常见的激活函数有:
https://www.cnblogs.com/rgvb178/p/6055213.html

在这里使用sigmod函数,作为激活函数:

f(x)=11+ex

一个神经元的运算过程我们已经研究完成了,下面我们来看一个完整的神经网络模型:

这里写图片描述

这是三层的神经网络,第一层为输入层有三个神经元,第二层为隐藏层有两个神经元,最后一层为输出层有一个神经元。
假设现在我们使用上面的公式进行计算,一直到输出层我们会有一个输出结果。
整个的从输入层——>输出层的过程我们称为向前传播。自然而然的我们会想,机器学习中十分重要的就是优化调参。到现在为止我们还没有看到调参优化的地方啊。当然这就是我们下面要说的咯。

在说如何优化之前我们还缺一个Cost function,现在来定义一个Cost function。

C=12n||y(x)aL(x)||2

说明: y(x)为当前训练样本的标签值。a(x)为当前训练样本输出层的最后输出值。

观察函数就发现事情总是惊人的相似啊,又回到了之前接触的机器学习的优化方法啊。我们目标就是最小化这个cost function,我们之前最常用自然是梯度下降啊。但是这里有个问题,我们之前使用梯度下降都是在凸函数上进行的,并且得到的是全局最优或者近似全局最优。而现在的函数显然不是凸函数,那么还可以使用吗?

其实有偏导数自然可以用啊,但是用的时候我们获取的是个局部最优值。这里就是问题了,也就是我们初始的w和b选值就很关键了。不同的选值可能造成很大的误差。

向后传播

还有一个难点,我们的函数在求偏导数的时候可不是那么容易啊。那么有没有什么好的方法来解决这个问题呢?

下面就祭出这个大神————BP算法。

BP算法解决了梯度下降中求解偏导困难的情况。

看过不少讲解BP算法的视频和博客,真是感觉各有千秋啊。但是个人感觉既然BP算法解决的是向后传播中函数求偏导困难的问题那我们的聚焦点不应该放在为什么求偏导简单了上吗?

我们首先从一个真实的案例中说起。这是看过的最好的一篇博文了,现在贴上来:
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述

观察上面进行链式求导的公式我们发现其中是有规律的,我们总结一下就会发现下面的规律:
这里写图片描述

观察上式我们发现,我们总结出了规律。不用次次都求偏导了。只需要根据误差来做乘法就可以了。
其实这就是BP算法的核心。

算法步骤:
这里写图片描述
根据上述步骤转化成python代码如下:

# bp算法的核心部分,根据算法的步骤来
    def back_prop(self, x, y):
        nabla_b = [np.zeros(b.shape) for b in self.biases]
        nabla_w = [np.zeros(w.shape) for w in self.weights]
        # feedforward
        activation = x
        activations = [x]  # list to store all the activations, layer by layer
        zs = []  # list to store all the z vectors, layer by layer
        for b, w in zip(self.biases, self.weights):
            z = np.dot(w, activation) + b
            zs.append(z)
            activation = sigmoid(z)
            activations.append(activation)
        # backward pass
        delta = self.cost_derivative(activations[-1], y) * sigmoid_prime(zs[-1])
        nabla_b[-1] = delta
        nabla_w[-1] = np.dot(delta, activations[-2].transpose())
        #这里是向后传播,所以变量l指的是从后往前数的数,跟前面的那个刚好相反。
        for l in range(2, self.num_layers):
            z = zs[-l]
            sp = sigmoid_prime(z)
            delta = np.dot(self.weights[-l + 1].transpose(), delta) * sp
            nabla_b[-l] = delta
            nabla_w[-l] = np.dot(delta, activations[-l - 1].transpose())
        return nabla_b, nabla_w

下面给出博客的原地址:
http://blog.csdn.net/yizhen_acmer/article/details/54561554

和一篇很好的博客:
http://galaxy.agh.edu.pl/~vlsi/AI/backp_t_en/backprop.html

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值