大家好,欢迎来到IT知识分享网。
一、CNN原理
卷积神经网络(CNN)主要是用于图像识别领域,它指的是一类网络,而不是某一种,其包含很多不同种结构的网络。不同的网络结构通常表现会不一样。从CNN的一些典型结构中,可以看到这些网络创造者非常有创造力,很多结构都非常巧妙,有机会再介绍现今主流的一些典型结构。 现在我们先来简单介绍一下卷积神经网络的原理。
Very Deep Convolutional Networks for Large-Scale Image Recognition(2014), arXiv: 1409.1556:
![卷积神经网络的原理与应用插图1 卷积神经网络的原理与应用](https://yundeesoft.com/wp-content/uploads/2022/11/2022112316405970.jpg)
所有CNN最终都是把一张图片转化为特征向量,特征向量就相当于这张图片的DNA。就像上图VGG网络一样,通过多层的卷积,池化,全连接,降低图片维度,最后转化成了一个一维向量。这个向量就包含了图片的特征,当然这个特征不是肉眼上的图片特征,而是针对于神经网络的特征。
之所以用VGG举例,因为他的网络结构非常简洁,清晰,相当好理解,简单介绍一下:
- 他的输入是一张224×224 的三通道图片,经过两层卷积之后,图片维度不变,通道数增加到了64。
- 之后那个红色的层是最大池化(max pooling)把图片维度变成了112×112。后续就是不断重复步骤1,2。
- 当变成1维向量之后,经过全连接(fully connected)加ReLU激活,softmax处理之后,变成了一个包含1000个数字的特征向量。
以上就是CNN所做的事情。
二、 CNN如何训练
1. 卷积神经网络的前向传播过程
在前向传播过程中,输入的图形数据经过多层卷积层的卷积和池化处理,提出特征向量,将特征向量传入全连接层中,得出分类识别的结果。当输出的结果与我们的期望值相符时,输出结果。
1.1 前向传播中的卷积操作
- 用一个小的权重矩阵去覆盖输入数据,对应位置加权相乘,其和作为结果的一个像素点;
- 这个权重在输入数据上滑动,形成一张新的矩阵:
![卷积神经网络的原理与应用插图3 卷积神经网络的原理与应用](https://yundeesoft.com/wp-content/uploads/2022/11/2022112316405970.jpg)
- 这个权重矩阵称为卷积核(convolution kernel);
- 其覆盖位置称为感受野(receptive field);
- 参数共享;
- 滑动的像素数量叫做步长(stride):
![卷积神经网络的原理与应用插图5 卷积神经网络的原理与应用](https://yundeesoft.com/wp-content/uploads/2022/11/2022112316405970.jpg)
- 以卷积核的边还是中心点作为开始/结束的依据,决定了卷积的补齐(padding)方式。上面的图片是valid方式(这种方式新的矩阵维度可能会降低),而same方式则会在图像边缘用0补齐(这种方式图像维度不会降低):
![卷积神经网络的原理与应用插图7 卷积神经网络的原理与应用](https://yundeesoft.com/wp-content/uploads/2022/11/2022112316405970.jpg)
- 如果输入通道不只一个,那么卷积核是三阶的。所有通道的结果累加:
![卷积神经网络的原理与应用插图9 卷积神经网络的原理与应用](https://yundeesoft.com/wp-content/uploads/2022/11/2022112316405970.jpg)
如图:
![卷积神经网络的原理与应用插图11 卷积神经网络的原理与应用](https://yundeesoft.com/wp-content/uploads/2022/11/2022112316405970.jpg)
1.2 前向传播中的池化操作
池化又称为降采样(down_sampling),类型:
- 最大池化(max pooling):在感受野内取最大值输出;
- 平均池化(average pooling):在感受野内取平均值进行输出;
- 其他如L2池化等。
理解:
- 一个选择框,将输入数据某个范围(矩阵)的所有数值进行相应计算,得到一个新的值,作为结果的一个像素点;
- 池化也有步长和补齐的概念,但是很少使用,通常选择框以不重叠的方式,在padding=0的输入数据上滑动,生成一张新的特征图:
![卷积神经网络的原理与应用插图13 卷积神经网络的原理与应用](https://yundeesoft.com/wp-content/uploads/2022/11/2022112316405970.jpg)
![卷积神经网络的原理与应用插图15 卷积神经网络的原理与应用](https://yundeesoft.com/wp-content/uploads/2022/11/2022112316405970.jpg)
1.3前向传播中的全连接
特征图进过卷积层和下采样层的特征提取之后,将提取出来的特征传到全连接层中,通过全连接层,进行分类,获得分类模型,得到最后的结果。
2. 卷积神经网络的反向传播过程
当卷积神经网络输出的结果与我们的期望值不相符时,则进行反向传播过程。求出结果与期望值的误差,再将误差一层一层地返回,计算出每一层的误差,然后进行权值更新。
3. 卷积神经网络的权值更新
卷积层的误差更新过程为:将误差矩阵当做卷积核,卷积输入的特征图,并得到了权值的偏差矩阵,然后与原先的卷积核的权值相加,并得到了更新后的卷积核。
卷积神经网络的训练过程流程图:
![卷积神经网络的原理与应用插图17 卷积神经网络的原理与应用](https://yundeesoft.com/wp-content/uploads/2022/11/2022112316405970.jpg)
就像这张流程图一样,不断循环这个过程。最后得到一个稳定的权值和阈值。
目前主流框架是pytorch(facebook)和tensorflow(google)。
举个例子(一个手写数字识别网络,其代码量也就100多行):
import sys import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data from tinyenv.flags import flags FLAGS = None def train(): mnist = input_data.read_data_sets( FLAGS.data_dir, one_hot=True, fake_data=FLAGS.fake_data, ) sess = tf.InteractiveSession() with tf.name_scope('input'): x = tf.placeholder(tf.float32, [None, 784], name='x-input') y_ = tf.placeholder(tf.float32, [None, 10], name='y-input') with tf.name_scope('input_reshape'): image_shaped_input = tf.reshape(x, [-1, 28, 28, 1]) tf.summary.image('input', image_shaped_input, 10) def weight_variable(shape): """Create a weight variable with appropriate initialization.""" initial = tf.truncated_normal(shape, stddev=0.1) return tf.Variable(initial) def bias_variable(shape): """Create a bias variable with appropriate initialization.""" initial = tf.constant(0.1, shape=shape) return tf.Variable(initial) def variable_summaries(var): with tf.name_scope('summaries'): mean = tf.reduce_mean(var) tf.summary.scalar('mean', mean) with tf.name_scope('stddev'): stddev = tf.sqrt(tf.reduce_mean(tf.square(var - mean))) tf.summary.scalar('stddev', stddev) tf.summary.scalar('max', tf.reduce_max(var)) tf.summary.scalar('min', tf.reduce_min(var)) tf.summary.histogram('histogram', var) def nn_layer(input_tensor, input_dim, output_dim, layer_name, act=tf.nn.relu): with tf.name_scope(layer_name): with tf.name_scope('weights'): weights = weight_variable([input_dim, output_dim]) variable_summaries(weights) with tf.name_scope('biases'): biases = bias_variable([output_dim]) variable_summaries(biases) with tf.name_scope('Wx_plus_b'): preactivate = tf.matmul(input_tensor, weights) + biases tf.summary.histogram('pre_activations', preactivate) activations = act(preactivate, name='activation') tf.summary.histogram('activations', activations) return activations hidden1 = nn_layer(x, 784, 500, 'layer1') with tf.name_scope('dropout'): keep_prob = tf.placeholder(tf.float32) tf.summary.scalar('dropout_keep_probability', keep_prob) dropped = tf.nn.dropout(hidden1, keep_prob) y = nn_layer(dropped, 500, 10, 'layer2', act=tf.identity) with tf.name_scope('cross_entropy'): diff = tf.nn.softmax_cross_entropy_with_logits(labels=y_, logits=y) with tf.name_scope('total'): cross_entropy = tf.reduce_mean(diff) tf.summary.scalar('cross_entropy', cross_entropy) with tf.name_scope('train'): train_step = tf.train.AdamOptimizer(FLAGS.learning_rate).minimize( cross_entropy) with tf.name_scope('accuracy'): with tf.name_scope('correct_prediction'): correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1)) with tf.name_scope('accuracy'): accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32)) tf.summary.scalar('accuracy', accuracy) merged = tf.summary.merge_all() train_writer = tf.summary.FileWriter(FLAGS.log_dir + '/train', sess.graph) test_writer = tf.summary.FileWriter(FLAGS.log_dir + '/test') tf.global_variables_initializer().run() def feed_dict(train): if train or FLAGS.fake_data: xs, ys = mnist.train.next_batch(100, fake_data=FLAGS.fake_data) k = FLAGS.dropout else: xs, ys = mnist.test.images, mnist.test.labels k = 1.0 return {x: xs, y_: ys, keep_prob: k} for i in range(FLAGS.iterations): if i % 10 == 0: # Record summaries and test-set accuracy summary, acc = sess.run( [merged, accuracy], feed_dict=feed_dict(False)) test_writer.add_summary(summary, i) print('Accuracy at step %s: %s' % (i, acc)) else: if i % 100 == 99: run_options = tf.RunOptions( trace_level=tf.RunOptions.FULL_TRACE) run_metadata = tf.RunMetadata() summary, _ = sess.run([merged, train_step], feed_dict=feed_dict(True), options=run_options, run_metadata=run_metadata) train_writer.add_run_metadata(run_metadata, 'step%03d' % i) train_writer.add_summary(summary, i) else: summary, _ = sess.run( [merged, train_step], feed_dict=feed_dict(True)) train_writer.add_summary(summary, i) train_writer.close() test_writer.close() def main(_): if tf.gfile.Exists(FLAGS.log_dir): tf.gfile.DeleteRecursively(FLAGS.log_dir) tf.gfile.MakeDirs(FLAGS.log_dir) train() if __name__ == '__main__': FLAGS = flags() tf.app.run(main=main, argv=[sys.argv[0]])
训练之后,其识别准确度已达到96.7%:
![卷积神经网络的原理与应用插图19 卷积神经网络的原理与应用](https://yundeesoft.com/wp-content/uploads/2022/11/2022112316405970.jpg)
三、 应用
1. 图片分类
假设每张图片最后获得了6维特征向量v: [-0., -0., 0., 0.0, 0.0, -0.0]。 我们要把图片分为3类, 那么分类矩阵就应该是6 x 3维的矩阵。 因为根据矩阵乘法:m,n维的矩阵乘以n,l维的矩阵,会得到一个m,l维的矩阵。 所以1 x 6维的矩阵乘以6 x 3维的矩阵最后会得到一个1 x 3的向量。 如上述6维向量乘以分类矩阵之后得到:[-0., -0., 1.0],那么很明显这张图片会被分到第三类。
2. 相似图搜索
广泛应用的人脸识别其实就是相似图搜索,比对两张照片是不是同一个人,当两张照片是同一个人时,他的欧氏距离会非常接近,反之。
![卷积神经网络的原理与应用插图21 卷积神经网络的原理与应用](https://yundeesoft.com/wp-content/uploads/2022/11/2022112316405970.jpg)
余弦距离:
![卷积神经网络的原理与应用插图23 卷积神经网络的原理与应用](https://yundeesoft.com/wp-content/uploads/2022/11/2022112316405970.jpg)
3.对抗样本
对抗样本和神经网络训练过程不同的是,他是固定权重,更新输入数据。比如输入一张猫的图片,人为地修改一点图片数据,肉眼上看还是一只猫,但是你告诉神经网络这是狗。最后大量数据训练这后,神经网络会把这些图片错误的分类到狗这一类。
四、 新技术
1. 批归一化(Batch Normalization)
相当于把数据缩放到了合适的位置,所以应该放在卷积之后,激活函数之前。能加快网络收敛速度。一堆公式,脑壳痛:
![卷积神经网络的原理与应用插图25 卷积神经网络的原理与应用](https://yundeesoft.com/wp-content/uploads/2022/11/2022112316405970.jpg)
2. Dropout(还没有合适的中文翻译)
应用广泛。在标准 Dropout 的每轮迭代中,网络中的每个神经元以 p 的概率被丢弃。Dropout能够有效的改善过拟合的情况,提升泛化能力。前几天google申请的Dropout专利生效了。
Dropout实现要点:
- 一般是实施在分类器之前(论文是放在最后一层分类器之后);
- Dropout以概率p置零神经元,这种情况下,保留的神经元的输出要除以1-p (论文是在inference时把所有权重乘以p);
- 通常p初始值0.5。
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/55426.html