劉曉,齊德昱,曹世軒
(1.華南理工大學計算機科學與工程學院,廣州510006;2.廣東實驗中學,廣州510375)
當前圖像分類技術的迅猛發(fā)展,主要歸功于深度學習模型訓練的可行性。深度學習的訓練方法發(fā)明于20 世紀70 年代[1],但因其模型層數及訓練次數過高,而當時計算機的硬件水平無法滿足訓練要求,因此未被重視。如今,計算機的性能有了極大提升,借助深度學習框架搭建和訓練神經網絡模型,可以在短時間內得到更精確的結果。
目前深度學習框架蓬勃發(fā)展,國內有百度的PaddlePaddle 框架,國外有谷歌的TensorFlow 框架[2]、Facebook 的PyTorch、Amazon 的MXNet 以及Microsoft 的CNTK。其中,TensorFlow 框架以其高度的靈活性和可移植性,迅速成為最受歡迎深度學習框架。另外,基于深度學習的圖像分類算法不斷取得進展。因此,基于TensorFlow 構建深度學習模型,實現圖像分類具備可行性,也是未來的發(fā)展趨勢。
當今圖像分類算法成為人工智能與計算機視覺領域的熱點之一,圖像分類的關鍵任務是特征提取,特征值的好壞直接影響了模型的分類效果。傳統(tǒng)的圖像分類方法依賴于人工設計特征,例如,1996 年Ojala T 等人提出并于2002 年拓展的局部二值模式(LBP)[3-4],用于圖像紋理特征提??;1999 年David Lowe 提出并于2004 年完善的尺度不變轉換特征(SIFT)[5],用于數字圖像的特征描述;2005 年Dala 提出的方向梯度直方圖(HOG)[6],用于行人檢測及目標跟蹤;2006 年Lazebnik等人提出的空間字塔模型(SPM)[7],將空間幾何信息加入圖像分類等。它們雖然在特定的領域取得了顯著的成果,但是人工設計特征耗時費力,且難以提取圖像的深層特征,存在一定的局限性。2006 年Hinton 等人[8]提出深度學習的概念,與傳統(tǒng)的圖像分類方法不同,深度學習能夠自主地學習圖像特征,并提取出更高維的圖像特征,具有很強的泛化能力和表達能力,在提高了分類準確率的同時,大大減少了人力,使圖像分類研究取得了突破性進展。
隨著深度學習技術的快速發(fā)展,針對深度學習的各種算法不斷完善,并在各個領域得到廣泛應用,例如,Taigman 等人[9]提出的DeepFace 和湯曉鷗團隊提出的DeepID,用于人臉識別;Sun 等人[10]提了一種融合卷積神經網絡和支持向量機兩種高級分類器協(xié)同進行功能磁共振成像識別的混合模型,用于醫(yī)學領域;Zhou 等人[11]提出一種基于卷積神經網絡的Landsat-8 多光譜遙感圖像花生種植面積提取方法,用于遙感圖像分類;Chang 等人[12]提出一種基于深度卷積神經網絡的交通標志檢測算法,用于交通領域等。尤其是基于卷積神經網絡(CNN)的深度學習模型,對于高維復雜數據的有效特征提取具有顯著優(yōu)勢。自2012 年Krizhevsky等人[13]提出基于卷積神經網絡的AlexNet 模型,成功將ImageNet 數據集的Top-5 錯誤率降至15%,隨后ZFNet、GoogLeNet、VGG、ResNet、DenseNet 相繼提出,到2017 年SENet 成功將Top-5 錯誤率降至2.25%,完成了大規(guī)模計算機視覺挑戰(zhàn)賽(ILSVRC)[14]的使命。此外,一些改進的卷積神經網絡也取得了不俗的成績。例如,用于目標識別的R-CNN[15]、Fast R-CNN[16]、Faster R-CNN[17];基于空間金字塔池化的卷積神經網絡SPPNet[18];以及能夠移植到移動端的MobileNet[19]、ShuffleNet[20]等。
隨著深度學習的研究熱潮持續(xù)高漲,開源深度學習框架不斷涌現、合并或者沒落,如TensorFlow、Py-Torch、MXNet、Deeplearning4j、PaddlePaddle、CNTK、Caffe、Theano 等,其中,PyTorch 是Caffe2 和Torch 合并得到,而CNTK、Theano 已經停止更新。這些框架極大簡化了深度學習模型的實現,快速推動了深度學習在學術界的研究效率和工業(yè)界的落地應用。表1 總結了目前主流框架的主要信息。
表1 主流深度學習框架信息對比
表2 對比了主流深度學習框架在GitHub 上的活躍度,可以看出,TensorFlow 關注度占據絕對優(yōu)勢。
表2 主流深度學習框架活躍度對比
為應對使用大規(guī)模深度學習的技術難題,谷歌2011 年推出第一代分布式機器學習框架DistBelief[21],并基于DistBelief 建立了Ineption 模型[22]取得2014 年ImageNet 競賽冠軍。但由于DistBelief 使用了許多谷歌內部系統(tǒng)模型架構,涉及商業(yè)機密信息,使得該框架難以對外開源,僅在谷歌內部使用。為更好地推動機器學習和深度學習在學術界和工業(yè)界的發(fā)展應用,谷歌于2015 年11 月在GitHub 上發(fā)布了第二代深度學習框架TensorFlow,2016 年4 月又開放了帶有分布式學習功能的增強版TensorFlow。截至目前,TensorFlow最新版本為2.0。
TensorFlow 是基于數據流圖的數值計算軟件庫,為實現機器學習或深度學習算法提供接口和計算框架。它兼具靈活性和規(guī)模性,前端支持C++、Python、Java 等多種編程語言,后端使用C++、CUDA 等保證底層高效性和穩(wěn)定性,可以將計算結果映射到不同的硬件或操作系統(tǒng),例如Windows、Linux、Android、iOS、服務器,甚至是大規(guī)模GPU 集群,大大降低了開發(fā)難度,同時提供了大規(guī)模分布式訓練方式,并允許用戶使用不同設備更新模型參數,節(jié)省了開發(fā)成本,使用戶可以快速實現模型設計并在海量數據集上訓練模型。近年來,TensorFlow 被廣泛應用到機器學習、深度學習以及其他計算領域,例如語音識別、自然語言處理、計算機視覺、機器人控制、信息提取等。
TensorFlow 由Tensor 和Flow 組成,Tensor 意為張量[23],是指某個計算圖在邊中流動的數據,可理解為多維數組;Flow 意為流,表示張量之間通過計算互相轉化的過程。TensorFlow 用數據流的流向圖表示計算流程,通過一個有向圖或者計算圖來表述計算,計算圖的每一個節(jié)點代表了一個運算操作,節(jié)點之間的邊代表了計算之間的依賴關系,若一個計算的輸入依賴于其他計算的輸出,那么這兩個計算之間存在依賴關系。所有TensorFlow 的程序都可以使用計算圖的形式表示,用戶通過使用Python、C++、Java 等編程語言對計算圖的分支進行條件控制或循環(huán)操作來定義數據的計算,樣例代碼如下:
TensorFlow 會自動將定義的計算轉化為計算圖上的節(jié)點,并自動維護一個默認的計算圖,通過tf.get_default_graph 函數獲取默認的計算圖,此外,TensorFlow還支持通過tf.Graph 生成新的計算圖。計算圖不僅能描述數據的計算過程,還能維護或更新計算狀態(tài)。
TensorFlow 的基本數據結構為張量,其中,零階張量為標量即一個數,一階張量為向量即一維數組,n 階張量即n 維數組。張量是對TensorFlow 中運算結果的引用,例如,上例代碼的運行結果為:
可以看出,張量保存的是數字的計算過程,包括name、shape、dtype 屬性。
TensorFlow 基本的數據類型包括數值型、字符串型和布爾型,常用的精度類型包括tf.int16、tf.int32、tf.int64、tf.float16、tf.float32、tf.float64,張量的類型和精度的轉換使用tf.cast 函數。TensorFlow 支持以下三種類型的張量:常量、變量、占位符。其中,常量是值不能改變的張量。聲明一個常量使用tf.constant()函數;填充張量,使用tf.fill()函數;此外,TensorFlow 還提供生成等差序列、正態(tài)分布和張量的隨機排列、隨機剪裁等。變量是TensorFlow 的一個類,用來存儲和更新機器學習模型中的參數,在神經網絡中通常表示權重和偏置,使用前需要初始化,模型訓練后必須存儲在磁盤,未來模型訓練和分析可直接加載它。創(chuàng)建變量,使用tf.Variable 函數;初始化變量,使用tf.Variable.initializer或assign()函數,此外,assign()函數還可更新變量;保存變量,使用Saver 類。占位符用于將數據輸入TensorFlow 圖,當要傳入的數據不確定時,使用占位符聲明一個沒有傳入具體值的數據格式,可使數據的使用更靈活。在訓練神經網絡時,通常用于提供新的訓練樣本,在會話中運行計算圖時,可為占位符賦值。占位符不包含任何數據,因此不需要初始化。創(chuàng)建占位符,使用tf.placeholder()函數。
TensorBoard 是TensorFlow 內置的可視化工具,提供計算圖的圖像和網絡執(zhí)行的量化指標,通過可視化TensorFlow 輸出的日志信息,使理解、調試和優(yōu)化TensorFlow 程序更容易。圖1 顯示了利用TensorBoard 可視化訓練指標的示例。
圖1 TensorBoard可視化訓練指標
2019 年10 月谷歌發(fā)布了TensorFlow2.0 正式版,其最大改變之一是Keras 得到官方內置和全面支持。Keras 是一個高級神經網絡API,具有高度模塊化、極簡和可擴充的特性,并提供清晰、可操作的錯誤消息,支持CNN 和RNN,通過調用tf.keras 的Sequential、compile 和fit 方法來構建、編譯和訓練模型。
另一個最大改變是將圖與會話機制(Graph Execution)改為動態(tài)圖機制(Eager Execution)。Eager Execution 是一個由運行定義的命令式接口,允許用戶在不構建圖的情況下,立即執(zhí)行操作,可直接使用numpy 作為輸入操作,操作會返回具體的值。tf.contrib.eager 模塊包含用于Eager Execution 和Graph Execution 環(huán)境的符號。
本文的實驗環(huán)境為Windows 10 操作系統(tǒng)、Intel Core i7-8565U 處理器、8G 內存、集成顯卡的普通PC,使用TensorFlow2.0 的Keras 高級API 構建一個卷積神經網絡模型,來解析TensorFlow2.0 圖像分類的實現過程。
本實驗采用經典的CIFAR-10 數據集,它包含10類60000 個32×32 彩色圖像,其中,訓練集為50000 個樣本,測試集為10000 個樣本。圖2 顯示了每個類別的一些示例。
圖2 CIFAR-10數據集示例
從TensorFlow2.0 中下載獲取CIFAR-10 數據集,并傳入訓練集和測試集的數據和對應標簽。
(train_image,train_label),(test_image,test_label)=keras.datasets.cifar10.load_data()
圖像大小是32×32×3,像素值介于0 到255 之間。標簽是從0 到9 的整數數組。圖像標簽與實際類別的對應關系,如表3 所示。
表3 圖像標簽與實際類別對應關系
將訓練集和測試集的圖片像素值歸一化處理。
TensorFlow2.0 提供了完整的模型構建參數,包括基本的構建模塊,如卷積層、池化層、全連接層、遞歸神經網絡模塊和非線性激活函數等來完成神經網絡模型從輸入到輸出的計算;各種損失函數,如交叉熵、均方誤差等來構建神經網絡模型的前向傳遞;自微分(autodiff)函數和模型優(yōu)化器,如adam、adagradumizer 等來自動構建神經網絡的向后傳遞操作。
本文使用TensorFlow2.0 的Keras API 構建神經網絡模型,通過調用tf.keras.Sequential 設計了一個卷積神經網絡模型,其中,卷積層步長stride 設為1 不會跳過任何一個像素值,padding 為same 使卷積的輸入和輸出保持相同尺寸,使用ReLU 激活函數進行非線性化。
池化層使用最大池化來保留最顯著的特征,步長stride 設為2 來縮小圖片尺寸。
卷積層和池化層反復使用,需分別定義。全連接層前使用flatten 將輸入數據展平,全連接層使用ReLU激活函數進行非線性化。
全連接層后使用Dropout 層,比例設為0.5,即隨機使50%的節(jié)點數據失活來減輕模型過擬合。輸出層使用Softmax 分類器來計算概率。模型的網絡結構圖如圖3 所示。
圖3 模型的網絡結構
模型的具體參數如表4 所示。
調用model.compile()設置模型參數,本文使用adam 作為優(yōu)化器,sparse_categorical_crossentropy 作為損失函數,accuracy 作為指標。
表4 模型的參數設計
調用model.fit()將訓練數據輸入模型;使用evaluate 評估準確率。
調用model.predict()對測試圖像進行預測。
圖4 所示為模型在訓練集上的準確率及損失率變化曲線??梢钥闯觯S著訓練次數的增加,模型準確率逐漸升高,損失率逐漸降低,準確率在訓練346 次時達到最高為98.78%,損失率在訓練346 次時達到最低為0.08193,訓練次數達350 次后,準確率和損失率趨于平緩。
圖4 模型在訓練集上的準確率及損失率變化曲線
圖5 所示為模型在測試集上的準確率及損失率變化曲線??梢钥闯觯S著訓練次數的增加,模型準確率逐漸升高,損失率先降低后升高,訓練次數達25 次時,準確率達到最高為76.12%,損失率達到最低為0.731,訓練超過25 次后,準確率趨于平緩,損失率呈上升趨勢。這是由于模型訓練過程出現了過擬合問題,從而影響了模型的識別精度。
圖5 模型在訓練集上的準確率及損失率變化曲線
本文基于TensorFlow2.0 來研究圖像分類算法,通過使用Keras API 構建卷積神經網絡模型實現了CIFAR-10 的圖像分類識別,具有實際意義,但是該模型在訓練過程產生了過擬合問題,下一步計劃引入L1、L2 正則化和批歸一化[24]等方法對模型進行優(yōu)化改進,此外,針對復雜背景下圖像分類的精度低、噪點數據的難以處理和深層卷積神經網絡模型的運行效率低等問題,有待繼續(xù)深入研究。
TensorFlow2.0 是一種靈活的、可擴展的深度學習庫,提供Python、C++、Java 等多種語言接口,用戶能自定義構建深度學習模型,同時,可使用TensorBoard 可視化模型和有關網絡執(zhí)行的量化指標。由于Keras 的高度封裝,TensorFlow2.0 使用戶能快速構建并在海量數據集上訓練模型,此外,TensorFlow2.0 還提供將模塊部署到生產環(huán)境中,但也造成了模型細節(jié)不透明、難以進行創(chuàng)新性更改等問題,值得進一步深入研究。