中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

TensorFlow 實戰之實現卷積神經網絡的實例講解

發布時間:2020-09-20 13:49:33 來源:腳本之家 閱讀:210 作者:藍色之旅 欄目:開發技術

本文根據最近學習TensorFlow書籍網絡文章的情況,特將一些學習心得做了總結,詳情如下.如有不當之處,請各位大拿多多指點,在此謝過。

一、相關性概念

1、卷積神經網絡(ConvolutionNeural Network,CNN)

19世紀60年代科學家最早提出感受野(ReceptiveField)。當時通過對貓視覺皮層細胞研究,科學家發現每一個視覺神經元只會處理一小塊區域的視覺圖像,即感受野。20世紀80年代,日本科學家提出神經認知機(Neocognitron)的概念,被視為卷積神經網絡最初的實現原型。神經認知機中包含兩類神經元:S-cells和C-cells。S-cells用來抽取特征,對應我們現在主流卷積神經網絡中的卷積核濾波操作;C-cells用來抗形變,對應現在的激活函數、最大池化(Max-Pooling)等操作。

一般情況下,卷積神經網絡由多個卷積層構成,每個卷積層通常會進行如下操作:

(1) 圖像通過多個不同的卷積核的濾波,并加偏置(bias),提取出局部特征,每一個卷積核會映射出一個新的2D圖像。

(2) 將前面卷積核的濾波處理結果,進行非線性的激活函數處理。目前最常見的是使用ReLU函數,之前Sigmoid函數應用較多。

(3)多激活函數處理的結果再進行池化操作(即降采樣,例如:將4*4的圖片降為1*1的圖片),一般會使用最大池化,保留最顯著特征,并提升模型畸變容忍能力。

這幾個步驟就構成了最常見的卷積層,也可以再加上一個LRN(LocalResponse Normalization,局部響應歸一化層)層,現在非常流行的Trick還有BatchNormalization等。

2、池化層

3、卷積核尺寸

4、神經網絡算法相關特性

4.1、優點

(1)可以高效提取特征。

當我們面對一個分類任務時,傳統的機器學習算法,一般要首先明確feature和label,然后拿數據取“喂”訓練模型并保存,最后測試模型的準確性。這就需要我們確定好特征,當特征數目很少就無法精確進行分類而引起欠擬合;當特征數目很多,又會在分類過程中太過于看重某個特征引起分類錯誤,產生過擬合。而神經網絡則不需要做大量的特征工程,可以直接把數據“灌”進去而讓其自身訓練,自我“修正”,即可達到預期效果。   (2)數據格式更加簡易

利用傳統的機器學習解決分類問題時,數據不能直接“灌”進去的,需要對數據進行一些處理,譬如量綱的歸一化,格式的轉化等等,然而在神經網絡里卻不需要額外對數據做過多的處理。

(3) 參數數目的少量性

同樣在面對一個分類問題時,利用傳統機器學習SVM來做的話,需要涉及核函數,懲罰因子,松弛變量等等參數,而這些不同的參數組合會對模型效果產生不一樣的影響,想要迅速而又準確的得到最適合模型的參數,需要對相關理論知識有深入研究,但對于一個基本的三層神經網絡來說(輸入-隱含-輸出),只需要初始化時給每一個神經元上隨機的賦予一個權重w和偏置項b,在訓練過程中,這兩個參數就會不斷的修正,調整到最優質,使模型的誤差最小。所以從這個角度來看,我們的工作效率會更佳。 4.2、缺點

如果我們加深我網絡層,每一個網絡層都增加神經元數量,則參數的個數將是M*N(m為網絡層數,N為每層神經元個數),這樣一來參數很多,引起模型復雜化,就更加不好調參,進而會更加容易導致過擬合。另外,從神經網絡的反向傳播的過程來看,梯度在反向傳播時,不斷的迭代會導致梯度越來越小,引起梯度趨近于0(梯度消失),梯度消失就使得權值無法更新,這個神經元的存在就毫無意義,很難導致收斂。尤其是在圖像領域,直接使用最基本的神經網絡,是不合理的。

二、卷積神經網絡基本原理

1、基本闡述

現在有一圖像,其尺寸大小是1000像素*1000像素且設定為黑白圖像,也就是只有一個顏色通道,則一張圖片就要100萬個像素點,輸入數據維度也是100萬維。如果連接的現在隱含層大小也是同樣大小(100萬個隱含節點),最后將產生100萬*100萬即一億萬個連接。僅僅一個全連接(FullConnected Layer),就有一萬億連接的權重需要去訓練,目前看,顯然是不劃算不現實。

通過局部連接(LocalConnect)方法優化解決:由于每一個感受野只接受一小塊區域的信號,且這一小塊區域內的像素是互相關聯的,每一個神經元不需要接收全部像素點的信息,只需要接收局部的像素點作為輸入,而后將所有這些神經元收到的局部信息綜合起來,就可以得到全局信息。假設局部感受野大小是10*10,即每個隱含節點只與10*10個像素點相連,現在只需要10*100萬即1億個連接。

現在隱含層每一個節點都與10*10的像素相連,即每一個隱含層節點都擁有100個參數。假設我們的局部連接方式是卷積操作,即默認每一個隱含節點的參數都完全一樣,這樣參數從1億降為100。不管圖像大小是多大,一律都是這個10*10=100個參數,即卷積核尺寸,顯然卷積核對縮小參數數量貢獻非常大、意義非凡。因此,此時,我們不需要再擔心有多少隱含節點或者圖片多大,參數量只跟卷積核的大小有關,即所謂的權值共享。

總結:卷積神經網絡要素是局部連接(LocalConnection)、權值共享(WeightSharing)和池化層(Pooling)中的降采樣(Down-Sampling)。其中,局部連接和權值共享降低了參數量,訓練復雜度被大大下降、過擬合被減輕。同時,權值共享還賦予了卷積網絡對平移的容忍性,而池化層降采樣則進一步降低了輸出參數量,并賦予模型對輕度形變的容忍性,提供了模型的泛化能力。

2、LeNet5

1994年,大名鼎鼎的LeNet5誕生,作為最早的深層卷積神經網絡之一,推動了深度學習的發展。自1998年開始,在多次成功迭代之后,由Yann LeCun完成的開拓性成果被命名為LeNet5。LeCun認為,可訓練參數的卷積層是一種利用少量參數在圖像的多個位置上提取相似特征的有效方式,這和直接把每個像素作為多層神經網絡的輸入不一樣。像素不應該被使用在輸入層,因為圖像具有很強的空間相關性,而使用圖像中獨立的像素直接作為輸入則利用不到這些相關性。筆者認為,這些內容比較重要。

在當時,LeNet5的特性如下:

(1)每個卷積層包含三個部分:卷積、池化和非線性激活函數;

(2)使用卷積提取空間特征;

(3)降采樣(Subsample)的平均池化層(AveragePooling);

(4)雙曲正切(Tanh)或S型(Sigmoid)的激活函數;

(5)MLP作為最后的分類器;

(6)層與層之間的稀疏性連接減少計算復雜度。

三、TensorFlow 實現簡單的卷積網絡

1、簡要說明

這里使用的數據集依然是MNIST,使用兩個卷積層加一個全連接層構建一個簡單但非常有代表性的卷積神經網絡,預計準確率約為99.2%左右。

2、實現過程

#載入MNIST數據集,創建默認的Interactive Session。
from tensorflow.examples.tutorials.mnist import input_data
import tensorflow as tf
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)
sess = tf.InteractiveSession()
 
#定義初始化函數,以便重復使用創建權重、偏置、卷積層、池化層。
def weight_variable(shape):
 initial = tf.truncated_normal(shape, stddev=0.1)
 return tf.Variable(initial)
 
def bias_variable(shape):
 initial = tf.constant(0.1, shape=shape)
 return tf.Variable(initial)
 
def conv2d(x, W):
 return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')
 
def max_pool_2x2(x):
 return tf.nn.max_pool(x, ksize=[1, 2, 2, 1],
      strides=[1, 2, 2, 1], padding='SAME') 
 
#在設計卷積神經網絡結構之前,定義輸入的placeholder,x是特征,y_是真實Label。
#由于卷積神經網絡會使用到空間結構信息,所以,需要將1D的輸入向量轉為2D圖片結構,即從1*784的形式轉換為原始的28*28結構。
#因為只有一個顏色通道,所以最終尺寸為[-1,28,28,1],其中‘-1'代表樣本數量不固定,'1'代表顏色通道數量。
x = tf.placeholder(tf.float32, [None, 784])
y_ = tf.placeholder(tf.float32, [None, 10])
x_image = tf.reshape(x, [-1,28,28,1])
#定義第一個卷積層。
#先使用前面函數進行初始化,包括weights和bias。其中[5,5,1,32]代表卷積核尺寸為5**5,1個顏色通道,32個不同的卷積核。
W_conv1 = weight_variable([5, 5, 1, 32])
b_conv1 = bias_variable([32])
h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1)
h_pool1 = max_pool_2x2(h_conv1)
#定義第二個卷積層。
#基本與第一個卷積層一樣,只是其中的卷積核數量變成64.
W_conv2 = weight_variable([5, 5, 32, 64])
b_conv2 = bias_variable([64])
h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2)
h_pool2 = max_pool_2x2(h_conv2)
 
W_fc1 = weight_variable([7 * 7 * 64, 1024])
b_fc1 = bias_variable([1024])
h_pool2_flat = tf.reshape(h_pool2, [-1, 7*7*64])
h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1)
#為了減輕過擬合,使用一個Dropout層,其用法是通過一個placeholder傳入keep_prob比率來控制。
keep_prob = tf.placeholder(tf.float32)
h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)
 
W_fc2 = weight_variable([1024, 10])
b_fc2 = bias_variable([10])
y_conv=tf.nn.softmax(tf.matmul(h_fc1_drop, W_fc2) + b_fc2)
#定義損失函數cross_entropy,這里選擇Adam優化器。
cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(y_conv), reduction_indices=[1]))
train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)
#繼續定義評測準確率操作。
correct_prediction = tf.equal(tf.argmax(y_conv,1), tf.argmax(y_,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
 
#開始訓練過程。
tf.global_variables_initializer().run()
for i in range(20000):
 batch = mnist.train.next_batch(50)
 if i%100 == 0:
 train_accuracy = accuracy.eval(feed_dict={
  x:batch[0], y_: batch[1], keep_prob: 1.0})
 print("step %d, training accuracy %g"%(i, train_accuracy))
 train_step.run(feed_dict={x: batch[0], y_: batch[1], keep_prob: 0.5})
#全部訓練完畢,在最終的測試集上進行全面測試,得到整體的分類準確率。
print("test accuracy %g"%accuracy.eval(feed_dict={
 x: mnist.test.images, y_: mnist.test.labels, keep_prob: 1.0}))

3、執行結果

Extracting MNIST_data/train-images-idx3-ubyte.gz
Extracting MNIST_data/train-labels-idx1-ubyte.gz
Extracting MNIST_data/t10k-images-idx3-ubyte.gz
Extracting MNIST_data/t10k-labels-idx1-ubyte.gz
step 0, training accuracy 0.1
step 100, training accuracy 0.82
step 200, training accuracy 0.9
step 300, training accuracy 0.9
step 400, training accuracy 0.96
step 500, training accuracy 0.9
step 600, training accuracy 0.94
step 700, training accuracy 0.96
step 800, training accuracy 0.94
step 900, training accuracy 0.98
.  .  .  .  .
 
step 19600, training accuracy 1
step 19700, training accuracy 1
step 19800, training accuracy 1
step 19900, training accuracy 1
test accuracy 0.9929

4、模型分析

CNN模型的最終準確率約為99.2%,基本上可以滿足對手寫數字識別準確率的初步要求。相比于之前的MLP2%的錯誤率,CNN下降了60%左右。這里的性能提升主要在于更佳的網絡設計,也就是卷積網絡對圖像特征的提取和抽象能力。依靠卷積核的權值共享,CNN的參數數量沒有爆炸,降低計算量的同時也減去了過擬合,所以,整個模型的性能會有較大的提升。

四、TensorFlow實現進階的卷積網絡

1、基本介紹

這里使用CIFAR-10數據集,包含60,000張32*32的彩色圖像,其中訓練集50,000張,測試10,000張,一共標注為10類,分別為airplane、automobile、bird、cat、deer、dog、frog、horse、shhip、truck,,每一類圖片6000張,其中沒有任何重疊情況發生,例如:automobile 只包括小型汽車,truck只包括卡車,不會出現一張圖片展現兩類物體的現象。

2、實現過程

#載入數據
import cifar10,cifar10_input
import tensorflow as tf
import numpy as np
import time
 
max_steps = 3000 #訓練輪數
batch_size = 128
data_dir = '/tmp/cifar10_data/cifar-10-batches-bin'#下載數據默認路徑。
 
 
def variable_with_weight_loss(shape, stddev, wl):
 var = tf.Variable(tf.truncated_normal(shape, stddev=stddev))
 if wl is not None:
  weight_loss = tf.multiply(tf.nn.l2_loss(var), wl, name='weight_loss')
  tf.add_to_collection('losses', weight_loss)
 return var
 
#計算CNN的損失。
def loss(logits, labels):
 
 labels = tf.cast(labels, tf.int64)
 cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits(
  logits=logits, labels=labels, name='cross_entropy_per_example')
 cross_entropy_mean = tf.reduce_mean(cross_entropy, name='cross_entropy')
 tf.add_to_collection('losses', cross_entropy_mean)
 
 return tf.add_n(tf.get_collection('losses'), name='total_loss') 
 
cifar10.maybe_download_and_extract()
 
images_train, labels_train = cifar10_input.distorted_inputs(data_dir=data_dir,
               batch_size=batch_size)
 
images_test, labels_test = cifar10_input.inputs(eval_data=True,
            data_dir=data_dir,
            batch_size=batch_size)            
 
image_holder = tf.placeholder(tf.float32, [batch_size, 24, 24, 3])
label_holder = tf.placeholder(tf.int32, [batch_size])
 
#創建第一個卷積層。
weight1 = variable_with_weight_loss(shape=[5, 5, 3, 64], stddev=5e-2, wl=0.0)
kernel1 = tf.nn.conv2d(image_holder, weight1, [1, 1, 1, 1], padding='SAME')
bias1 = tf.Variable(tf.constant(0.0, shape=[64]))
conv1 = tf.nn.relu(tf.nn.bias_add(kernel1, bias1))
pool1 = tf.nn.max_pool(conv1, ksize=[1, 3, 3, 1], strides=[1, 2, 2, 1],
      padding='SAME')
norm1 = tf.nn.lrn(pool1, 4, bias=1.0, alpha=0.001 / 9.0, beta=0.75)
 
#創建第二個卷積層。
weight2 = variable_with_weight_loss(shape=[5, 5, 64, 64], stddev=5e-2, wl=0.0)
kernel2 = tf.nn.conv2d(norm1, weight2, [1, 1, 1, 1], padding='SAME')
bias2 = tf.Variable(tf.constant(0.1, shape=[64]))
conv2 = tf.nn.relu(tf.nn.bias_add(kernel2, bias2))
norm2 = tf.nn.lrn(conv2, 4, bias=1.0, alpha=0.001 / 9.0, beta=0.75)
pool2 = tf.nn.max_pool(norm2, ksize=[1, 3, 3, 1], strides=[1, 2, 2, 1],
      padding='SAME')
#使用一個全連接層,先把第二個卷積層的輸出結果flatten,將每個樣本都變成一維向量。
reshape = tf.reshape(pool2, [batch_size, -1])
dim = reshape.get_shape()[1].value
weight3 = variable_with_weight_loss(shape=[dim, 384], stddev=0.04, wl=0.004)
bias3 = tf.Variable(tf.constant(0.1, shape=[384]))
local3 = tf.nn.relu(tf.matmul(reshape, weight3) + bias3)
#下面這個使用的全連接層,其隱含節點數下降了一半。
weight4 = variable_with_weight_loss(shape=[384, 192], stddev=0.04, wl=0.004)
bias4 = tf.Variable(tf.constant(0.1, shape=[192]))          
local4 = tf.nn.relu(tf.matmul(local3, weight4) + bias4)
 
weight5 = variable_with_weight_loss(shape=[192, 10], stddev=1/192.0, wl=0.0)
bias5 = tf.Variable(tf.constant(0.0, shape=[10]))
logits = tf.add(tf.matmul(local4, weight5), bias5)
loss = loss(logits, label_holder)
train_op = tf.train.AdamOptimizer(1e-3).minimize(loss) #0.72
top_k_op = tf.nn.in_top_k(logits, label_holder, 1)
sess = tf.InteractiveSession()
tf.global_variables_initializer().run()
tf.train.start_queue_runners()
#正式開始訓練。
for step in range(max_steps):
 start_time = time.time()
 image_batch,label_batch = sess.run([images_train,labels_train])
 _, loss_value = sess.run([train_op, loss],feed_dict={image_holder: image_batch,
               label_holder:label_batch})
 duration = time.time() - start_time
 if step % 10 == 0:
  examples_per_sec = batch_size / duration
  sec_per_batch = float(duration)
  
  format_str = ('step %d, loss = %.2f (%.1f examples/sec; %.3f sec/batch)')
  print(format_str % (step, loss_value, examples_per_sec, sec_per_batch))
  
#評測模型在測試集上的準確率。
num_examples = 10000
import math
num_iter = int(math.ceil(num_examples / batch_size))
true_count = 0 
total_sample_count = num_iter * batch_size
step = 0
while step < num_iter:
 image_batch,label_batch = sess.run([images_test,labels_test])
 predictions = sess.run([top_k_op],feed_dict={image_holder: image_batch,
             label_holder:label_batch})
 true_count += np.sum(predictions)
 step += 1
#最后,將準確率的評測結果計算并輸出。
precision = true_count / total_sample_count
print('precision @ 1 = %.3f' % precision)

3、執行結果

由于筆者試了幾次CIFAR-10模塊,最后一步失敗,所以沒能正確顯示,后續找機會再試試,但以筆者的初步判斷,在CIFAR-10安裝成功的情況下,執行結果應該是沒問題的。感興趣的朋友可以再看看,這里就不貼出相關結果了,望各位網友理解。

4、模型分析

在CIFAR-10數據集上,通過一個短時間小迭代次數的訓練,可以達到約73%的準確率,后續若增加max_steps,期望準確率會逐漸增加。若max_steps比較大的化,建議使用學習速率衰減(decay)的SGD來進行訓練,其訓練過程中準確率的峰值會較高,約86%,因為這其中的L2正則和LRN層的使用均提升了模型準確率和模型的泛化性能。

五、小結

卷積網絡最后的幾個全連接層的作用是輸出分類結果,前面的卷積層主要做特征提取工作,直到最后的全連接層才開始對特征進行組合分配,并進行分類。

卷積層一般需要和一個池化層連接,二者組合是做圖像識別時的一個標準組件。卷積層的訓練相對于全連接層更復雜,訓練全連接層基本是進行一個些矩陣乘法運算,而目前卷積層的訓練基本上依賴于cuDNN實現,其中的算法也相對復雜,甚至會涉及到傅里葉變換。

參考資料 主要參考資料《TensorFlow實戰》(黃文堅 唐源 著)(電子工業出版社)。

以上這篇TensorFlow 實戰之實現卷積神經網絡的實例講解就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支持億速云。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

新巴尔虎右旗| 讷河市| 顺平县| 鹿泉市| 本溪市| 叶城县| 察雅县| 禄丰县| 南澳县| 长岛县| 台南市| 华坪县| 江阴市| 祁连县| 封丘县| 西吉县| 黎川县| 高雄市| 海林市| 昌平区| 江西省| 嘉禾县| 安岳县| 革吉县| 银川市| 德令哈市| 张家港市| 梁平县| 镇巴县| 象山县| 鄂伦春自治旗| 梧州市| 大英县| 万宁市| 眉山市| 邻水| 罗田县| 驻马店市| 绥棱县| 伊宁市| 开江县|