學習筆記TF030:實現AlexNet

来源:http://www.cnblogs.com/libinggen/archive/2017/07/25/7231978.html
-Advertisement-
Play Games

ILSVRC(ImageNet Large Scale Visual Recognition Challenge)分類比賽。AlexNet 2012年冠軍(top-5錯誤率16.4%,額外數據15.3%,8層神經網路)。VGGNet 2014年亞軍(top-5錯誤率7.3%,19層神經網路)。Goo ...


ILSVRC(ImageNet Large Scale Visual Recognition Challenge)分類比賽。AlexNet 2012年冠軍(top-5錯誤率16.4%,額外數據15.3%,8層神經網路)。VGGNet 2014年亞軍(top-5錯誤率7.3%,19層神經網路)。Google Inception 2014年冠軍(top-5錯誤率6.7%,22層神經網路)。ResNet 2015年冠軍(top-5錯誤率3.57%,152層神經網路)。人眼錯誤率5.1%。捲積神經網路基本解決ImageNet數據集圖片分類問題。

ImageNet,2007年斯坦福大學李飛飛教授創辦,收集大量帶標註信息圖片數據供電腦視覺模型訓練。1500萬張標註高清圖片,22000類,100萬張標註圖片主要物體定位邊框。眼睛生物照相機,每200ms拍一張,3歲已經上億張。ImageNet下載互聯網10億張圖片,亞馬遜土耳其機器人平臺眾包標註過程,167個國家5萬名工作者篩選標註。每年ILSVRC比賽數據120萬張圖片,1000類標註。top-5、top-1分類錯誤率模型性能評測指標。

2012年,Hinton學生Alex Krizhevsky提出LeNet更深更寬版深度神經網路模型AlexNet。首次在CNN用ReLU、Dropout、LRN等Trick。GPU運算加速。開源GPU訓紅捲積神經網路CUDA代碼。6億3000萬連接,6000萬參數,65萬神經元,5個捲積層,3個捲積層後連最大池化層,3個全連接層。top-5錯誤率16.4%。第二名26.2%。神經網路低谷期後第一次發聲,確立深度學習(深度捲積網路)電腦視覺統治地位,推動深度學習語音識別、自然語言處理、強化學習領域拓展。

成功使用ReLU CNN激活函數,驗證較深網路效果超過Sigmoid,解決梯度彌散問題。訓練用Dropout隨機忽略部分神經元,避免模型過擬合。CNN用重疊最大池化,避免平均池化模糊化效果,步長比池化核尺寸小,池化層輸出重疊覆蓋,提升特征豐富性。LRN層,創建局部神經元活動競爭機制,響應較大值變更大,抑制其他反饋較小神經元,增強模型泛化能力。CUDA加速深度捲積網路訓練,並行計算大量矩陣,GPU通信方便,互相訪問顯存,只在網路某些層進行,控制通信性能損耗。數據增強,隨機從256x256原始圖像截取224x224區域,水平翻轉鏡像,增加(256-224)^2x2=2048倍數據量,減輕過擬合,提升泛化能力,預測取圖片四角加中間5個位置,左右翻轉,10張圖片,10次預測結果求均值,圖像RGB數據PCA處理,主成分標準差0.1高斯擾動,增加雜訊,錯誤率下降1%。

8個參數訓練層(不包括池化層、LRN層),前5捲積層,後3全連接層。最後一層1000類輸出Softmax層分類。LRN層在第1、2捲積層後,最大池化層在LRN層、最後捲積層後。ReLU激活函數在每個參數層後。

AlexNet超參數:
params AlexNext FLOPs
4M FC1000 4M
16M FC4096/ReLU 4M
37M FC4096/ReLU 37M
Max Pool 3x3s2
442K Conv 3x3s1,256/ReLU 74M
1.3M Conv 3x3s1,384/ReLU 112M
884K Conv 3x3s1,384/ReLU 149M
Max Pool 3x3s2
Local Response Norm
307K Conv 5x5s1,256/ReLU 223M
Max Pool 3x3s2
Local Response Norm
35K Conv 11x11s4,96/ReLU 105M

輸入圖片尺寸224x224,第一卷積層捲積核尺寸11x11,步長4,96個捲積核。LRN層。3x3 最大池化層,步長2。後續捲積核5x5或3x3,步長2。通過較小參數提取有效特征。

導入系統庫datetime、math、time,載入TensorFlow。

batch_size 32,num_batches 100,共測試100個batch數據。

定義網路結構顯示函數print_actications,捲積層或池化層輸出tensor尺寸。接受tensor輸入,顯示名稱(t.op.name)、tensor尺寸(t.get_shape.as_list())。

網路結構。定義inference函數,接受images輸入,返回最後一層pool5(第5個池化層)及parameters(模型參數)。多個捲積層、池化層。

第一卷積層conv1,TensorFlow name_scope,with tf.name_scope('conv1') as scope,scope內生成Variable自動命名為conv1/xxx,區分不同捲積層組件。定義第一卷積層,tf.truncated_normal截斷正態分佈函數(標準差0.1),初始化捲積核參數kernel。捲積核尺寸11x11,顏色通道3,捲積核64。tf.nn.conv2d捲積images,strides步長4x4(圖片每4x4區域只取樣一次,橫向間隔4,縱向間隔4,取樣捲積核尺寸11x11),padding模式SAME。捲積層biases全初始化0。tf.nn.bias_add,conv、biases加。用激活函數tf.nn.relu結果非線性。print_activations 列印最後輸出tensor conv1結構。可訓練參數kernel、biases添加parameters。

第一卷積層後添加LRN層、最大池化層。tf.nn.lrn LRN處理前面輸出tensor conv1,depth_radius 4,bias 1,alpha 0.001/9,beta 0.75。其他經典捲積神經網路放充LRN。LRN讓前饋、反饋速度下降到1/3。tf.nn.max_pool 最大池化處理前面輸出lrn1,尺寸 3x3,3x3像素塊降為1x1像素,取樣步長2x2,padding模式VALID,取樣不超過邊框,不填充邊界外點(SAME)。列印輸出結果pool1結構。

第二捲積層,捲積核尺寸5x5,輸入通道數 64(上一層輸出通道數,上一層捲積核數量),捲積核192,步長1,掃描全圖像素。

處理第二捲積層輸出conv2,先LRN處理,再最大池化。

第三捲積層,捲積核尺寸3x3,輸入通道數 192,捲積核 384,步長1。

第四捲積層,捲積核尺寸3x3,輸入通道數 384,捲積核 256,步長1。

第五捲積層,捲積核尺寸3x3,輸入通道數 256,捲積核 256,步長1。

最大池化層,返回池化層輸出pool5。捲積結束。

3個全連接層,隱含節點4096、4096、1000,計算量很小。

評估AlexNet每輪計算時間函數time_tensorflow_run。第一輸入TensorFlow Session,第二變數評測運算運算元,第三變數測試名稱。定義預熱輪數num_steps_burn_in=10,給程式熱身,頭幾輪迭代顯存載入、cache命中問題跳過,10輪迭代後計算時間。記錄總時間total_duration、平方和total_duration_squared,計算方差。

num_batches+num_steps_burn_in次迭代計算,time.time()記錄時間,session.run(target)執行每次迭代。初始熱身num_steps_burn_in次迭代後,每10輪迭代顯示當前迭代時間。每輪total_duration、total_duration_squared累加。

迴圈結束,計算每輪耗時均值mn、標準差sd,顯示結果。

主函數run_benchmark。with tf.Graph().as_default()定義預設Graph。tf.random_nomal函數構造正態頒上(標準差 0.1)隨機tensor,第一維度batch_size,每輪迭代樣本數,第二、三維度圖片尺寸image_size 224,第四維度圖片顏色通道數。inference函數構建整個AlexNet網路,最後池化層輸出pool5,訓練參數集合parameters。tf.Session()創建新Session,tf.global_variables_initializer()初始化所有參數。

AlexNet forward計算評測,time_tensorflow_run 統計運算時間,傳入target pool5,捲積網路最後池化層輸出。backward 訓練過程評測,最後輸出pool5設置優化目標loss。tf.nn.l2_loss計算,tf.gradients求loss所有模型參數梯度,模擬訓練過程,根據梯度更新參數。time_tensorflow_run統計backward運算時間,target求整個網路梯度gard。

執行主函數。

程式顯示三段結果。AlexNet網路結構、輸出tensor尺寸。forward計算時間,有LRN層每輪迭代時間0.026s,去除LRN層0.007s,對最終準確率影響不大。backward運算時間,有LRN層每輪迭代時間0.078s,去除LRN層0.025s。backward運算耗時約forward三倍。

CNN訓練過程(backward計算)比較耗時,過很多遍數據,大量迭代。CNN瓶勁在訓練。TensorFlow已經支持iOS、Android,手機CPU做人臉識別、圖片分類非常方便、響應速度很快。

傳統機器學習模型適合學習小型數據集,大型數據集需要更大學習容量(Learning Capacity)模型,深度學習模型。捲積層參數量少,抽取特征能力非常強。

    from datetime import datetime
    import math
    import time
    import tensorflow as tf
    batch_size=32
    num_batches=100
    def print_activations(t):
        print(t.op.name, ' ', t.get_shape().as_list())
    def inference(images):
        parameters = []
        # conv1
        with tf.name_scope('conv1') as scope:
            kernel = tf.Variable(tf.truncated_normal([11, 11, 3, 64], dtype=tf.float32,
                                                 stddev=1e-1), name='weights')
            conv = tf.nn.conv2d(images, kernel, [1, 4, 4, 1], padding='SAME')
            biases = tf.Variable(tf.constant(0.0, shape=[64], dtype=tf.float32),
                             trainable=True, name='biases')
            bias = tf.nn.bias_add(conv, biases)
            conv1 = tf.nn.relu(bias, name=scope)
            print_activations(conv1)
            parameters += [kernel, biases]
      # pool1
        lrn1 = tf.nn.lrn(conv1, 4, bias=1.0, alpha=0.001 / 9.0, beta=0.75, name='lrn1')
        pool1 = tf.nn.max_pool(lrn1,
                           ksize=[1, 3, 3, 1],
                           strides=[1, 2, 2, 1],
                           padding='VALID',
                           name='pool1')
        print_activations(pool1)
      # conv2
        with tf.name_scope('conv2') as scope:
            kernel = tf.Variable(tf.truncated_normal([5, 5, 64, 192], dtype=tf.float32,
                                                 stddev=1e-1), name='weights')
            conv = tf.nn.conv2d(pool1, kernel, [1, 1, 1, 1], padding='SAME')
            biases = tf.Variable(tf.constant(0.0, shape=[192], dtype=tf.float32),
                             trainable=True, name='biases')
            bias = tf.nn.bias_add(conv, biases)
            conv2 = tf.nn.relu(bias, name=scope)
            parameters += [kernel, biases]
        print_activations(conv2)
      # pool2
        lrn2 = tf.nn.lrn(conv2, 4, bias=1.0, alpha=0.001 / 9.0, beta=0.75, name='lrn2')
        pool2 = tf.nn.max_pool(lrn2,
                           ksize=[1, 3, 3, 1],
                           strides=[1, 2, 2, 1],
                           padding='VALID',
                           name='pool2')
        print_activations(pool2)
      # conv3
        with tf.name_scope('conv3') as scope:
            kernel = tf.Variable(tf.truncated_normal([3, 3, 192, 384],
                                                 dtype=tf.float32,
                                                 stddev=1e-1), name='weights')
            conv = tf.nn.conv2d(pool2, kernel, [1, 1, 1, 1], padding='SAME')
            biases = tf.Variable(tf.constant(0.0, shape=[384], dtype=tf.float32),
                             trainable=True, name='biases')
            bias = tf.nn.bias_add(conv, biases)
            conv3 = tf.nn.relu(bias, name=scope)
            parameters += [kernel, biases]
            print_activations(conv3)
      # conv4
        with tf.name_scope('conv4') as scope:
            kernel = tf.Variable(tf.truncated_normal([3, 3, 384, 256],
                                                 dtype=tf.float32,
                                                 stddev=1e-1), name='weights')
            conv = tf.nn.conv2d(conv3, kernel, [1, 1, 1, 1], padding='SAME')
            biases = tf.Variable(tf.constant(0.0, shape=[256], dtype=tf.float32),
                             trainable=True, name='biases')
            bias = tf.nn.bias_add(conv, biases)
            conv4 = tf.nn.relu(bias, name=scope)
            parameters += [kernel, biases]
            print_activations(conv4)
      # conv5
        with tf.name_scope('conv5') as scope:
            kernel = tf.Variable(tf.truncated_normal([3, 3, 256, 256],
                                                 dtype=tf.float32,
                                                 stddev=1e-1), name='weights')
            conv = tf.nn.conv2d(conv4, kernel, [1, 1, 1, 1], padding='SAME')
            biases = tf.Variable(tf.constant(0.0, shape=[256], dtype=tf.float32),
                             trainable=True, name='biases')
            bias = tf.nn.bias_add(conv, biases)
            conv5 = tf.nn.relu(bias, name=scope)
            parameters += [kernel, biases]
            print_activations(conv5)
      # pool5
        pool5 = tf.nn.max_pool(conv5,
                           ksize=[1, 3, 3, 1],
                           strides=[1, 2, 2, 1],
                           padding='VALID',
                           name='pool5')
        print_activations(pool5)
        return pool5, parameters
    def time_tensorflow_run(session, target, info_string):
        num_steps_burn_in = 10
        total_duration = 0.0
        total_duration_squared = 0.0
        for i in range(num_batches + num_steps_burn_in):
            start_time = time.time()
            _ = session.run(target)
            duration = time.time() - start_time
            if i >= num_steps_burn_in:
                if not i % 10:
                    print ('%s: step %d, duration = %.3f' %
                       (datetime.now(), i - num_steps_burn_in, duration))
                total_duration += duration
                total_duration_squared += duration * duration
        mn = total_duration / num_batches
        vr = total_duration_squared / num_batches - mn * mn
        sd = math.sqrt(vr)
        print ('%s: %s across %d steps, %.3f +/- %.3f sec / batch' %
           (datetime.now(), info_string, num_batches, mn, sd))
    def run_benchmark():
        with tf.Graph().as_default():
            image_size = 224
            images = tf.Variable(tf.random_normal([batch_size,
                                           image_size,
                                           image_size, 3],
                                          dtype=tf.float32,
                                          stddev=1e-1))
            pool5, parameters = inference(images)
            init = tf.global_variables_initializer()
            config = tf.ConfigProto()
            config.gpu_options.allocator_type = 'BFC'
            sess = tf.Session(config=config)
            sess.run(init)
            time_tensorflow_run(sess, pool5, "Forward")
            objective = tf.nn.l2_loss(pool5)
            grad = tf.gradients(objective, parameters)
            time_tensorflow_run(sess, grad, "Forward-backward")
    run_benchmark()

 

參考資料:
《TensorFlow實踐》

歡迎付費咨詢(150元每小時),我的微信:qingxingfengzi


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 話不多說直接上代碼 連接字元串: 主體代碼: IMongoModel: 值得註意的是:需引用MongoDB.BSon與MongoDB.Driver VS2017若在引用包後,還是無法找到命名空間,重啟VS即可。 ABCDEFG.GetAppSetting("mongodb"));讀取配置文件 ...
  • ////////HTTPGET HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); request.Method = "GET"; request.ContentType = "text/html;charset=UTF- ...
  • 18位號碼: 15位號碼: ...
  • 目錄 "簡介" "安裝" "主從複製" "備份與恢復" "API" AddOrUpdate GetOrAdd DeleteByPattern SearchKeys TransExcute Subscribe/Publish "命令" Todo Sentinel .NET Core Configura ...
  • 基於 Quartz.NET 實現可中斷的任務 Quartz.NET 是一個開源的作業調度框架,非常適合在平時的工作中,定時輪詢資料庫同步,定時郵件通知,定時處理數據等。 Quartz.NET 允許開發人員根據時間間隔(或天)來調度作業。它實現了作業和觸發器的多對多關係,還能把多個作業與不同的觸發器關 ...
  • 題目背景 二分圖 題目描述 給定一個二分圖,結點個數分別為n,m,邊數為e,求二分圖最大匹配數 輸入輸出格式 輸入格式: 第一行,n,m,e 第二至e+1行,每行兩個正整數u,v,表示u,v有一條連邊 輸出格式: 共一行,二分圖最大匹配 輸入輸出樣例 輸入樣例#1: 1 1 1 1 1 輸出樣例#1 ...
  • 1.攔截器與過濾器的區別 相同點:攔截器其實也是一種過濾器,都用於對請求和響應做攔截進行額外的處理. 不同點:攔截器主要是通過過濾器來調用的,功能實現主要放在攔截器中,而過濾器主要是用來調用攔截器.而且過濾器屬於java web中的概念範疇,而攔截器只有在struts2框架中採用這一概念 2.str ...
  • http://www.cnblogs.com/hoojo/archive/2011/08/11/2134638.html 可擴展標記語言——eXtensible Markup Language 用戶可以自己定義語言標記,只要有開始和閉合標簽即可。 xsl裝飾、修飾xml的顯示結果。 dtd約束xml ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...