人工智能的浪潮正席卷全球,諸多詞匯時刻縈繞在我們的耳邊,如人工智能,機器學習,深度學習等。“人工智能”的概念早在1956年就被提出,顧名思義用計算機來構造復雜的,擁有與人類智慧同樣本質特性的機器。經過幾十年的發展,在2012年后,得益於數據量的上漲,運算力的提升和機器學習算法(深度學習)的出現,人工智能開始大爆發。但目前的科研工作都集中在弱人工智能部分,即讓機器具備觀察和感知能力,可以一定程度的理解和推理,預期在該領域能夠取得一些重大突破。電影里的人工智能多半都是在描繪強人工智能,即讓機器獲得自適應能力,解決一些之前還沒遇到過的問題,而這部分在目前的現實世界里難以真正實現。
若人工智能有希望取得突破,是如何實現的,“智能”又從何而來呢?這主要歸功於一種實現人工智能的方法——機器學習。
一、機器學習概念
機器學習一種實現人工智能的方法。
機器學習最基本的做法是,使用算法來解析數據從中學習,然后對真實世界中的事件做出決策和預測。與傳統的為解決特定任務、硬編碼的軟件程序不同,機器學習是用大量的數據來“訓練”,通過各種算法從數據中學習如何完成任務。機器學習源於早期的人工智能領域,傳統的算法包括決策樹、聚類、貝葉斯分類、支持向量機、EM、Adaboost等等。從學習方法上來分,機器學習算法可以分為監督學習(如分類問題)、無監督學習(如聚類問題)、半監督學習、集成學習、深度學習和強化學習。
傳統的機器學習算法在指紋識別、基於Haar的人臉檢測、基於HoG特征的物體檢測等領域的應用基本達到了商業化的要求或者特定場景的商業化水平,但每前進一步都異常艱難,直到深度學習算法的出現。
二、深度學習概念
深度學習是一種實現機器學習的技術。
其本身並不是一種獨立的學習方法,也會用到有監督和無監督的學習方法來訓練深度神經網絡。但由於近幾年該領域發展迅猛,一些特有的學習手段相繼被提出(如殘差網絡),因此越來越多的人將其單獨看作一種學習的方法。
最初的深度學習是利用深度神經網絡來解決特征表達的一種學習過程。深度神經網絡本身並不是一個全新的概念,可大致理解為包含多個隱含層的神經網絡結構。為了提高深層神經網絡的訓練效果,人們對神經元的連接方法和激活函數等方面做出相應的調整。其實有不少想法早年間也曾有過,但由於當時訓練數據量不足、計算能力落后,因此最終的效果不盡如人意。深度學習,作為目前最熱的機器學習方法,但並不意味着是機器學習的終點。起碼目前存在以下問題:
1、深度學習模型需要大量的訓練數據,才能展現出神奇的效果,但現實生活中往往會遇到小樣本問題,此時深度學習方法無法入手,傳統的機器學習方法就可以處理;
2、有些領域,采用傳統的簡單的機器學習方法,可以很好地解決了,沒必要非得用復雜的深度學習方法;
3、深度學習的思想,來源於人腦的啟發,但絕不是人腦的模擬。
因此,機器學習框架和深度學習框架之間也是有區別的。本質上,機器學習框架涵蓋用於分類,回歸,聚類,異常檢測和數據准備的各種學習方法,也可以包括神經網絡方法。深度學習或深度神經網絡(DNN)框架涵蓋具有許多隱藏層的各種神經網絡拓撲,包括模式識別的多步驟過程。網絡中的層越多,可以提取用於聚類和分類的特征越復雜。常見的Caffe,CNTK,DeepLearning4j,Keras,MXNet和TensorFlow是深度學習框架。 而Scikit-learning和Spark MLlib是機器學習框架。 Theano則跨越了這兩個類別。
本文接下來的篇幅將會重點介紹深度學習的三個框架caffe、tensorflow和keras,如果只是需要使用傳統的機器學習基礎算法使用scikit-learning和spark MLlib則更為合適。
三、深度學習框架比較
神經網絡一般包括:訓練,測試兩大階段。訓練就是把訓練數據和神經網絡模型(AlexNet、RNN等神經網絡訓練框架Caffe等)用CPU或GPU提煉出模型參數的過程。測試就是把測試數據用訓練好的模型(神經網絡模型+模型參數)運行后查看結果。而caffe,keras,tensorflow就是把訓練過程所涉及的環節數據統一抽象,形成可使用框架。
(一)Caffe
1、概念
Caffe是一個清晰而高效的深度學習框架,也是一個被廣泛使用的開源深度學習框架,在Tensorflow出現之前一直是深度學習領域Github star最多的項目。主要優勢為:上手容易,網絡結構都是以配置文件形式定義,不需要用代碼設計網絡。訓練速度快,組件模塊化,可以方便的拓展到新的模型和學習任務上。但是Caffe最開始設計時的目標只針對於圖像,沒有考慮文本、語音或者時間序列的數據,因此Caffe對卷積神經網絡的支持非常好,但是對於時間序列RNN,LSTM等支持的不是特別充分。Caffe工程的models文件夾中常用的網絡模型比較多,比如Lenet、AlexNet、ZFNet、VGGNet、GoogleNet、ResNet等。
2、Caffe的模塊結構
Caffe由低到高依次把網絡中的數據抽象成Blob, 各層網絡抽象成Layer ,整個網絡抽象成Net,網絡模型的求解方法抽象成Solver。
1.Blob表示網絡中的數據,包括訓練數據,網絡各層自身的參數,網絡之間傳遞的數據都是通過Blob來實現的,同時Blob數據也支持在CPU與GPU上存儲,能夠在兩者之間做同步。
2.Layer是對神經網絡中各種層的抽象,包括卷積層和下采樣層,還有全連接層和各種激活函數層等。同時每種Layer都實現了前向傳播和反向傳播,並通過Blob來傳遞數據。
3.Net是對整個網絡的表示,由各種Layer前后連接組合而成,也是所構建的網絡模型。
4.Solver 定義了針對Net網絡模型的求解方法,記錄網絡的訓練過程,保存網絡模型參數,中斷並恢復網絡的訓練過程。自定義Solver能夠實現不同的網絡求解方式。
3、安裝方式
Caffe 需要預先安裝比較多的依賴項,CUDA,snappy,leveldb,gflags,glog,szip,lmdb,OpenCV,hdf5,BLAS,boost、ProtoBuffer等;
Caffe官網:http://caffe.berkeleyvision.org/;
Caffe Github : https://github.com/BVLC/caffe;Caffe 安裝教程:
http://caffe.berkeleyvision.org/installation.html,
http://blog.csdn.net/yhaolpz/article/details/71375762;
Caffe 安裝分為CPU和GPU版本,GPU版本需要顯卡支持以及安裝CUDA
4、使用Caffe搭建神經網絡
【caffe搭建神經網絡流程圖】

在上述流程中,步驟2是核心操作,也是caffe使用最讓人頭痛的地方,keras則對該部分做了更高層的抽象,讓使用者能夠快速編寫出自己想要實現的模型。
(二) Tensorflow
1、概念
TensorFlow是一個使用數據流圖進行數值計算的開源軟件庫。圖中的節點表示數學運算,而圖邊表示節點之間傳遞的多維數據陣列(又稱張量)。靈活的體系結構允許使用單個API將計算部署到服務器或移動設備中的某個或多個CPU或GPU。Tensorflow涉及相關概念解釋如下:
1)符號計算
符號計算首先定義各種變量,然后建立一個“計算圖”,圖中規定了各個變量之間的計算關系。 符號計算也叫數據流圖,其過程如下圖2-1所示,數據是按圖中黑色帶箭頭的線流動的。

【2-1 數據流圖示例】
數據流圖用“結點”(nodes)和“線”(edges)的有向圖來描述數學計算。
① “節點” 一般用來表示施加的數學操作,但也可以表示數據輸入(feed in)的起點/輸出(push out)的終點,或者是讀取/寫入持久變量(persistent variable)的終點。
② “線”表示“節點”之間的輸入/輸出關系。
③ 在線上流動的多維數據陣列被稱作“張量”。
2)張量
張量(tensor),可以看作是向量、矩陣的自然推廣,用來表示廣泛的數據類型,張量的階數也叫維度。
0階張量,即標量,是一個數。1階張量,即向量,是一組有序排列的數。2階張量,即矩陣,是一組向量有序的排列起來。3階張量,即立方體,是一組矩陣上下排列起來。以此類推。
3)數據格式(data_format)
目前主要有兩種方式來表示張量:
① th模式或channels_first模式,Theano和caffe使用此模式。
② tf模式或channels_last模式,TensorFlow使用此模式。
舉例說明兩種模式的區別:對於100張RGB3通道的16×32(高為16寬為32)彩色圖,th表示方式:(100,3,16,32)tf表示方式:(100,16,32,3)唯一的區別就是表示通道個數3的位置不一樣。
2、Tensorflow的模塊結構
Tensorflow/core目錄包含了TF核心模塊代碼,具體結構如圖2-2所示:
【圖 2-2 tensorflow代碼模塊結構】

3、安裝方式
1、官網下載naconda安裝:https://www.anaconda.com/download/;
2、依次在Anaconda Prompt控制台,按以下5個步驟輸入指令進行安裝:
1) 安裝py3+ cmd : conda create -n py3.6 python=3.6 anaconda;
2) 激活虛擬環境 cmd : activate py3.6
3) 激活TSF預安裝cmd: conda create -n tensorflow python=3.6;activate tensorflow;
4) 安裝TSF:pip install —ignore-installed —upgrade tensorflow;pip install —ignore-installed —upgrade tensorflow-gpu;
5) 退出虛擬環境cmd :deactivate py3.6。
4、使用Tensorflow搭建神經網絡
使用Tensorflow搭建神經網絡主要包含以下6個步驟:
1) 定義添加神經層的函數;
2) 准備訓練的數據;
3) 定義節點准備接收數據;
4) 定義神經層:隱藏層和預測層;
5) 定義loss表達式;
6) 選擇optimizer使loss達到最小;
7) 對所有變量進行初始化,通過sess.run optimizer,迭代多次進行學習。
5、示例代碼
Tensorflow 構建神經網絡識別手寫數字,具體代碼如下所示:
importtensorflow as tfimportnumpy as np# 添加層defadd_layer(inputs, in_size, out_size, activation_function=None): # add one more layer andreturnthe output ofthislayer Weights= tf.Variable(tf.random_normal([in_size, out_size])) biases = tf.Variable(tf.zeros([1, out_size]) +0.1) Wx_plus_b = tf.matmul(inputs, Weights) + biases
ifactivation_function is None: outputs = Wx_plus_b
else: outputs = activation_function(Wx_plus_b)
returnoutputs#1.訓練的數據# Make up some real data x_data = np.linspace(-1,1,300)[:, np.newaxis]noise = np.random.normal(0,0.05, x_data.shape)y_data = np.square(x_data) -0.5+ noise#2.定義節點准備接收數據# define placeholderforinputs to network xs = tf.placeholder(tf.float32, [None,1])ys = tf.placeholder(tf.float32, [None,1])#3.定義神經層:隱藏層和預測層# add hidden layer 輸入值是 xs,在隱藏層有10個神經元 l1 = add_layer(xs,1,10, activation_function=tf.nn.relu)# add output layer 輸入值是隱藏層 l1,在預測層輸出1個結果prediction = add_layer(l1,10,1, activation_function=None)#4.定義 loss 表達式# the error between prediciton and real data loss = tf.reduce_mean(tf.reduce_sum(tf.square(ys - prediction), reduction_indices=[1]))#5.選擇 optimizer 使 loss 達到最小 # 這一行定義了用什么方式去減少 loss,學習率是0.1
train_step = tf.train.GradientDescentOptimizer(0.1).minimize(loss)# important step 對所有變量進行初始化init = tf.initialize_all_variables()sess = tf.Session()# 上面定義的都沒有運算,直到 sess.run 才會開始運算sess.run(init)# 迭代1000次學習,sess.run optimizerfori inrange(1000): # training train_step 和 loss 都是由 placeholder 定義的運算,所以這里要用 feed 傳入參數 sess.run(train_step, feed_dict={xs: x_data, ys: y_data})ifi % 50==0: #to see the step improvement
print(s
ess.run(loss, feed_dict={xs: x_data, ys: y_data}))
(三) Keras
1、概念
Keras由純Python編寫而成並基於Tensorflow、Theano以及CNTK后端,相當於Tensorflow、Theano、CNTK的上層接口,號稱10行代碼搭建神經網絡,具有操作簡單、上手容易、文檔資料豐富、環境配置容易等優點,簡化了神經網絡構建代碼編寫的難度。目前封裝有全連接網絡、卷積神經網絡、RNN和LSTM等算法。
Keras有兩種類型的模型,序貫模型(Sequential)和函數式模型(Model),函數式模型應用更為廣泛,序貫模型是函數式模型的一種特殊情況。
1) 序貫模型(Sequential):單輸入單輸出,一條路通到底,層與層之間只有相鄰關系,沒有跨層連接。這種模型編譯速度快,操作也比較簡單。
2) 函數式模型(Model):多輸入多輸出,層與層之間任意連接。這種模型編譯速度慢。
2、Keras的模塊結構
Keras主要由5大模塊構成,模塊之間的關系及每個模塊的功能如圖3-1所示:
【圖 3-1 keras模塊結構圖】

3、安裝方式
Keras的安裝為以下三個步驟:
1) 安裝anaconda(python);
2) 用於科學計算的python發行版,支持Linux、Mac、Windows系統,提供了包管理與環境管理的功能,可以很方便的解決多版本python並存、切換以及各種第三方包安裝問題;
3) 利用pip或者conda安裝numpy、keras、 pandas、tensorflow等庫;
下載地址:
https://www.anaconda.com/what-is-anaconda/。
4、使用Keras搭建神經網絡
使用keras搭建一個神經網絡,包括5個步驟,分別為模型選擇、構建網絡層、編譯、訓練和預測。每個步驟操作過程中使用到的keras模塊如圖3-2所示:
【3-2 使用keras搭建神經網絡步驟】

5、示例代碼
Kears構建神經網絡識別手寫數字,具體代碼如下所示:
from keras.models import Sequential
from keras.layers.core import Dense, Dropout, Activation
from keras.optimizers import SGD
from keras.datasets import mnist
import numpy
'''
第一步:選擇模型
'''
model = Sequential()
'''
第二步:構建網絡層
'''
model.add(Dense(500,input_shape=(784,))) # 輸入層,28*28=784
model.add(Activation('tanh')) # 激活函數是tanh
model.add(Dropout(0.5)) # 采用50%的dropout
model.add(Dense(500)) # 隱藏層節點500個
model.add(Activation('tanh'))
model.add(Dropout(0.5))
model.add(Dense(10)) # 輸出結果是10個類別,所以維度是10
model.add(Activation('softmax')) # 最后一層用softmax作為激活函數
'''
第三步:編譯
'''
sgd = SGD(lr=0.01, decay=1e-6, momentum=0.9, nesterov=True) # 優化函數,設定學習率(lr)等參數
model.compile(loss='categorical_crossentropy', optimizer=sgd, class_mode='categorical') # 使用交叉熵作為loss函數
'''
第四步:訓練
.fit的一些參數
batch_size:對總的樣本數進行分組,每組包含的樣本數量
epochs :訓練次數
shuffle:是否把數據隨機打亂之后再進行訓練
validation_split:拿出百分之多少用來做交叉驗證
verbose:屏顯模式 0:不輸出 1:輸出進度 2:輸出每次的訓練結果
'''
(X_train, y_train), (X_test, y_test) = mnist.load_data() # 使用Keras自帶的mnist工具讀取數據(第一次需要聯網)
# 由於mist的輸入數據維度是(num, 28, 28),這里需要把后面的維度直接拼起來變成784維
X_train = X_train.reshape(X_train.shape[0], X_train.shape[1] * X_train.shape[2])
X_test = X_test.reshape(X_test.shape[0], X_test.shape[1] * X_test.shape[2])
Y_train = (numpy.arange(10) == y_train[:, None]).astype(int)
Y_test = (numpy.arange(10) == y_test[:, None]).astype(int)
model.fit(X_train,Y_train,batch_size=200,epochs=50,shuffle=True,verbose=0,validation_split=0.3)
model.evaluate(X_test, Y_test, batch_size=200, verbose=0)
'''
第五步:輸出
'''
print("test set")
scores = model.evaluate(X_test,Y_test,batch_size=200,verbose=0)
print("")
print("The test loss is %f" % scores)
result = model.predict(X_test,batch_size=200,verbose=0)
result_max = numpy.argmax(result, axis = 1)
test_max = numpy.argmax(Y_test, axis = 1)
result_bool = numpy.equal(result_max, test_max)
true_num = numpy.sum(result_bool)
print("")
print("The accuracy of the model is %f" % (true_num/len(result_bool)))
(四)框架優缺點對比
對比維度CaffeTensorflowKeras
上手難度1、不用寫代碼,只需在.prototxt文件中定義網絡結構就可以完成模型訓練。2、安裝復雜,且在.prototxt 文件內部設計網絡結構比較受限,沒有在 Python中設計網絡結構方便自由。3、配置文件不能用編程的方式調整超參數,對交叉驗證、超參數Grid Search 等操作無法很方便的支持。1、安裝簡便,教學資源豐富,根據樣例能快速搭建出基礎模型。2、有一定的使用門檻。編程范式和數學統計,都讓非機器學習或數據科學背景的使用者有上手難度。3、因為其靈活性,因此是一個相對底層的框架,使用時需要編寫大量的代碼,重新發明輪子。1、安裝簡單,旨在讓用戶進行最快速的原型實驗,讓想法變為結果的這個過程最短,非常適合最前沿的研究。2、API使用方便,用戶只需要將高級的模塊拼在一起,就可以設計神經網絡,降低了編程和閱讀別人代碼時的理解開銷。
框架維護GitHub項目,由伯克利視覺學中心(Berkeley Vision and Learning Center,BVLC)進行維護。被定義為最流行、最被認可的開源深度學習框架,框架結構優秀,擁有產品級的高質量代碼,由 Google團隊進行開發和維護,以及能力的加持。依然由google團隊開發支持,API以tf.keras的形式打包在TensorFlow中;微軟維護其CNTK后端;亞馬遜AWS也在開發MXNet支持。其他支持的公司包括NVIDIA、Uber、蘋果(通過CoreML)。
支持語言C++/CudaC++ python (Go,Java,Lua,Javascript,或者是R)Python
封裝算法1、對卷積神經網絡CNN的支持非常好,擁有大量訓練好的經典模型(AlexNet、VGG、Inception)以及state-of-the-art(ResNet等)等模型,收藏在Model Zoo。2、對時間序列 RNN、LSTM 等支持得不是特別充分1、支持CNN與RNN, 也支持深度強化學習乃至其他計算密集的科學計算(如偏微分方程求解等)。2、計算圖必須構建為靜態圖,這讓很多計算變得難以實現,尤其是序列預測中經常使用的beam search。1、支持CNN和循環網絡,支持級聯的模型或任意的圖結構的模型,從CPU上計算切換到GPU加速無須任何代碼的改動。2、沒有增強學習工具箱,自己修改實現很麻煩。封裝得太高級,訓練細節不能修改、penalty細節很難修改。
模型部署1、程序運行穩定,代碼質量高,適合對穩定性要求嚴格的生產環境,第一個主流的工業級深度學習框架。2、Caffe的底層基於C++,可在各種硬件環境編譯並具有良好的移植性,支持Linux、Mac和Windows,也可以編譯部署到移動設備系統如Android和iOS 上。1、性能好,可以同時運行多個大規模深度學習模型,支持模型生命周期管理、算法實驗,並可以高效地利用GPU資源,讓訓練好的模型更快捷方便地投入到實際生產環境。2、靈活的移植性,可以將同一份代碼幾乎不經過修改就輕松地部署到有任意數量CPU或GPU的PC、服務器或者移動設備上。1、部署簡便,使用TensorFlow、CNTK、Theano作為后端,簡化了編程的復雜度,節約了嘗試新網絡結構的時間。2、模型越復雜,收益越大,尤其是在高度依賴權值共享、多模型組合、多任務學習等模型上,表現得非常突出。
性能目前僅支持單機多GPU的訓練,不支持分布式的訓練。支持分布式計算,使GPU或TPU(Tensor Processing Unit)集群並行計算,共同訓練出一個模型。對不同設備間的通信優化得不是很好,分布式性能還沒有達到最優無法直接使用多GPU,對大規模的數據處理速度沒有其他支持多 GPU和分布式的框架快。用TensorFLow backend后端時速度比純TensorFLow下要慢很多。