神经网略图像识别或分类问题该怎么玩step 1
Posted 千古侠客文人梦
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了神经网略图像识别或分类问题该怎么玩step 1相关的知识,希望对你有一定的参考价值。
一、先看作为例子的网络结构
本想搞个四层的,让大家能够从视觉上感受到神经网络的强大,考虑到码文字的工作量,暂时把这个100层的去掉变成三层的。原谅我的偷懒。
输入层/也称之为数据层等:batchsize*784=batchsize*32*32*1
解释一下:Batchsize就是跑一个来回所用的训练样本数据。784就是一个样本的所有数据,我这里使用mnist数据集。如下图所示:
左边是玩卷积的CIFAR数据集,为下一篇文章作铺垫的,只欣赏视觉美,其他不管。右边才是我们的mnist数据集,直白点就是手写数字图像,每个数字就是一张32*32的图像,如左上角红色方框。所以一张图像的数据是32*32*1。这里出现1是因为手写数字图像数据都是单通道的,后期计算的时候就省略了1,但是1的数学意义必须清楚,我在写下一篇《卷积神经网络图像识别或分类问题怎么玩》的时候需要用到这个通道数。综上所述:输入层的数据是一个:Batchsize行*784列的二维矩阵。
隐层(HideLayer):在一个网略中,除了输入层和输出层以外的其他层均称之为隐层。这是一个三层网略,所以只有1层隐层,且大小设置为10
解释一下:隐层的意义,综合各家言论,下面3条是公认度最高的。①Each layer can apply any function that you want to the previous layer(usually,a linear transformation followed by a squashing nonlinearity).②The hidden layers' job is to transform the inputs into something that the output layer can use.③The output layer transforms the hidden layer activations into whatever scale you wanted your output to be on. 翻译过来就是:①每个隐层都可以应用在你训练的模型的前一层。②隐层的作用是将输入转换成输出。③输出层将隐层的激活转换成期望输出的比例。
参数W1:w1是一个784*25的矩阵
参数W2: w2是一个25*10的矩阵
输出层:out的大小为10,也就是说一个图像数据最终会得到10个分类结果。
二、前向传播
以前高中时候经常听数学老师说“数形结合”,硕士写论文时经常听大咖说“字不如图,图不如表”。所以这里先看一张图,整个前向传播过程如图所示:
x : 输入数据
w1,w2 : 权重参数
y : 输出类别out
softmax(y) : 求所有类别概率p,该函数本质是sigmoid函数的推广,日后细说
lab(p) : 训练样本的标签,根据标签索引下表找到该样本的概率p'
-log(p'):建立Loss函数
这个圆圈是隐层的缩写,里面是一个rule函数,该函数的功能是将线性映射关系变成离散的,也就是非线性的。也可以使用sigmoid函数代替rule函数,但是sigmoid函数会存在梯度消失现象,对参数更新极为不利。这也是日后细说
2.1 前向传播的数学计算过程
数据集已经被收集,制作好,并且已经进行好预处理(这个坑,之后单独更新一篇文章来讲,如何制作个人数据集)。数据集是长这样的。
逐个解释一下:每一行都是一个样本,以第一行为例,5是该样本的实际值,也是标签,不过这个label格式是非标准的,后面需要制作一个标准格式的label。除过5以外的数据是该图像的pixel,最后一列是28x28。这样一个样本的所有pixel和它的标签值都放在了一行,每一行就是一个样本,图中由0~255的数据组成,0就是白色,数字边缘是0~255的值,1就是黑色,专业称呼为灰度值。用python画出来几个样本如下图所示:
数据集有了,网络框架也已经定下来了。现在该初始化w1和w2了
w1是一个25x784的矩阵(一直称呼为矩阵,别扭啊,在TensorFlow中,矩阵是一种数据结构,称为“张量”,下文中,我都将之称为‘张量’)。w2是一个10x25的二维张量。便于代码的可读性,称w为theta
#staticmethod
def thetas_init(layers):
num_layers = len(layers)
thetas={}
for layers_index in range(num_layers-1):
in_count = layers[layer_index]
out_count = layers[layer_index+1]
np.random.rand(out_count,in_count+1)*0.05 =
return thetas
要明白in_count+1是怎么回事,首先得明白偏置项的作用。(再挖一个坑),输入是X,参数是θ,再加上偏置b应该是:X*θ+b,为了好看,根据张量的乘法,给X和θ各增加一维。X'=[1,X],θ'=[b,θ],X'*θ' = b+X*θ。所以in_count+1多增加一维后初始化,相当于增加了一个b,当然这与我刚举的这个例子格式上有些出入,且往后看,一目了然。
参数w1和w2初始化完成后存储在字典thetas里面。
逐层向前计算:
#staticmethod
def feedforward_propagation(data,thetas,layers):
num_layers = len(layers)
num_examples = data.shape[0]
in_layer_activation = data
for layer_index in range(num_layers):
theta = thetas[layer_index]
out_layer_activation = sigmoid(np.dot(in_layer_activation,theta.T))
out_layer_activation = np.hstack((np.ones((num_examples,1)),out_layer_activation))
in_layer_activation = out_layer_activation
return in_layer_activation[:,1:]
大致解释一下:
sigmoid(np.dot(in_layer_activation,theta.T)) =
这行代码执行完成后,out_layer_activation是一个num_example X 25的张量。但是w2是一个10X26的张量(因为偏置项b),为了能使out_layer_activation能和w2执行np.dot()操作,必须给out_layer_activation张量链接一个num_example X 1的张量,且值均为1。看到这里,大家就会明白我在上文中所举的X’*θ’的例子。
np.hstack((np.ones((num_examples,1)),out_layer_activation)) =
执行完,这行代码后,out_layer_activation矩阵张量就会发生如下变化。
多的一列做张量的乘法后,刚好是偏置项b。代码这样写的好处是方便更多层的计算,但是attentionPlease: 我们最终的输出结果需要去链接。
循环执行第二次:out_layer_activation和w2进行np.dot()操作,紧接着又进行了hstack()链接后得到out_layer_activation是一个num_example+1 X 10的张量,毫无疑问和上述一样,张量的第一列全是1,所以去链接后的:num_example_activation X 10的张量才是输出层的最终结果。
未完,待续《神经网略图像识别或分类问题该怎么玩step 2》。
以上是关于神经网略图像识别或分类问题该怎么玩step 1的主要内容,如果未能解决你的问题,请参考以下文章
OpenCV车辆识别 目标检测 级联分类器 C++ 案例实现