日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 人工智能 > 卷积神经网络 >内容正文

卷积神经网络

TensorFlow:实战Google深度学习框架(五)图像识别与卷积神经网络

發(fā)布時(shí)間:2023/12/15 卷积神经网络 58 豆豆
生活随笔 收集整理的這篇文章主要介紹了 TensorFlow:实战Google深度学习框架(五)图像识别与卷积神经网络 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

  • 第6章 圖像識(shí)別與卷積神經(jīng)網(wǎng)絡(luò)
    • 6.1 圖像識(shí)別問(wèn)題簡(jiǎn)介及經(jīng)典數(shù)據(jù)集
    • 6.2 卷積神經(jīng)網(wǎng)絡(luò)簡(jiǎn)介
    • 6.3 卷積神經(jīng)網(wǎng)絡(luò)常用結(jié)構(gòu)
      • 6.3.1 卷積層
      • 6.3.2 池化層
    • 6.4 經(jīng)典卷積神經(jīng)網(wǎng)絡(luò)模型
      • 6.4.1 LeNet-5模型
      • 6.4.2 Inception模型
    • 6.5 卷積神經(jīng)網(wǎng)絡(luò)實(shí)現(xiàn)遷移學(xué)習(xí)
      • 6.5.1 遷移學(xué)習(xí)的介紹

第6章 圖像識(shí)別與卷積神經(jīng)網(wǎng)絡(luò)

本章通過(guò)利用CNN實(shí)現(xiàn)圖像識(shí)別的應(yīng)用來(lái)說(shuō)明如何使用TensorFlow實(shí)現(xiàn)卷積神經(jīng)網(wǎng)絡(luò)

6.1 圖像識(shí)別問(wèn)題簡(jiǎn)介及經(jīng)典數(shù)據(jù)集

1. Cifar

Cifar-10:10種不同種類的60000張圖像,像素大小為32*32的彩色圖像

Cifar-100:20 個(gè)大類,大類又細(xì)分為 100 個(gè)小類別,每類包含 600 張圖像。

  • Cifar相比MNIST的最大區(qū)別:彩色,且每張圖包含一個(gè)種類的實(shí)體分類難度更高。
  • 無(wú)論Cifar還是MNIST,相比真實(shí)環(huán)境的圖像識(shí)別,還有兩個(gè)主要的問(wèn)題:
  • 現(xiàn)實(shí)生活的圖片分辨率遠(yuǎn)遠(yuǎn)高于32*32,且分辨率不固定;
  • 現(xiàn)實(shí)生活中物體類別很多,且每張圖像中不會(huì)僅僅出現(xiàn)一種物體;

2. ImageNet

  • 由斯坦福教授李飛飛(Feifei Li)帶頭整理的數(shù)據(jù)庫(kù),更加貼近真實(shí)生活環(huán)境。
  • Imagenet數(shù)據(jù)集有1400多萬(wàn)幅圖片,涵蓋2萬(wàn)多個(gè)類別;其中有超過(guò)百萬(wàn)的圖片有明確的類別標(biāo)注和圖像中物體位置的標(biāo)注,
  • 相關(guān)信息:
    1)Total number of non-empty synsets: 21841

    2)Total number of images: 14,197,122

    3)Number of images with bounding box annotations: 1,034,908

    4)Number of synsets with SIFT features: 1000

    5)Number of images with SIFT features: 1.2 million

6.2 卷積神經(jīng)網(wǎng)絡(luò)簡(jiǎn)介

前面所介紹的神經(jīng)網(wǎng)絡(luò)都為全連接神經(jīng)網(wǎng)絡(luò),本節(jié)的卷積神經(jīng)網(wǎng)絡(luò)是非全連接的神經(jīng)網(wǎng)絡(luò),全連接與卷積神經(jīng)網(wǎng)絡(luò)的結(jié)構(gòu)對(duì)比如下:

兩者之間最主要的區(qū)別就在于相鄰兩層之間的連接方式

1. 為什么全連接不能很好的處理圖像數(shù)據(jù)

最大的問(wèn)題在于全連接層參數(shù)太多,使得計(jì)算速度減慢,且容易導(dǎo)致過(guò)擬合問(wèn)題。

2. 卷積神經(jīng)網(wǎng)絡(luò)的優(yōu)勢(shì)

卷積神經(jīng)網(wǎng)絡(luò)的前幾層都被組織成一個(gè)三維矩陣,可以看出前幾層的每個(gè)節(jié)點(diǎn)都是和上層中的部分節(jié)點(diǎn)相連,卷積神經(jīng)網(wǎng)絡(luò)由以下五部分構(gòu)成:

1. 輸入層

輸入層是整個(gè)神經(jīng)網(wǎng)絡(luò)的輸入,在圖像處理中,輸入一般代表一張圖片的像素矩陣。在上圖中,最左側(cè)的三維矩陣就代表一張圖片。三維矩陣的長(zhǎng)和寬代表圖像的大小,深度代表了圖像的色彩通道。從輸入層開始,卷積神經(jīng)網(wǎng)絡(luò)通過(guò)不同的神經(jīng)網(wǎng)絡(luò)結(jié)構(gòu)將上一層的三維矩陣轉(zhuǎn)化為下一層的三維矩陣,知道最后的全連接層。

2. 卷積層

卷積層是卷積神經(jīng)網(wǎng)絡(luò)中最重要的部分。卷積層中每一個(gè)節(jié)點(diǎn)的輸入只是上一層神經(jīng)網(wǎng)絡(luò)的一小塊,這個(gè)小塊常用的大小有3?3或5?5,卷積層試圖將神經(jīng)網(wǎng)絡(luò)中的每個(gè)小塊進(jìn)行更加深入的分析從而抽象得到更高層次的特征,一般來(lái)說(shuō)經(jīng)過(guò)卷積層處理過(guò)的節(jié)點(diǎn)矩陣會(huì)變得更深。

3. 池化層

池化層神經(jīng)網(wǎng)絡(luò)不會(huì)改變?nèi)S矩陣的深度,但是它可以縮小矩陣的大小。池化操作可以認(rèn)為是將一張分辨率較高的圖片轉(zhuǎn)化為分辨率較低的圖片。池化層可以進(jìn)一步縮小最后全連接層中節(jié)點(diǎn)的個(gè)數(shù),從而達(dá)到減少整個(gè)神經(jīng)網(wǎng)絡(luò)中參數(shù)的目的。

4. 全連接層

經(jīng)過(guò)多輪卷積層和池化層的處理之后,卷積神經(jīng)網(wǎng)絡(luò)的最后一般會(huì)是由1-2個(gè)全連接層來(lái)給出最后的分類結(jié)果。經(jīng)過(guò)幾輪卷積層和池化層處理之后,可以認(rèn)為圖像中的信息已經(jīng)被抽象成了信息含量更高的特征。 可以將卷積和池化層看成特征提取的過(guò)程,提取完成之后,仍然需要使用全連接層來(lái)完成分類任務(wù)。

5. Softmax層(pooling層)

Softmax層主要用于分類問(wèn)題,通過(guò)softmax可以得到當(dāng)前樣例屬于不同種類的概率分布情況。

6.3 卷積神經(jīng)網(wǎng)絡(luò)常用結(jié)構(gòu)

6.3.1 卷積層

TensorFlow文檔中將下圖的部分被稱為“過(guò)濾器”或“內(nèi)核”,過(guò)濾器可以將當(dāng)前層神經(jīng)網(wǎng)絡(luò)上的一個(gè)子節(jié)點(diǎn)矩陣轉(zhuǎn)化為下一層神經(jīng)網(wǎng)絡(luò)上的一個(gè)單位節(jié)點(diǎn)矩陣(長(zhǎng)和寬都為1,但深度不限的節(jié)點(diǎn)矩陣)。

  • 過(guò)濾器:

  • 常用的過(guò)濾器的大小為 3*3 或 5*5 的,過(guò)濾器處理的矩陣深度和當(dāng)前車網(wǎng)絡(luò)節(jié)點(diǎn)矩陣的深度一致。
  • 尺寸:過(guò)濾器輸入節(jié)點(diǎn)矩陣的大小
  • 深度:輸出節(jié)點(diǎn)矩陣的深度
  • 上圖中,左側(cè)小矩陣的尺寸為過(guò)濾器的尺寸,右側(cè)單位矩陣的深度為過(guò)濾器的深度。
  • 前向傳播過(guò)程:通過(guò)左側(cè)小矩陣的節(jié)點(diǎn)計(jì)算出右側(cè)單位矩陣中節(jié)點(diǎn)的過(guò)程
  • 過(guò)濾器的前向傳播
    卷積層結(jié)構(gòu)的前向傳播過(guò)程就是通過(guò)將一個(gè)過(guò)濾器從神經(jīng)網(wǎng)絡(luò)當(dāng)前層的左上角移動(dòng)到右下角,并且在移動(dòng)過(guò)程中計(jì)算每一個(gè)對(duì)應(yīng)的單位矩陣得到的。

    傳播過(guò)程:左上角右上角左下角右下角

  • 全零填充:為了避免尺寸變化,可以使用“全零填充”,可以使得前向傳播后兩矩陣大小不變。

  • 設(shè)置不同的步長(zhǎng):也可以調(diào)整卷積后矩陣的大小

  • 參數(shù)共享:每一個(gè)卷積層中使用的濾波器中的參數(shù)都是一樣的(很重要的性質(zhì))

  • 使得圖像上的內(nèi)容不受位置的影響,因?yàn)橐环鶊D上的濾波器是相同的,無(wú)論“1”出現(xiàn)在圖中的哪個(gè)位置,濾波的結(jié)果都是一樣的。

  • 很大程度上減少神經(jīng)網(wǎng)絡(luò)的參數(shù)

  • 示例:全零填充、步長(zhǎng)為2的卷積層前向傳播過(guò)程


左上角的計(jì)算方式:

ReLU(0×1+0×(?1)+0×0+1×2+1)=ReLU(3)=3ReLU(0×1+0×(?1)+0×0+1×2+1)=ReLU(3)=3

  • TensorFlow實(shí)現(xiàn)卷積神經(jīng)網(wǎng)絡(luò)

1.創(chuàng)建濾波器的權(quán)值和偏置

filter_weight=tf.get_variable('weights',[5,5,3,16],initializer=tf.truncated_initializer(stddev=0.1))# t通過(guò)tf.get_variable的方式創(chuàng)建濾波器的權(quán)值和偏置# 聲明一個(gè)4維矩陣,前面兩個(gè)是濾波器尺寸、第三個(gè)表示當(dāng)前層深度、第四個(gè)表示過(guò)濾器的深度(也就是卷積核個(gè)數(shù)) biases=tf.get_variable('biases',[16],initializer=tf.constant_initializer(0.1))# 當(dāng)前層矩陣上不同位置的偏置項(xiàng)也是共享的,所以偏置項(xiàng)個(gè)數(shù)=下一層深度,本例為16

2.實(shí)現(xiàn)卷積層的前向傳播

conv=tf.nn.conv2d(input,filter_weight,strides=[1,1,1,1],padding='SAME')# tf.nn.conv2提供了一個(gè)非常方便的函數(shù)來(lái)實(shí)現(xiàn)卷積層的前向傳播# 第一個(gè)輸入:當(dāng)前層節(jié)點(diǎn)矩陣# (比如輸入層,input[0,:,:,:]表示輸入第一張圖像,input[1,:,:,:]表示輸入第二張圖像# 第二個(gè)參數(shù):卷積層的權(quán)重# 第三個(gè)參數(shù)不同維度上的步長(zhǎng)(第一維和最后一維要求一定是1,因?yàn)椴介L(zhǎng)只對(duì)矩陣的長(zhǎng)和寬有效)# 第四個(gè)參數(shù):填充的方法,可選'SAME'(全0填充)/'VALID'(不填充)

3.加上偏置項(xiàng)

bias=tf.nn.bias_add(conv,biases)# tf.nn.bias_add提供了一個(gè)方便的函數(shù)給每個(gè)節(jié)點(diǎn)加上偏置項(xiàng)# 不直接使用加法:因?yàn)榫仃嚿喜煌恢蒙系墓?jié)點(diǎn)都需要加上相同的偏置項(xiàng)

4.激活

actived_conv=tf.nn.relu(bias)# 將計(jì)算結(jié)果通過(guò)ReLU函數(shù)激活

6.3.2 池化層

  • 作用:

  • 減少參數(shù)
  • 防止過(guò)擬合
  • 獲得平移不變性
  • 常用池化類型:

  • 最大池化
  • 平均池化
  • 池化層的作用范圍:

  • 只影響一個(gè)深度上的節(jié)點(diǎn)
  • 在長(zhǎng)、寬、深這三個(gè)維度都要進(jìn)行移動(dòng)

  • TensorFlow實(shí)現(xiàn)最大池化層的前向傳播
pool = tf.nn.max_pool(actived_conv,ksize[1,3,3,1],strides=[1,2,2,1],padding='SAME')# 第一個(gè)參數(shù):當(dāng)前層節(jié)點(diǎn)矩陣# 第二個(gè)參數(shù):過(guò)濾器尺寸# 給出的是一個(gè)長(zhǎng)度為4的一位數(shù)組,但數(shù)組的首位和末位必須為1# 意味著池化層的過(guò)濾器是不可以跨過(guò)不同樣例或節(jié)點(diǎn)矩陣深度的# 第三個(gè)參數(shù):步長(zhǎng),第一維和最后一維必須為1,即池化層不能減少節(jié)點(diǎn)矩陣的深度或者輸入樣例的個(gè)數(shù)# 第四個(gè)參數(shù):填充方法,'SAME'表示全0填充,'VALID'表示不填充
  • TensorFlow實(shí)現(xiàn)平均池化層的前向傳播
pool = tf.nn.avg_pool(actived_conv,ksize[1,3,3,1],strides=[1,2,2,1],padding='SAME')# 第一個(gè)參數(shù):當(dāng)前層節(jié)點(diǎn)矩陣# 第二個(gè)參數(shù):過(guò)濾器尺寸# 給出的是一個(gè)長(zhǎng)度為4的一維數(shù)組,但數(shù)組的首位和末位必須為1# 意味著池化層的過(guò)濾器是不可以跨過(guò)不同樣例或節(jié)點(diǎn)矩陣深度的# 第三個(gè)參數(shù):步長(zhǎng),第一維和最后一維必須為1,即池化層不能減少節(jié)點(diǎn)矩陣的深度或者輸入樣例的個(gè)數(shù)# 第四個(gè)參數(shù):填充方法,'SAME'表示全0填充,'VALID'表示不填充

卷積層、池化層樣例

# 《TensorFlow實(shí)戰(zhàn)Google深度學(xué)習(xí)框架》06 圖像識(shí)別與卷積神經(jīng)網(wǎng)絡(luò) # win10 Tensorflow1.0.1 python3.5.3 # CUDA v8.0 cudnn-8.0-windows10-x64-v5.1 # filename:ts06.01.py # 卷積層、池化層樣例import tensorflow as tf import numpy as np# 1. 輸入矩陣 M = np.array([[[1],[-1],[0]],[[-1],[2],[1]],[[0],[2],[-2]]]) print("Matrix shape is: ",M.shape) # Matrix shape is: (3, 3, 1)# 2. 定義卷積過(guò)濾器, 深度為1 filter_weight = tf.get_variable('weights', [2, 2, 1, 1], initializer = tf.constant_initializer([[1, -1],[0, 2]])) biases = tf.get_variable('biases', [1], initializer = tf.constant_initializer(1))# 3. 調(diào)整輸入的格式符合TensorFlow的要求 M = np.asarray(M, dtype='float32') M = M.reshape(1, 3, 3, 1)# 4. 計(jì)算矩陣通過(guò)卷積層過(guò)濾器和池化層過(guò)濾器計(jì)算后的結(jié)果 x = tf.placeholder('float32', [1, None, None, 1]) conv = tf.nn.conv2d(x, filter_weight, strides=[1, 2, 2, 1], padding='SAME') bias = tf.nn.bias_add(conv, biases) pool = tf.nn.avg_pool(x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME') with tf.Session() as sess:tf.global_variables_initializer().run()convoluted_M = sess.run(bias, feed_dict={x: M})pooled_M = sess.run(pool, feed_dict={x: M})print("convoluted_M: \n", convoluted_M)print("pooled_M: \n", pooled_M)

輸出:

Matrix shape is: (3, 3, 1) convoluted_M: [[[[ 7.],[ 1.]][[-1.],[-1.]]]]pooled_M: [[[[ 0.25],[ 0.5 ]][[ 1. ],[-2. ]]]]

6.4 經(jīng)典卷積神經(jīng)網(wǎng)絡(luò)模型

6.4.1 LeNet-5模型

Yann LeCun 教授于1998年提出,是第一個(gè)成功用于數(shù)字識(shí)別的卷積神經(jīng)網(wǎng)絡(luò),在mnist數(shù)據(jù)集上,可以達(dá)到99.2%的效果,共有7層,如下圖所示。

輸入原始圖像的大小是32×32

1. 卷積層

輸入:原始圖像的像素(32*32*1)

過(guò)濾器:尺寸為5*5,深度為6,不使用全0填充,步長(zhǎng)為1

輸出:尺寸為 32-5+1=28,深度為6

參數(shù)個(gè)數(shù):5*5*1*6+6=156,

下一層節(jié)點(diǎn)矩陣的節(jié)點(diǎn):28*28*6=4704,每個(gè)節(jié)點(diǎn)和5*5=25 個(gè)當(dāng)前層節(jié)點(diǎn)相連

本層卷積層共有連接個(gè)數(shù):4704*(25+1)=122304

2. 池化層

輸入:第一層的輸出,是一個(gè)28*28*6的節(jié)點(diǎn)矩陣

過(guò)濾器:大小為2*2,長(zhǎng)、寬、步長(zhǎng)都為2

輸出:14*14*6

3. 卷積層

輸入:14*14*6

過(guò)濾器:大小為5*5,深度為16,不使用0填充,步長(zhǎng)為1

輸出:10*10*16,按標(biāo)準(zhǔn)的卷積層,本層應(yīng)該有5*5*6*16+16=2416個(gè)參數(shù)

共有:10*10*16*(25+1)=41600個(gè)連接

4. 池化層

輸入:10*10*16

過(guò)濾器:大小為2*2,步長(zhǎng)為2

輸出:矩陣大小為5*5*16

5. 全連接層

輸入:5*5*16,本來(lái)論文中稱本層為卷積層,但是因?yàn)闉V波器大小為5*5,所以和全連接層沒有區(qū)別,之后就將其看成全連接層。如果將矩陣5*5*16拉成一個(gè)向量,則和第四章的無(wú)區(qū)別

輸出:節(jié)點(diǎn)個(gè)數(shù)為120

總共參數(shù):5*5*16*120+120個(gè)參數(shù)。

6. 全連接層

輸入:節(jié)點(diǎn)個(gè)數(shù)為120個(gè)

輸出:節(jié)點(diǎn)個(gè)數(shù)為84個(gè)

總共參數(shù):120*84+84=10164個(gè)

7. 全連接層

輸入:84個(gè)節(jié)點(diǎn)

輸出:10個(gè)節(jié)點(diǎn)

總共參數(shù):84*10+10=850個(gè)

代碼示例:

  • LeNet_inference.py
# 《TensorFlow實(shí)戰(zhàn)Google深度學(xué)習(xí)框架》06 圖像識(shí)別與卷積神經(jīng)網(wǎng)絡(luò) # win10 Tensorflow1.0.1 python3.5.3 # CUDA v8.0 cudnn-8.0-windows10-x64-v5.1 # filename:LeNet5_infernece.py # LeNet5前向傳播import tensorflow as tf# 1. 設(shè)定神經(jīng)網(wǎng)絡(luò)的參數(shù) INPUT_NODE = 784 OUTPUT_NODE = 10IMAGE_SIZE = 28 NUM_CHANNELS = 1 NUM_LABELS = 10CONV1_DEEP = 32 CONV1_SIZE = 5CONV2_DEEP = 64 CONV2_SIZE = 5FC_SIZE = 512# 2. 定義前向傳播的過(guò)程 def inference(input_tensor, train, regularizer):with tf.variable_scope('layer1-conv1'):conv1_weights = tf.get_variable("weight", [CONV1_SIZE, CONV1_SIZE, NUM_CHANNELS, CONV1_DEEP],initializer=tf.truncated_normal_initializer(stddev=0.1))conv1_biases = tf.get_variable("bias", [CONV1_DEEP],initializer=tf.constant_initializer(0.0))conv1 = tf.nn.conv2d(input_tensor, conv1_weights, strides=[1, 1, 1, 1],padding='SAME')relu1 = tf.nn.relu(tf.nn.bias_add(conv1, conv1_biases))with tf.name_scope("layer2-pool1"):pool1 = tf.nn.max_pool(relu1, ksize = [1,2,2,1],strides=[1,2,2,1],padding="SAME")with tf.variable_scope("layer3-conv2"):conv2_weights = tf.get_variable("weight", [CONV2_SIZE, CONV2_SIZE, CONV1_DEEP, CONV2_DEEP],initializer=tf.truncated_normal_initializer(stddev=0.1))conv2_biases = tf.get_variable("bias", [CONV2_DEEP],initializer=tf.constant_initializer(0.0))conv2 = tf.nn.conv2d(pool1, conv2_weights, strides=[1, 1, 1, 1], padding='SAME')relu2 = tf.nn.relu(tf.nn.bias_add(conv2, conv2_biases))with tf.name_scope("layer4-pool2"):pool2 = tf.nn.max_pool(relu2, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1],padding='SAME')pool_shape = pool2.get_shape().as_list()nodes = pool_shape[1] * pool_shape[2] * pool_shape[3]reshaped = tf.reshape(pool2, [pool_shape[0], nodes])with tf.variable_scope('layer5-fc1'):fc1_weights = tf.get_variable("weight", [nodes, FC_SIZE],initializer=tf.truncated_normal_initializer(stddev=0.1))if regularizer != None: tf.add_to_collection('losses', regularizer(fc1_weights))fc1_biases = tf.get_variable("bias", [FC_SIZE], initializer=tf.constant_initializer(0.1))fc1 = tf.nn.relu(tf.matmul(reshaped, fc1_weights) + fc1_biases)if train: fc1 = tf.nn.dropout(fc1, 0.5)with tf.variable_scope('layer6-fc2'):fc2_weights = tf.get_variable("weight", [FC_SIZE, NUM_LABELS],initializer=tf.truncated_normal_initializer(stddev=0.1))if regularizer != None: tf.add_to_collection('losses', regularizer(fc2_weights))fc2_biases = tf.get_variable("bias", [NUM_LABELS],initializer=tf.constant_initializer(0.1))logit = tf.matmul(fc1, fc2_weights) + fc2_biasesreturn logit
  • LeNet_train.py
# 《TensorFlow實(shí)戰(zhàn)Google深度學(xué)習(xí)框架》06 圖像識(shí)別與卷積神經(jīng)網(wǎng)絡(luò) # win10 Tensorflow1.0.1 python3.5.3 # CUDA v8.0 cudnn-8.0-windows10-x64-v5.1 # filename:LeNet5_train.py # LeNet5訓(xùn)練import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data import LeNet_inference import os import numpy as np# 1. 定義神經(jīng)網(wǎng)絡(luò)相關(guān)的參數(shù) BATCH_SIZE = 100 LEARNING_RATE_BASE = 0.01 LEARNING_RATE_DECAY = 0.99 REGULARIZATION_RATE = 0.0001 TRAINING_STEPS = 55000 MOVING_AVERAGE_DECAY = 0.99 MODEL_SAVE_PATH = "LeNet5_model/" # 在當(dāng)前目錄下存在LeNet5_model子文件夾 MODEL_NAME = "LeNet5_model"# 2. 定義訓(xùn)練過(guò)程 def train(mnist):# 定義輸出為4維矩陣的placeholderx = tf.placeholder(tf.float32, [BATCH_SIZE,LeNet_inference.IMAGE_SIZE,LeNet_inference.IMAGE_SIZE,LeNet_inference.NUM_CHANNELS],name='x-input')y_ = tf.placeholder(tf.float32, [None, LeNet_inference.OUTPUT_NODE], name='y-input')regularizer = tf.contrib.layers.l2_regularizer(REGULARIZATION_RATE)y = LeNet_inference.inference(x, True, regularizer)global_step = tf.Variable(0, trainable=False)# 定義損失函數(shù)、學(xué)習(xí)率、滑動(dòng)平均操作以及訓(xùn)練過(guò)程。variable_averages = tf.train.ExponentialMovingAverage(MOVING_AVERAGE_DECAY, global_step)variables_averages_op = variable_averages.apply(tf.trainable_variables())cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=y, labels=tf.argmax(y_, 1))cross_entropy_mean = tf.reduce_mean(cross_entropy)loss = cross_entropy_mean + tf.add_n(tf.get_collection('losses'))learning_rate = tf.train.exponential_decay(LEARNING_RATE_BASE,global_step,mnist.train.num_examples / BATCH_SIZE, LEARNING_RATE_DECAY,staircase=True)train_step = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss, global_step=global_step)with tf.control_dependencies([train_step, variables_averages_op]):train_op = tf.no_op(name='train')# 初始化TensorFlow持久化類。saver = tf.train.Saver()with tf.Session() as sess:tf.global_variables_initializer().run()for i in range(TRAINING_STEPS):xs, ys = mnist.train.next_batch(BATCH_SIZE)reshaped_xs = np.reshape(xs, (BATCH_SIZE,LeNet_inference.IMAGE_SIZE,LeNet_inference.IMAGE_SIZE,LeNet_inference.NUM_CHANNELS))_, loss_value, step = sess.run([train_op, loss, global_step], feed_dict={x: reshaped_xs, y_: ys})if i % 1000 == 0:print("After %d training step(s), loss on training batch is %g." % (step, loss_value))saver.save(sess, os.path.join(MODEL_SAVE_PATH, MODEL_NAME), global_step=global_step)# 3. 主程序入口 def main(argv=None):mnist = input_data.read_data_sets("MNIST_data", one_hot=True)train(mnist)if __name__ == '__main__':tf.app.run()

輸出:

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.gzAfter 1 training step(s), loss on training batch is 6.10953. After 1001 training step(s), loss on training batch is 0.801586. After 2001 training step(s), loss on training batch is 0.829287. After 3001 training step(s), loss on training batch is 0.655056. After 4001 training step(s), loss on training batch is 0.698159. After 5001 training step(s), loss on training batch is 0.744295. After 6001 training step(s), loss on training batch is 0.657604. After 7001 training step(s), loss on training batch is 0.697003. After 8001 training step(s), loss on training batch is 0.685206. After 9001 training step(s), loss on training batch is 0.651352. After 10001 training step(s), loss on training batch is 0.729663. After 11001 training step(s), loss on training batch is 0.666927. After 12001 training step(s), loss on training batch is 0.65114. After 13001 training step(s), loss on training batch is 0.648548. ...
  • LeNet_eval.py(測(cè)試該網(wǎng)絡(luò)在mnist的正確率,達(dá)到99.4%,巨幅高于第五章的98.4%)
# 《TensorFlow實(shí)戰(zhàn)Google深度學(xué)習(xí)框架》06 圖像識(shí)別與卷積神經(jīng)網(wǎng)絡(luò) # win10 Tensorflow1.0.1 python3.5.3 # CUDA v8.0 cudnn-8.0-windows10-x64-v5.1 # filename:LeNet5_eval.py # 測(cè)試import time import math import tensorflow as tf import numpy as np from tensorflow.examples.tutorials.mnist import input_data import LeNet5_infernece import LeNet5_traindef evaluate(mnist):with tf.Graph().as_default() as g:# 定義輸出為4維矩陣的placeholderx = tf.placeholder(tf.float32, [mnist.test.num_examples,#LeNet5_train.BATCH_SIZE,LeNet5_infernece.IMAGE_SIZE,LeNet5_infernece.IMAGE_SIZE,LeNet5_infernece.NUM_CHANNELS],name='x-input')y_ = tf.placeholder(tf.float32, [None, LeNet5_infernece.OUTPUT_NODE], name='y-input')validate_feed = {x: mnist.test.images, y_: mnist.test.labels}global_step = tf.Variable(0, trainable=False)regularizer = tf.contrib.layers.l2_regularizer(LeNet5_train.REGULARIZATION_RATE)y = LeNet5_infernece.inference(x, False, regularizer)correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))variable_averages = tf.train.ExponentialMovingAverage(LeNet5_train.MOVING_AVERAGE_DECAY)variables_to_restore = variable_averages.variables_to_restore()saver = tf.train.Saver(variables_to_restore)#n = math.ceil(mnist.test.num_examples / LeNet5_train.BATCH_SIZE)n = math.ceil(mnist.test.num_examples / mnist.test.num_examples)for i in range(n):with tf.Session() as sess:ckpt = tf.train.get_checkpoint_state(LeNet5_train.MODEL_SAVE_PATH)if ckpt and ckpt.model_checkpoint_path:saver.restore(sess, ckpt.model_checkpoint_path)global_step = ckpt.model_checkpoint_path.split('/')[-1].split('-')[-1]xs, ys = mnist.test.next_batch(mnist.test.num_examples)#xs, ys = mnist.test.next_batch(LeNet5_train.BATCH_SIZE)reshaped_xs = np.reshape(xs, (mnist.test.num_examples,#LeNet5_train.BATCH_SIZE,LeNet5_infernece.IMAGE_SIZE,LeNet5_infernece.IMAGE_SIZE,LeNet5_infernece.NUM_CHANNELS))accuracy_score = sess.run(accuracy, feed_dict={x:reshaped_xs, y_:ys})print("After %s training step(s), test accuracy = %g" % (global_step, accuracy_score))else:print('No checkpoint file found')return# 主程序 def main(argv=None):mnist = input_data.read_data_sets("../../../datasets/MNIST_data", one_hot=True)evaluate(mnist)if __name__ == '__main__':tf.app.run()

LeNet-5模型的缺點(diǎn)
不能很好的解決所有問(wèn)題,比如類似ImageNet的復(fù)雜數(shù)據(jù)集

如何設(shè)計(jì)卷積神經(jīng)網(wǎng)絡(luò)架構(gòu)
該正則表達(dá)公式總結(jié)了經(jīng)典的用于圖像分類問(wèn)題的卷積神經(jīng)網(wǎng)絡(luò)架構(gòu)

輸入層(卷積層+池化層?)+全連接層+
其中:

  • +表示一層或多層
  • “池化層?”表示沒有或一層池化層,因?yàn)橛械木W(wǎng)絡(luò)是通過(guò)直接調(diào)整卷積層步長(zhǎng)來(lái)完成的參數(shù)減少
  • 多倫卷積核池化之后,輸出層之前會(huì)有1~2個(gè)全連接層
  • LeNet-5的正則表達(dá):

    輸入層卷積層池化層卷積層池化層全連接層全連接層輸出層

    從VGGNet觀察正則表達(dá)式的特點(diǎn):

  • convX-Y:濾波器的邊長(zhǎng)為X,深度為Y

  • VGGNet中的濾波器的邊長(zhǎng)基本都為3或1

  • LeNet-5中使用了大小為5*5的濾波器,一般都不會(huì)超過(guò)5,但也有的設(shè)置為7*7,甚至11*11的

  • 在濾波器的深度選擇上,大部分都采用逐層遞增的方式,VGG中,每經(jīng)過(guò)一個(gè)池化層,濾波器的深度*2,

  • 卷積層的步長(zhǎng)一般為2,但也有例外(使用2或3)

  • 池化層配置相對(duì)簡(jiǎn)單,用的最多的是最大池化層,邊長(zhǎng)一般為2或3,步長(zhǎng)一般為2或3

  • 6.4.2 Inception模型

    已知濾波器的大小可選,但是沒有先驗(yàn)知識(shí)幫助我們?nèi)ミx擇其大小,所以Inception模型將不同尺寸的濾波器的濾波結(jié)果通過(guò)并聯(lián)的方式結(jié)合在一起,即將得到的矩陣拼接起來(lái)。

    Inception模型會(huì)使用不同尺寸的濾波器處理矩陣,使用全0填充和步長(zhǎng)為1的方法獲得的特征圖譜大小是相同的,不會(huì)影響矩陣的拼接。

    Inception-v3模型共有46層,由11個(gè)Inception模塊構(gòu)成,上圖中方框標(biāo)注的就是一個(gè)模塊,Inception-v3模型有96個(gè)卷積層,直接使用上文的TensorFlow模型會(huì)非常冗長(zhǎng),所以此處介紹TensorFlow-Slim工具來(lái)更加簡(jiǎn)潔的實(shí)現(xiàn)同樣結(jié)構(gòu)的神經(jīng)網(wǎng)絡(luò)代碼量。

    1.直接使用TensorFlow原始API實(shí)現(xiàn)卷積層

    with tf.variable_scope(scope_name):weights=tf.get_variable("weight",...)biases=tf.get_variable("bias",...)conv=tf.nn.conv2d(...)relu=tf.nn.relu(tf.nn.bias_add(conv,biases))

    2.使用TensorFlow-Slim實(shí)現(xiàn)卷積層

    tf.contrib.slim.conv2d (inputs,num_outputs,#[卷積核個(gè)數(shù)]kernel_size,#[高度,寬度]stride=1,#步長(zhǎng)padding='SAME',#VALID

    存在于tensorflow.contrib的庫(kù)中,導(dǎo)入方法:import tensorflow.contrib.slim as slim

    net=slim.conv2d(input,32,[3,3]) # 可以在一行中實(shí)現(xiàn)一個(gè)卷積層的前向傳播算法 # 第一個(gè)參數(shù):輸入節(jié)點(diǎn)矩陣 # 第二個(gè)參數(shù):當(dāng)前卷積層過(guò)濾器的深度 # 第三個(gè)參數(shù):過(guò)濾器的尺寸 # 可選步長(zhǎng)、填充、激活函數(shù)、變量命名空間等

    6.5 卷積神經(jīng)網(wǎng)絡(luò)實(shí)現(xiàn)遷移學(xué)習(xí)

    6.5.1 遷移學(xué)習(xí)的介紹

    從上表可以看出,隨著模型層數(shù)及復(fù)雜度的增加,模型在ImageNet上的錯(cuò)誤率也隨之降低,然而訓(xùn)練神經(jīng)網(wǎng)絡(luò)需要非常多的標(biāo)注數(shù)據(jù),ImageNet數(shù)據(jù)集中有120萬(wàn)標(biāo)注圖像,所以才能使得152層的ResNet模型達(dá)到分類的96.5%的正確率,實(shí)際中很難收集到如此多的標(biāo)記數(shù)據(jù),即使收集也會(huì)花費(fèi)很多的人力物力,并且海量的訓(xùn)練數(shù)據(jù)使得復(fù)雜的卷積神經(jīng)網(wǎng)絡(luò)的訓(xùn)練需要幾天甚至幾周,為了解決標(biāo)注數(shù)據(jù)和訓(xùn)練時(shí)間的問(wèn)題,提出了遷移學(xué)習(xí)。

    遷移學(xué)習(xí):將一個(gè)問(wèn)題上訓(xùn)練好的模型通過(guò)簡(jiǎn)單的調(diào)整使其適用于一個(gè)新的問(wèn)題。比如可以保留訓(xùn)練好的Inception-v3模型中所有卷積層的參數(shù),只是替換最后一層全連接層,可以解決一個(gè)新的圖像分類問(wèn)題。

    瓶頸層:在最后這一層全連接層之前的網(wǎng)絡(luò)層稱之為瓶頸層。

    • 將新的圖像通過(guò)訓(xùn)練好的卷積神經(jīng)網(wǎng)絡(luò)直到瓶頸層的過(guò)程可以看成是對(duì)圖像進(jìn)行特征提取的過(guò)程。
    • 可以認(rèn)為瓶頸層的輸出節(jié)點(diǎn)向量可以被作為任何圖像的一個(gè)更加精簡(jiǎn)且表達(dá)能力更強(qiáng)的特征向量,于是可以用該訓(xùn)練好的神經(jīng)網(wǎng)絡(luò)在新的數(shù)據(jù)集上完成對(duì)圖像特征的提取。
    • 再將提取到的特征作為輸入來(lái)訓(xùn)練一個(gè)新的單層全連接神經(jīng)網(wǎng)絡(luò)處理新的分類問(wèn)題

    遷移學(xué)習(xí)相比重新訓(xùn)練的優(yōu)缺點(diǎn):

    • 缺點(diǎn):效果不如完全重新訓(xùn)練
    • 優(yōu)點(diǎn):需要的訓(xùn)練時(shí)間和訓(xùn)練樣本數(shù)要遠(yuǎn)遠(yuǎn)小于訓(xùn)練完整的模型

    代碼實(shí)現(xiàn):

    # 《TensorFlow實(shí)戰(zhàn)Google深度學(xué)習(xí)框架》06 圖像識(shí)別與卷積神經(jīng)網(wǎng)絡(luò) # win10 Tensorflow1.0.1 python3.5.3 # CUDA v8.0 cudnn-8.0-windows10-x64-v5.1 # filename:ts06.03.py # 遷移學(xué)習(xí)# 以下實(shí)驗(yàn)需要如下資源 # 源碼及資源位置:git clone https://github.com/caicloud/tensorflow-tutorial.git # 需要tensorflow-tutorial.git庫(kù)中的flower_photos和inception_dec_2015 # tensorflow-tutorial\Deep_Learning_with_TensorFlow\datasets\flower_photos # tensorflow-tutorial\Deep_Learning_with_TensorFlow\datasets\inception_dec_2015import glob import os.path import random import numpy as np import tensorflow as tf from tensorflow.python.platform import gfile# 1. 模型和樣本路徑的設(shè)置 # inception-v3模型瓶頸層的節(jié)點(diǎn)數(shù) BOTTLENECK_TENSOR_SIZE = 2048# inception-v3模型中代表瓶頸層結(jié)果的張量名稱,谷歌提供的inception-v3模型中,這個(gè)張量名稱就是'pool_3/_reshape:0' # 訓(xùn)練過(guò)程中,可以利用tensor.name來(lái)獲取張量的名稱 BOTTLENECK_TENSOR_NAME = 'pool_3/_reshape:0'# 圖像輸入張量所對(duì)應(yīng)的名稱 JPEG_DATA_TENSOR_NAME = 'DecodeJpeg/contents:0'# 保存的模型文件目錄 MODEL_DIR = '../../datasets/inception_dec_2015' # 下載的谷歌訓(xùn)練好的inception-v3模型文件名 MODEL_FILE= 'tensorflow_inception_graph.pb'# 因?yàn)橐粋€(gè)訓(xùn)練數(shù)據(jù)會(huì)被使用多次,所以可以將原始圖像通過(guò)inception-v3模型計(jì)算得到的特征向量保存在文件中, # 以免重復(fù)計(jì)算,下面是這些文件的存放地址。 CACHE_DIR = '../../datasets/bottleneck'# 圖片數(shù)據(jù)文件夾 # 該文件夾中每一個(gè)子文件夾代表一個(gè)需要區(qū)分的類別,每個(gè)子文件夾中存放了對(duì)應(yīng)類別的圖片 INPUT_DATA = '../../datasets/flower_photos'# 驗(yàn)證集百分比 VALIDATION_PERCENTAGE = 10 # 測(cè)試集百分比 TEST_PERCENTAGE = 10# 2. 神經(jīng)網(wǎng)絡(luò)參數(shù)的設(shè)置 LEARNING_RATE = 0.01 STEPS = 4000 BATCH = 100# 3. 把樣本中所有的圖片列表并按訓(xùn)練、驗(yàn)證、測(cè)試數(shù)據(jù)分開 # testing_percentage:測(cè)試數(shù)據(jù)集的大小 # validation_percentage:驗(yàn)證數(shù)據(jù)集的大小 def create_image_lists(testing_percentage, validation_percentage):# 定義一個(gè)result字典,key存儲(chǔ)類別名稱, 與key對(duì)應(yīng)的value也是一個(gè)字典,存儲(chǔ)所有該類的圖片名稱result = {}# 獲取當(dāng)前目錄下所有的子目錄sub_dirs = [x[0] for x in os.walk(INPUT_DATA)]is_root_dir = Truefor sub_dir in sub_dirs:if is_root_dir:is_root_dir = Falsecontinueextensions = ['jpg', 'jpeg', 'JPG', 'JPEG']file_list = []dir_name = os.path.basename(sub_dir)for extension in extensions:file_glob = os.path.join(INPUT_DATA, dir_name, '*.' + extension)file_list.extend(glob.glob(file_glob))if not file_list: continuelabel_name = dir_name.lower()# 初始化training_images = []testing_images = []validation_images = []for file_name in file_list:base_name = os.path.basename(file_name)# 隨機(jī)劃分?jǐn)?shù)據(jù)chance = np.random.randint(100)if chance < validation_percentage:validation_images.append(base_name)elif chance < (testing_percentage + validation_percentage):testing_images.append(base_name)else:training_images.append(base_name)result[label_name] = {'dir': dir_name,'training': training_images,'testing': testing_images,'validation': validation_images,}return result# 4. 定義函數(shù)通過(guò)類別名稱、所屬數(shù)據(jù)集和圖片編號(hào)獲取一張圖片的地址 def get_image_path(image_lists, image_dir, label_name, index, category):label_lists = image_lists[label_name]category_list = label_lists[category]mod_index = index % len(category_list)base_name = category_list[mod_index]sub_dir = label_lists['dir']full_path = os.path.join(image_dir, sub_dir, base_name)return full_path# 5. 定義函數(shù)獲取Inception-v3模型處理之后的特征向量的文件地址 def get_bottleneck_path(image_lists, label_name, index, category):return get_image_path(image_lists, CACHE_DIR, label_name, index, category) + '.txt'# 6. 定義函數(shù)使用加載的訓(xùn)練好的Inception-v3模型處理一張圖片,得到這個(gè)圖片的特征向量 # 該過(guò)程實(shí)際上就是將當(dāng)前圖片作為輸入九三瓶頸張量的值,這個(gè)瓶頸張量的值就是該圖像的新的特征向量 def run_bottleneck_on_image(sess, image_data, image_data_tensor, bottleneck_tensor):bottleneck_values = sess.run(bottleneck_tensor, {image_data_tensor: image_data})# 將四維數(shù)組壓縮為一個(gè)特征向量bottleneck_values = np.squeeze(bottleneck_values)return bottleneck_values# 7. 定義函數(shù)會(huì)先試圖尋找已經(jīng)計(jì)算且保存下來(lái)的特征向量,如果找不到則先計(jì)算這個(gè)特征向量,然后保存到文件 def get_or_create_bottleneck(sess, image_lists, label_name, index, category, jpeg_data_tensor, bottleneck_tensor):label_lists = image_lists[label_name]sub_dir = label_lists['dir']sub_dir_path = os.path.join(CACHE_DIR, sub_dir)if not os.path.exists(sub_dir_path): os.makedirs(sub_dir_path)bottleneck_path = get_bottleneck_path(image_lists, label_name, index, category)if not os.path.exists(bottleneck_path):image_path = get_image_path(image_lists, INPUT_DATA, label_name, index, category)image_data = gfile.FastGFile(image_path, 'rb').read()bottleneck_values = run_bottleneck_on_image(sess, image_data, jpeg_data_tensor, bottleneck_tensor)bottleneck_string = ','.join(str(x) for x in bottleneck_values)with open(bottleneck_path, 'w') as bottleneck_file:bottleneck_file.write(bottleneck_string)else:with open(bottleneck_path, 'r') as bottleneck_file:bottleneck_string = bottleneck_file.read()bottleneck_values = [float(x) for x in bottleneck_string.split(',')]return bottleneck_values# 8. 這個(gè)函數(shù)隨機(jī)獲取一個(gè)batch的圖片作為訓(xùn)練數(shù)據(jù) def get_random_cached_bottlenecks(sess, n_classes, image_lists, how_many, category, jpeg_data_tensor, bottleneck_tensor):bottlenecks = []ground_truths = []for _ in range(how_many):label_index = random.randrange(n_classes)label_name = list(image_lists.keys())[label_index]image_index = random.randrange(65536)bottleneck = get_or_create_bottleneck(sess, image_lists, label_name, image_index, category, jpeg_data_tensor, bottleneck_tensor)ground_truth = np.zeros(n_classes, dtype=np.float32)ground_truth[label_index] = 1.0bottlenecks.append(bottleneck)ground_truths.append(ground_truth)return bottlenecks, ground_truths# 9. 這個(gè)函數(shù)獲取全部的測(cè)試數(shù)據(jù),并計(jì)算正確率 def get_test_bottlenecks(sess, image_lists, n_classes, jpeg_data_tensor, bottleneck_tensor):bottlenecks = []ground_truths = []label_name_list = list(image_lists.keys())for label_index, label_name in enumerate(label_name_list):category = 'testing'for index, unused_base_name in enumerate(image_lists[label_name][category]):bottleneck = get_or_create_bottleneck(sess, image_lists, label_name, index, category,jpeg_data_tensor, bottleneck_tensor)ground_truth = np.zeros(n_classes, dtype=np.float32)ground_truth[label_index] = 1.0bottlenecks.append(bottleneck)ground_truths.append(ground_truth)return bottlenecks, ground_truths# 10. 定義主函數(shù) def main():image_lists = create_image_lists(TEST_PERCENTAGE, VALIDATION_PERCENTAGE)n_classes = len(image_lists.keys())# 讀取已經(jīng)訓(xùn)練好的Inception-v3模型。with gfile.FastGFile(os.path.join(MODEL_DIR, MODEL_FILE), 'rb') as f:graph_def = tf.GraphDef()graph_def.ParseFromString(f.read())bottleneck_tensor, jpeg_data_tensor = tf.import_graph_def(graph_def, return_elements=[BOTTLENECK_TENSOR_NAME, JPEG_DATA_TENSOR_NAME])# 定義新的神經(jīng)網(wǎng)絡(luò)輸入bottleneck_input = tf.placeholder(tf.float32, [None, BOTTLENECK_TENSOR_SIZE], name='BottleneckInputPlaceholder')ground_truth_input = tf.placeholder(tf.float32, [None, n_classes], name='GroundTruthInput')# 定義一層全鏈接層with tf.name_scope('final_training_ops'):weights = tf.Variable(tf.truncated_normal([BOTTLENECK_TENSOR_SIZE, n_classes], stddev=0.001))biases = tf.Variable(tf.zeros([n_classes]))logits = tf.matmul(bottleneck_input, weights) + biasesfinal_tensor = tf.nn.softmax(logits)# 定義交叉熵?fù)p失函數(shù)。cross_entropy = tf.nn.softmax_cross_entropy_with_logits(logits=logits, labels=ground_truth_input)cross_entropy_mean = tf.reduce_mean(cross_entropy)train_step = tf.train.GradientDescentOptimizer(LEARNING_RATE).minimize(cross_entropy_mean)# 計(jì)算正確率。with tf.name_scope('evaluation'):correct_prediction = tf.equal(tf.argmax(final_tensor, 1), tf.argmax(ground_truth_input, 1))evaluation_step = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))with tf.Session() as sess:init = tf.global_variables_initializer()sess.run(init)# 訓(xùn)練過(guò)程。for i in range(STEPS):train_bottlenecks, train_ground_truth = get_random_cached_bottlenecks(sess, n_classes, image_lists, BATCH, 'training', jpeg_data_tensor, bottleneck_tensor)sess.run(train_step,feed_dict={bottleneck_input: train_bottlenecks, ground_truth_input: train_ground_truth})if i % 100 == 0 or i + 1 == STEPS:validation_bottlenecks, validation_ground_truth = get_random_cached_bottlenecks(sess, n_classes, image_lists, BATCH, 'validation', jpeg_data_tensor, bottleneck_tensor)validation_accuracy = sess.run(evaluation_step, feed_dict={bottleneck_input: validation_bottlenecks, ground_truth_input: validation_ground_truth})print('Step %d: Validation accuracy on random sampled %d examples = %.1f%%' %(i, BATCH, validation_accuracy * 100))# 在最后的測(cè)試數(shù)據(jù)上測(cè)試正確率。test_bottlenecks, test_ground_truth = get_test_bottlenecks(sess, image_lists, n_classes, jpeg_data_tensor, bottleneck_tensor)test_accuracy = sess.run(evaluation_step, feed_dict={bottleneck_input: test_bottlenecks, ground_truth_input: test_ground_truth})print('Final test accuracy = %.1f%%' % (test_accuracy * 100))if __name__ == '__main__':tf.app.run()

    總結(jié)

    以上是生活随笔為你收集整理的TensorFlow:实战Google深度学习框架(五)图像识别与卷积神经网络的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。