神经网络正向传播及反向传播原理分析——神经网络之softmax(5)

14 篇文章 3 订阅
12 篇文章 0 订阅

转载https://forecast.blog.csdn.net/article/details/96465982?spm=1001.2014.3001.5502

通过对本系列的学习,你可以全面的了解softmax的来龙去脉。如果你尚不了解神经网络,通过本系列的学习,你也可以学到神经网络反向传播的基本原理。学完本系列,基本神经网络原理就算式入门了,毕竟神经网络基本的网络类型就那几种,很多变种,有一通百通的特点。

网上对softmax或是神经网络反向传播知识的整理,基本都通过一个长篇大论堆积出来,一套下来面面俱到但又都不精细。本文将每个环节拆开,分别进行详细介绍,即清晰易懂,又减轻了阅读负担,增加可读性。本文也借鉴了其他作者的内容,并列举引用,希望大家在学习过程中能有所收获

本章内容提要:

通过前四篇文章的学习,此时我们的知识体系里有了神经网络,分类函数,损失函数这三个重要模块。

掌握了数据从:输入→输出→预测分类→评估预测结果与真实结果差异;的原理以及推导过程。本文接着探讨在通过损失函数得到预测结果的误差后,下一步我们要怎么做,以及为什么要这么做。

得到损失函数计算出的损失值后,我们就要将损失值反响传播到网络中,网络会根据回传的损失值,修改网络模型参数,而后用修改后的网络模型对数据进行重新计算。修改网络模型的方法就是众所周知的求导(链式求导)了。这也是BP神经网络中back propagation的精髓了。在学习手动推导求导过程之前,我们先了解一下反响传播的本质,以及求导的目的。

一、神经网络反向传播示意图

拿出我们的经典图,图中新增了一些东西,图中红色的箭头表示神经网络反向传播的路线,网络部分多了两个黄色的区域,代表链接网络中层与层之间的权重矩阵,这也是后续要重点讨论的对象。

从图中可以看出,在损失函数Loss部分产生的损失值,随着网络正向传播来的方向,将误差值反向传播了回去。

神经网络反向传播示意图

 

二、神经网络正向传播原理

下面是一个神经网的络构造图,此图便于我们对神经网络正向传播流程进行分析:

神经网络内部结构图

 

首先,我们要搞清楚一个问题,求导是对谁求导。先回顾一下输入神经网络的输入X是怎么一步步传递到损失函数Loss的。输入层X到Loss要经过一下三个步骤:

                                         X=\begin{bmatrix} X_{1}\\ X_{2}\\ X_{3} \end{bmatrix}

                                         X\rightarrow Loss \Leftrightarrow \left\{\begin{matrix} z_{1}=x_{1}w_{11}+x_{2}w_{12}+x_{3}w_{13} \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ (1)\\ \\ s_{1} = \frac{e^{z_{1}}}{e^{z_{1}}+e^{z_{2}}+e^{z_{3}}} \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ (2) \\ \\ Loss_{1} = -(y_{1}lnS_{1}+y_{2}lnS_{2}+y_{3}lnS_{3})\ \ \ \ (3) \end{matrix}\right.

第一步:输入层X与权重矩阵W相乘,得到输出z

第二步:输出z通过softmax函数转换成概率分布s

第三步:通过损失函数Loss,计算预测概率分布s和真实概率分布y之间的损失值loss

现在神经网络的原理是不是就很清楚了:

1.输入X为已知数据。

2.s是通过softmax函数计算而来,softmax函数为已知表达式

3.loss是通过交叉熵函数和真实的概率分布计算而来,交叉熵函数表达式已知,真实的概率分布已知。

4.矩阵W是未知数据
 

 

三、寻找求导目标及链式求导的应用

通过第二节的结论,显然,整个过程中只有一个未知量即W。

事实上我们所谓的训练神经网络最后的结果就是生成一个或多个参数矩阵W,所以我们反向传播损失值本质上也就是为了修改权重矩阵W。那么W就是我们要求导的终极目标,即:

                                                                                          \frac{\partial Loss}{\partial W}

但在损失函数和权重矩阵W之间,除损失函数以外,还间隔的有softmax层,以及输出层。那么我们就要以softmax层和输出层为桥梁,来对权重矩阵W求导,即所谓的链式求导:

                                                                         \frac{\partial Loss}{\partial W} = \frac{\partial Loss}{\partial s_{i}}\cdot \frac{\partial s_{i}}{\partial z_{i}}\cdot \frac{\partial z_{i}}{\partial w_{i}}

因此,想求得权重矩阵的倒数,首先要求得损失函数与softmax层之间的倒数,再求softmax层与输出层z之间的导数,最后求得输出层与权重矩阵之间的导数。

原理流程图如下:

反向传播示意图

 

四、总结

我们理清楚了神经网络的正向传播原理,恭喜你,可以说此时你已经从0到1的理解了神经网络原理,同时也明白了反向传播要求导的对象是谁,下一章就一起来手动推导神经网络反向传播公式吧~

传送门:手动推导softmax神经网络反向传播求导过程——softmax前世今生系列(6)

 

五、附学习笔记如下:

</article>
  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
首先,我们需要定义一个卷积层的类,其中包含正向传播反向传播的函数。 ```python import numpy as np import theano import theano.tensor as T class ConvLayer(object): def __init__(self, rng, input_shape, filter_shape): self.input_shape = input_shape self.filter_shape = filter_shape fan_in = np.prod(filter_shape[1:]) fan_out = (filter_shape[0] * np.prod(filter_shape[2:])) W_bound = np.sqrt(6. / (fan_in + fan_out)) self.W = theano.shared( np.asarray( rng.uniform(low=-W_bound, high=W_bound, size=filter_shape), dtype=theano.config.floatX ), borrow=True ) self.b = theano.shared( np.zeros((filter_shape[0],), dtype=theano.config.floatX), borrow=True ) self.params = [self.W, self.b] def convolve(self, input): conv_out = T.nnet.conv2d( input=input, filters=self.W, filter_shape=self.filter_shape, input_shape=self.input_shape ) return T.nnet.sigmoid(conv_out + self.b.dimshuffle('x', 0, 'x', 'x')) def get_cost_updates(self, cost, learning_rate): grads = T.grad(cost, self.params) updates = [(param, param - learning_rate * grad) for param, grad in zip(self.params, grads)] return updates ``` 接下来,我们定义一个多层感知机的类,包含训练函数和预测函数。 ```python class MLP(object): def __init__(self, rng, input_shape, filter_shapes, hidden_sizes, output_size): self.x = T.tensor4('x') self.y = T.matrix('y') self.layers = [] self.params = [] layer_input = self.x input_shape = input_shape for i in range(len(filter_shapes)): filter_shape = filter_shapes[i] layer = ConvLayer(rng=rng, input_shape=input_shape, filter_shape=filter_shape) self.layers.append(layer) self.params += layer.params layer_output = layer.convolve(layer_input) layer_input = layer_output input_shape = (input_shape[0], filter_shape[0], input_shape[2] - filter_shape[2] + 1, input_shape[3] - filter_shape[3] + 1) flatten_layer_output = layer_output.flatten(2) hidden_layer_input = flatten_layer_output hidden_layer_size = input_shape[1] * input_shape[2] * input_shape[3] for hidden_size in hidden_sizes: W = theano.shared( np.asarray( rng.uniform(low=-np.sqrt(6. / (hidden_layer_size + hidden_size)), high=np.sqrt(6. / (hidden_layer_size + hidden_size)), size=(hidden_layer_size, hidden_size)), dtype=theano.config.floatX ), borrow=True ) b = theano.shared( np.zeros((hidden_size,), dtype=theano.config.floatX), borrow=True ) self.params += [W, b] hidden_layer_output = T.nnet.sigmoid(T.dot(hidden_layer_input, W) + b) hidden_layer_input = hidden_layer_output hidden_layer_size = hidden_size W = theano.shared( np.asarray( rng.uniform(low=-np.sqrt(6. / (hidden_layer_size + output_size)), high=np.sqrt(6. / (hidden_layer_size + output_size)), size=(hidden_layer_size, output_size)), dtype=theano.config.floatX ), borrow=True ) b = theano.shared( np.zeros((output_size,), dtype=theano.config.floatX), borrow=True ) self.params += [W, b] self.output = T.nnet.softmax(T.dot(hidden_layer_output, W) + b) self.prediction = T.argmax(self.output, axis=1) self.cost = -T.mean(T.log(self.output)[T.arange(self.y.shape[0]), self.y]) self.updates = self.layers[0].get_cost_updates(self.cost, learning_rate=0.1) for i in range(1, len(self.layers)): layer_updates = self.layers[i].get_cost_updates(self.cost, learning_rate=0.1) self.updates += layer_updates self.train = theano.function(inputs=[self.x, self.y], outputs=self.cost, updates=self.updates, allow_input_downcast=True) self.predict = theano.function(inputs=[self.x], outputs=self.prediction, allow_input_downcast=True) ``` 最后,我们可以使用以下代码来训练和测试模型。 ```python rng = np.random.RandomState(1234) train_x = np.random.rand(100, 1, 28, 28).astype(theano.config.floatX) train_y = np.random.randint(0, 10, size=(100,)).astype(np.int32) mlp = MLP(rng=rng, input_shape=(100, 1, 28, 28), filter_shapes=[(20, 1, 5, 5), (50, 20, 5, 5)], hidden_sizes=[500], output_size=10) for i in range(10): cost = mlp.train(train_x, train_y) print('Epoch %d, cost %f' % (i, cost)) test_x = np.random.rand(10, 1, 28, 28).astype(theano.config.floatX) test_y = np.random.randint(0, 10, size=(10,)).astype(np.int32) pred_y = mlp.predict(test_x) accuracy = np.mean(pred_y == test_y) print('Accuracy %f' % accuracy) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值