cnn卷积神经网络_卷积神经网络(CNN)原理及应用
一、CNN原理
卷積神經(jīng)網(wǎng)絡(luò)(CNN)主要是用于圖像識(shí)別領(lǐng)域,它指的是一類網(wǎng)絡(luò),而不是某一種,其包含很多不同種結(jié)構(gòu)的網(wǎng)絡(luò)。不同的網(wǎng)絡(luò)結(jié)構(gòu)通常表現(xiàn)會(huì)不一樣。從CNN的一些典型結(jié)構(gòu)中,可以看到這些網(wǎng)絡(luò)創(chuàng)造者非常有創(chuàng)造力,很多結(jié)構(gòu)都非常巧妙,有機(jī)會(huì)再介紹現(xiàn)今主流的一些典型結(jié)構(gòu)。 現(xiàn)在我們先來(lái)簡(jiǎn)單介紹一下卷積神經(jīng)網(wǎng)絡(luò)的原理。
Very Deep Convolutional Networks for Large-Scale Image Recognition(2014), arXiv: 1409.1556:
所有CNN最終都是把一張圖片轉(zhuǎn)化為特征向量,特征向量就相當(dāng)于這張圖片的DNA。就像上圖VGG網(wǎng)絡(luò)一樣,通過(guò)多層的卷積,池化,全連接,降低圖片維度,最后轉(zhuǎn)化成了一個(gè)一維向量。這個(gè)向量就包含了圖片的特征,當(dāng)然這個(gè)特征不是肉眼上的圖片特征,而是針對(duì)于神經(jīng)網(wǎng)絡(luò)的特征。
之所以用VGG舉例,因?yàn)樗木W(wǎng)絡(luò)結(jié)構(gòu)非常簡(jiǎn)潔,清晰,相當(dāng)好理解,簡(jiǎn)單介紹一下:
以上就是CNN所做的事情。
二、 CNN如何訓(xùn)練
1. 卷積神經(jīng)網(wǎng)絡(luò)的前向傳播過(guò)程
在前向傳播過(guò)程中,輸入的圖形數(shù)據(jù)經(jīng)過(guò)多層卷積層的卷積和池化處理,提出特征向量,將特征向量傳入全連接層中,得出分類識(shí)別的結(jié)果。當(dāng)輸出的結(jié)果與我們的期望值相符時(shí),輸出結(jié)果。
1.1 前向傳播中的卷積操作
- 用一個(gè)小的權(quán)重矩陣去覆蓋輸入數(shù)據(jù),對(duì)應(yīng)位置加權(quán)相乘,其和作為結(jié)果的一個(gè)像素點(diǎn);
- 這個(gè)權(quán)重在輸入數(shù)據(jù)上滑動(dòng),形成一張新的矩陣:
- 這個(gè)權(quán)重矩陣稱為卷積核(convolution kernel);
- 其覆蓋位置稱為感受野(receptive field);
- 參數(shù)共享;
- 滑動(dòng)的像素?cái)?shù)量叫做步長(zhǎng)(stride):
- 以卷積核的邊還是中心點(diǎn)作為開(kāi)始/結(jié)束的依據(jù),決定了卷積的補(bǔ)齊(padding)方式。上面的圖片是valid方式(這種方式新的矩陣維度可能會(huì)降低),而same方式則會(huì)在圖像邊緣用0補(bǔ)齊(這種方式圖像維度不會(huì)降低):
- 如果輸入通道不只一個(gè),那么卷積核是三階的。所有通道的結(jié)果累加:
如圖:
1.2 前向傳播中的池化操作
池化又稱為降采樣(down_sampling),類型:
理解:
- 一個(gè)選擇框,將輸入數(shù)據(jù)某個(gè)范圍(矩陣)的所有數(shù)值進(jìn)行相應(yīng)計(jì)算,得到一個(gè)新的值,作為結(jié)果的一個(gè)像素點(diǎn);
- 池化也有步長(zhǎng)和補(bǔ)齊的概念,但是很少使用,通常選擇框以不重疊的方式,在padding=0的輸入數(shù)據(jù)上滑動(dòng),生成一張新的特征圖:
1.3 前向傳播中的全連接
特征圖進(jìn)過(guò)卷積層和下采樣層的特征提取之后,將提取出來(lái)的特征傳到全連接層中,通過(guò)全連接層,進(jìn)行分類,獲得分類模型,得到最后的結(jié)果。
2. 卷積神經(jīng)網(wǎng)絡(luò)的反向傳播過(guò)程
當(dāng)卷積神經(jīng)網(wǎng)絡(luò)輸出的結(jié)果與我們的期望值不相符時(shí),則進(jìn)行反向傳播過(guò)程。求出結(jié)果與期望值的誤差,再將誤差一層一層的返回,計(jì)算出每一層的誤差,然后進(jìn)行權(quán)值更新。
3. 卷積神經(jīng)網(wǎng)絡(luò)的權(quán)值更新
卷積層的誤差更新過(guò)程為:將誤差矩陣當(dāng)做卷積核,卷積輸入的特征圖,并得到了權(quán)值的偏差矩陣,然后與原先的卷積核的權(quán)值相加,并得到了更新后的卷積核。
卷積神經(jīng)網(wǎng)絡(luò)的訓(xùn)練過(guò)程流程圖:
就像這張流程圖一樣,不斷循環(huán)這個(gè)過(guò)程。最后得到一個(gè)穩(wěn)定的權(quán)值和閾值。
目前主流框架是pytorch(facebook)和tensorflow(google)。舉個(gè)例子(一個(gè)手寫(xiě)數(shù)字識(shí)別網(wǎng)絡(luò),其代碼量也就100多行):
import sysimport tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data from tinyenv.flags import flagsFLAGS = Nonedef 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) + biasestf.summary.histogram('pre_activations', preactivate)activations = act(preactivate, name='activation')tf.summary.histogram('activations', activations)return activationshidden1 = 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.dropoutelse:xs, ys = mnist.test.images, mnist.test.labelsk = 1.0return {x: xs, y_: ys, keep_prob: k}for i in range(FLAGS.iterations):if i % 10 == 0: # Record summaries and test-set accuracysummary, 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]])訓(xùn)練之后,其識(shí)別準(zhǔn)確度已達(dá)到96.7%:
三、 應(yīng)用
1. 圖片分類
假設(shè)每張圖片最后獲得了6維特征向量v: [-0.24754368, -0.19974484, 0.45622883, 0.01130153, 0.08802839, -0.0419769]。 我們要把圖片分為3類, 那么分類矩陣就應(yīng)該是6 x 3維的矩陣。 因?yàn)楦鶕?jù)矩陣乘法:m,n維的矩陣乘以n,l維的矩陣,會(huì)得到一個(gè)m,l維的矩陣。 所以1 x 6維的矩陣乘以6 x 3維的矩陣最后會(huì)得到一個(gè)1 x 3的向量。 如上述6維向量乘以分類矩陣之后得到:[-0.7777777, -0.9999999, 1.02222222],那么很明顯這張圖片會(huì)被分到第三類。
2. 相似圖搜索
廣泛應(yīng)用的人臉識(shí)別其實(shí)就是相似圖搜索,比對(duì)兩張照片是不是同一個(gè)人,當(dāng)兩張照片是同一個(gè)人時(shí),他的歐氏距離會(huì)非常接近,反之。
余弦距離:
3.對(duì)抗樣本
對(duì)抗樣本和神經(jīng)網(wǎng)絡(luò)訓(xùn)練過(guò)程不同的是,他是固定權(quán)重,更新輸入數(shù)據(jù)。比如輸入一張貓的圖片,人為的修改一點(diǎn)圖片數(shù)據(jù),肉眼上看還是一只貓,但是你告訴神經(jīng)網(wǎng)絡(luò)這是狗。最后大量數(shù)據(jù)訓(xùn)練這后,神經(jīng)網(wǎng)絡(luò)會(huì)把這些圖片錯(cuò)誤的分類到狗這一類。
四、 新技術(shù)
1. 批歸一化(Batch Normalization)
相當(dāng)于把數(shù)據(jù)縮放到了合適的位置,所以應(yīng)該放在卷積之后,激活函數(shù)之前。能加快網(wǎng)絡(luò)收斂速度。一堆公式,腦殼痛:
2. Dropout(還沒(méi)有合適的中文翻譯)
應(yīng)用廣泛。在標(biāo)準(zhǔn) Dropout 的每輪迭代中,網(wǎng)絡(luò)中的每個(gè)神經(jīng)元以 p 的概率被丟棄。Dropout能夠有效的改善過(guò)擬合的情況,提升泛化能力。前幾天google申請(qǐng)的Dropout專利生效了。
Dropout實(shí)現(xiàn)要點(diǎn):
- 一般是實(shí)施在分類器之前(論文是放在最后一層分類器之后);
- Dropout以概率p置零神經(jīng)元,這種情況下,保留的神經(jīng)元的輸出要除以1-p (論文是在inference時(shí)把所有權(quán)重乘以p);
- 通常p初始值0.5。
總結(jié)
以上是生活随笔為你收集整理的cnn卷积神经网络_卷积神经网络(CNN)原理及应用的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Python按键精灵自动化_安装Pyth
- 下一篇: python3模拟键盘输入_Python