譯文:如何使用TensorFlow實現神經網路(上)

原文鏈接:dzone.com/articles/an-i

原文作者:Faizan Shaikh

如果你一直關注數據科學或者機器學習等領域,你肯定不會錯過深度學習和神經網路的熱潮。許多組織都正在尋找深度學習人才,將深度學習運用於各個領域。從參與競賽到運用於開源項目,並願意為之付出高額的獎勵,他們正盡一切可能挖掘這個目前十分有限的人才庫為自己所用。

如果你對深度學習的前景感到興奮,但是還沒有開始你深度學習的旅程,這篇文章的目的就是扶你上馬,再送你一程。

在這篇文章中,我將介紹TensorFlow。通過本文,你將理解神經網路的應用,並能夠使用TensorFlow解決現實生活中的問題。本文需要你了解神經網路的基礎知識並熟悉編程。儘管本文中的代碼是用Python編寫的,但我會把重心集中在概念上,並儘可能保持語言無關。

現在就讓我們開始吧!

何時需要使用神經網路

近來,神經網路一直備受關注。有關神經網路和深度學習的更詳細的解釋, 請看這裡。相比我們今天討論的神經網路,更複雜,深奧的神經網路在圖像識別,語音和自然語言處理等諸多領域 正在取得巨大的突破。

現在的主要問題變成了何時使用,而何時不使用神經網路。現在這個領域就像金礦,每天都有許多發現。想要參與到神經網路的「淘金熱」,你必須記住以下幾點:

  • 首先,神經網路需要清晰的,具有信息量的數據(主要是大數據)來訓練。嘗試將神經網路想像成一個孩子。他首先觀察父母如何走路。然後試圖獨立行走,並且每走一步,孩子都會學習如何在特定情況下保持平衡。他可能會摔上幾跤,但經過幾次不成功的嘗試,他最終會學會走路。如果你不讓他走,他可能永遠學不會如何走路。小孩嘗試的次數越多,學習走路的效果就越好。
  • 神經網路適合應用於圖像處理等複雜問題。神經網路屬於表徵學習演算法的範疇。這些演算法將複雜問題分解為更簡單的形式,以使它們對於計算機變得可理解(或者說「可表示為計算機能處理的問題」)。好比先咀嚼食物,然後再咽下去。這對於傳統(非表徵學習)演算法來說是很難做到的。
  • 使用適當類型的神經網路來解決問題。 每個問題都有自己的難點。數據決定了你解決問題的方式。例如,如果問題是序列生成型的,那麼遞歸神經網路是解決這個問題的合適方法,而如果它是一個圖像相關的問題,轉而採取卷積神經網路可能更合適
  • 最後, 硬體性能對於運行深度神經網路模型是至關重要的。 神經網路很早以前就被「發現」了,但近些年來,主要是因為計算性能日益強大,才使神經網路開始大放異彩。如果你想運用神經網路解決現實生活中的問題,準備購買一些高端硬體吧!

如何使用神經網路解決問題

神經網路是一種特殊的機器學習(ML)演算法。因此,與每個機器學習演算法一樣,它遵循數據預處理,模型構建和模型評估等常規的機器學習工作流程。簡明起見,我列出了一個如何處理神經網路問題的待辦事項清單。

  • 檢查神經網路是否可以提升傳統演算法(請參考上部分提到的幾點)。
  • 調查何種神經網路架構最適合解決當前的問題。
  • 根據你使用語言和函數庫來定義神經網路架構。
  • 將數據轉換為正確的格式,並將數據分批。
  • 根據你的需要預處理數據。
  • 通過增加數據量增加模型的規模,訓練出更好的模型。
  • 將數據分批輸入神經網路。
  • 訓練並監測訓練集和驗證集的區別。
  • 測試你的模型,並保存以備將來使用。

對於本文,我將重點關注圖像數據。讓我們先了解一些圖像的知識,然後再研究TensorFlow。

了解圖像數據和當下流行的圖像處理庫

圖像大多可以視為一個三維數組,三個維度分別是指高度,寬度和顏色。比如說,如果你這會截取了你的電腦屏幕,截圖會首先被轉換為三維數組,然後被壓縮為PNG或JPG文件格式。

雖然圖像對於人類來說是相當容易理解的,但計算機很難理解它們。這種現象被稱為語義鴻溝。我們的大腦可以通過觀察圖像,並在幾秒鐘內了解整個圖像的意義。但是計算機只會將圖像視為一組數字。所以問題是,我們使機器了解圖像的意義?

在早期,人們試圖把圖像分解成「計算機可理解的」格式,好比各種模板。比如,人臉總是具有特定的結構,這個結構在每個人身上都有所體現,比如眼睛和鼻子的位置,或者我們臉的形狀。但是這種方法比較單一,當要識別的對象的數量增加時,「模板」的方法就很難繼續奏效。

時間來到2012年,深度神經網路架構贏得了那年的 ImageNet 挑戰,ImageNet 是一種從自然場景中識別物體的知名比賽。並且,深度神經網路架構繼續統治了此後進行的 ImageNet 挑戰,證明了深度神經網路架構在解決圖像問題方面的實際作用。

那麼人們通常使用哪種庫/編程語言來解決圖像識別問題?一項最近的一項調查 發現,大多數流行的深度學習庫都提供Python介面,其次第二多的是Lua,隨後是Java和Matlab。而最流行的深度學習庫,僅舉幾例:

  • Caffe
  • DeepLearning4j
  • TensorFlow
  • Theano
  • Torch

我們已經了解了圖像是如何儲存的以及有哪些常用的圖像處理庫,現在讓我們來看看TensorFlow提供了哪些功能。

什麼是TensorFlow?

我們從官方定義開始:

TensorFlow? 是一個採用數據流圖(data flow graphs),用於數值計算的開源軟體庫。節點(Nodes)在圖中表示數學操作,圖中的線(edges)則表示在節點間相互聯繫的多維數據數組,即張量(tensor)。它靈活的架構讓你可以在多種平台上展開計算,例如台式計算機中的一個或多個CPU(或GPU),伺服器,移動設備等等。

(官方中文定義)

如果對你來說,這些概念聽上去就很可怕,也請不要擔心。我會給TensorFlow一個簡單的定義。TensorFlow不過是對numpy(一個廣為使用的Python數學運算庫)做了一些變形而已。如果你之前曾經有使用numpy的經歷,那麼了解TensorFlow的原理不過是小菜一碟!numpy和TensorFlow之間的主要區別在於,TensorFlow遵循一個惰性編程範例。它首先建立一張包含所有需要完成的操作的圖( graph ),然後當調用某個「會話」(session),c程序會「運行」該圖形(譯者註:數據開始在圖中流動)。通過將內部數據表示更改為張量(也就是多維數組),張量具有可擴展性。構建一個計算圖可以被認為是TensorFlow的主要內容。要了解更多關於計算圖的數學原理,請閱讀 這篇文章。

TensorFlow一般被分類為神經網路庫,但其並不僅限於神經網路。TensorFlow設計的初衷是建立一個強大的神經網路庫,這沒錯。但它其實有能力做到更多。你可以在其上構建其他機器學習演算法,如決策樹或k最近鄰演算法。你完全可以在TensorFlow上做你通常會在numpy中做的一切!它被恰當地稱為「強化numpy」。

使用TensorFlow的優點是:

  • 它有一個直觀的結構, 顧名思義,TensorFlow有一個「張量流圖」。 你可以很容易地看到圖的每一個部分。
  • 可以方便地在CPU / GPU上通過分散式計算訓練模型
  • 平台靈活性。你可以在任何平台上運行模型,無論是移動設備,伺服器還是PC。

典型的TensorFlow「張量流圖"

每個庫都有自己的「實現細節」,即按照其編程範式編寫程序的一種方法。例如,在scikit-learn的實現中,首先創建所需演算法的對象,然後在訓練集上構建一個模型,使用訓練的模型對測試集進行評估 - 例如:

# define hyperparamters of ML algorithmclf = svm.SVC(gamma=0.001, C=100.)# train clf.fit(X, y)# test clf.predict(X_test)

正如我剛才所說,TensorFlow遵循一個惰性方法。在TensorFlow中運行程序的通常工作流程如下所示:

  • 建立一個計算圖。計算圖可以是任何TensorFlow支持的數學操作。
  • 初始化變數 以編譯先前定義的變數
  • 創建會話 (Session) 這是魔法開始的地方!
  • 在會話中運行圖形, 經過編譯的圖形傳遞給會話,開始執行會話。
  • 關閉會話 關閉會話。

TensorFlow中用到的一些術語:

placeholder: A way to feed data into the graphs# 一種數據輸入的方式(原意為佔位符,即在構建圖時使用佔位符,因為此時數據尚未輸入)feed_dict: A dictionary to pass numeric values to computational graph# 相當於一個key-value key:placeholder value:data接下來寫一個輸入兩個數據的小程序# import tensorflowimport tensorflow as tf# build computational grapha = tf.placeholder(tf.int16)b = tf.placeholder(tf.int16)addition = tf.add(a, b)# initialize variablesinit = tf.initialize_all_variables()# create session and run the graphwith tf.Session() as sess: sess.run(init) print "Addition: %i" % sess.run(addition, feed_dict={a: 2, b: 3})# close sessionsess.close()

在TensorFlow中實現神經網路

注意:我們可以使用不同的神經網路體系結構來解決這個問題,但是為了簡單起見,我們基於深度多層前向感知器實現。

讓我們首先回憶下我們通過這篇文章對神經網路的了解。

神經網路的典型實現如下:

  • 確定要使用神經網路體系結構
  • 將數據傳輸到模型
  • 在模型中,數據首先被分批以便可以被分批提取。首先對數據進行預處理,然後將其分批加入神經網路進行訓練。
  • 然後模型被逐漸訓練成型。
  • 顯示特定步長下的準確度。
  • 訓練結束後保存模型以供將來使用。
  • 在新數據上測試模型並觀察其執行情況。

在這裡,我們通過一個手寫數字識別的小例子來進行一次深度學習的實踐。首先讓我們看看我們的問題描述。

我們的問題是識別出所給的28x28圖像中的數字。我們將一部分圖像用於訓練,剩下的則用於測試我們的模型。所以首先下載訓練和測試文件。數據集包含一個數據集中所有圖像的壓縮文件,train.csvtest.csv包含相應訓練和測試圖像。數據集不提供任何附加功能,只是以「.png」的格式提供原始圖像。

正如本文的主題,我們將使用TensorFlow來建立一個神經網路模型。所以你應該先在你的系統中安裝TensorFlow。 根據你的系統情況,參閱 官方安裝指南進行安裝。

我們將按照上文的模板進行操作。用Python 2.7內核創建一個Jupyter notebook,步驟如下所示。

導入所有必需的模塊:

%pylab inlineimport osimport numpy as npimport pandas as pdfrom scipy.misc import imreadfrom sklearn.metrics import accuracy_scoreimport tensorflow as tf# To stop potential randomnessseed = 128rng = np.random.RandomState(seed)

第一步是設置數據的目錄路徑

root_dir = os.path.abspath(../..)data_dir = os.path.join(root_dir, data)sub_dir = os.path.join(root_dir, sub)# check for existenceos.path.exists(root_dir)os.path.exists(data_dir)os.path.exists(sub_dir)

讀取我們的數據集。數據集的格式為CSV,並且具有對應標籤的文件名:

train = pd.read_csv(os.path.join(data_dir, Train, train.csv))test = pd.read_csv(os.path.join(data_dir, Test.csv))sample_submission = pd.read_csv(os.path.join(data_dir, Sample_Submission.csv))train.head()

讓我們看看我們的數據是什麼樣的!我們查看我們的圖像並顯示它。

img_name = rng.choice(train.filename)filepath = os.path.join(data_dir, Train, Images, train, img_name)img = imread(filepath, flatten=True)pylab.imshow(img, cmap=gray)pylab.axis(off)pylab.show()

上圖可以表示為numpy數組,如下所示「

為了使數據處理更簡單,讓我們將所有的圖像存儲為numpy數組:

temp = []for img_name in train.filename: image_path = os.path.join(data_dir, Train, Images, train, img_name) img = imread(image_path, flatten=True) img = img.astype(float32) temp.append(img)train_x = np.stack(temp)temp = []for img_name in test.filename: image_path = os.path.join(data_dir, Train, Images, test, img_name) img = imread(image_path, flatten=True) img = img.astype(float32) temp.append(img)test_x = np.stack(temp)#由於這是一個典型的ML問題,為了測試我們模型的正確功能,我們創建了一個驗證集。我們以70:30的分組大小對比驗證集:split_size = int(train_x.shape[0]*0.7)train_x, val_x = train_x[:split_size], train_x[split_size:]train_y, val_y = train.label.values[:split_size], train.label.values[split_size:]#現在定義一些之後會用到的幫助函數def dense_to_one_hot(labels_dense, num_classes=10): """Convert class labels from scalars to one-hot vectors""" num_labels = labels_dense.shape[0] index_offset = np.arange(num_labels) * num_classes labels_one_hot = np.zeros((num_labels, num_classes)) labels_one_hot.flat[index_offset + labels_dense.ravel()] = 1 return labels_one_hotdef preproc(unclean_batch_x): """Convert values to range 0-1""" temp_batch = unclean_batch_x / unclean_batch_x.max() return temp_batchdef batch_creator(batch_size, dataset_length, dataset_name): """Create batch with random samples and return appropriate format""" batch_mask = rng.choice(dataset_length, batch_size) batch_x = eval(dataset_name + _x)[[batch_mask]].reshape(-1, input_num_units) batch_x = preproc(batch_x) if dataset_name == train: batch_y = eval(dataset_name).ix[batch_mask, label].values batch_y = dense_to_one_hot(batch_y) return batch_x, batch_y

現在來到了主要部分!我們會定義我們的神經網路架構。我們在這裡定義了一個三層神經網路:輸入層,隱藏層和輸出層。輸入層和輸出層中神經單元的數量是固定的,因為輸入是我們的28x28圖像,輸出是代表數字的10x1向量(0-9)。我們在隱藏層中設置500個神經元。這個數字可以根據你的需要而有所不同。我們再為剩下的變數賦值。閱讀 文章以獲得完整的代碼,並深入了解它的工作原理。

以 Sepmer Fi 的昵稱發佈於雲+社區翻譯社

推薦閱讀:

Michael Nielsen對交叉熵的解釋(三)
CS224N Lecture1 筆記
膠囊網路結構Capsule初探
【Neural Networks and Deep Learning】4.神經網路可以計算任何函數的可視化證明(1)
深度學習之人工神經網路及優化

TAG:人工智慧 | TensorFlow | 神經網路 |