用TensorFlow實現神經網路很難?看完這篇詳解,「小白」也秒懂!
圖:pixabay
作者:Faizan Shaikh
「機器人圈」編譯:嗯~阿童木呀、多啦A亮
「機器人圈」正式更名為「雷克世界」,
如果你一直在關注資料科學/機器學習等相關領域,那麼你一定不會錯過有關深度學習和神經網路的任何動態。組織正在尋找一些深諳深度學習技能的人,無論他們將深度學習的知識用於何處。從開啟競爭到開源專案再到巨額獎金,人們正在試圖嘗盡一切辦法來挖掘這個領域有限的人才資源。
如果你對深度學習的發展前景充滿憧憬和期望,
在本文中,我將介紹TensorFlow的相關知識。相信閱讀本文後,你將能夠瞭解神經網路的應用,並學會使用TensorFlow來解決現實生活中的問題。而在閱讀本文之前,要求你能夠瞭解神經網路的基礎知識,並熟悉程式設計。儘管這篇文章中的代碼是用Python編寫的,但我會將重點放在概念上,並盡可能保持所談論的內容與程式設計無關。
何時使用神經網路
眾所周知,到目前為止,神經網路成為人們關注的焦點已有很長一段時間了。如果還不是很瞭解,點選連結,這裡有有關神經網路和深度學習的更為詳盡的闡述。(https://www.analyticsvidhya.com/blog/2016/10/an-introduction-to-implementing-neural-networks-using-tensorflow/?utm_source=dzone&utm_medium=social)其中,它的“更深度”版本已然在諸如圖像識別、語音和自然語言處理等諸多領域取得了巨大的突破性進展。
而在神經網路的使用這有一個至關重要的問題出現了,
•首先,神經網路需要清晰且翔實的資料(主要是大資料)進行訓練。你可以試著將神經網路想像成一個孩子。在最初的時候,它首先要觀察其父母的走路方式,然後,
•對於諸如影像處理這樣的複雜問題,使用神經網路是一種需要很謹慎的行為。神經網路是隸屬於一種稱為表徵學習演算法(representation learning algorithms)的一類演算法。
•當你認為有了適當的神經網路類型來解決問題時,殊不知每個問題都有自己的難點。而資料將決定你用以解決問題的方式。例如,如果是序列生成的問題,則選擇迴圈神經網路是最為合適的,而如果它是一個和圖像相關的問題,那麼你可能就需要做些改變,採用卷積神經網路才是一個合適的選擇。
如何使用神經網路解決問題
神經網路是一種特殊類型的機器學習(ML)演算法。因此,與每個ML演算法一樣,它遵循資料預處理,模型構建和模型評估的通用ML工作流。為了簡明起見,我列出了一個如何處理神經網路問題的待辦事項清單。
•檢查神經網路是否提升了傳統演算法(參考上述章節中的檢查列表)。
•做一項關於哪個神經網路架構最適合亟待解決問題的調查。
•通過你所選擇的語言/庫來定義神經網路架構。
•將資料轉換為正確的格式,並將其分為若干批量。
•根據需要對資料進行預處理。
•添加資料以增加大小並做出更好的訓練模型。
•將批量饋送到神經網路。
•訓練、監測訓練過程中的變化並驗證資料集。
•對模型進行測試並保存以備將來使用。
對於這篇文章,我將重點介紹圖像資料。在深入瞭解TensorFlow之前,需要首先對其有基本瞭解。
理解圖像資料及用以解決問題的流行庫
圖像大部分以三維陣列的形式排列,其中三維是指高度、寬度和顏色信號通道。例如,如果你在此刻拍攝個人電腦的螢幕截圖,則首先將其轉換成三維陣列,然後將其壓縮為PNG或JPG檔案格式。
監管這些圖像對於人類來說是很容易理解的,但對電腦來說就沒有那麼容易了。這種現象被稱為語義鴻溝(semantic gap)。我們的大腦可以在幾秒鐘內看到圖像,並對完整的圖像加以瞭解。而另一方面,電腦則將圖像視為一個陣列。所以問題是,我們該如何將這個圖像向機器加以解釋。
在早期,人們試圖將這種圖像分解為像一個“範本”一樣的機器 “可理解”的格式。例如,一張臉中總有一個特定的結構,它以某種形式在每個人身上保留下來,比如我眼睛和鼻子的位置,或者臉型。但是這種方法將會非常繁瑣,因為當要識別的目標數量增加時,“範本”就不存在了。
到了2012年,深度神經網路架構贏得了ImageNet挑戰賽,這是一個在從自然場景中識別目標領域的很有聲望的挑戰。後來在所有即將到來的ImageNet挑戰中,神經網路都佔據著主導地位,從而證明了其在解決圖像問題的有效性。
那麼人們通常會使用哪些庫/語言來解決圖像識別問題呢?最近的一項調查結果顯示,大多數受歡迎的深度學習庫都有一個Python介面,其次是Lua、Java和Matlab。下面是最受歡迎的庫中的一些代表:
•Caffe(http://caffe.berkeleyvision.org/)
•DeepLearning4j(https://deeplearning4j.org/)
•TensorFlow(https://www.tensorflow.org/)
•Theano(http://www.deeplearning.net/software/theano/)
•Torch(http://torch.ch/)
現在,你應該瞭解圖像是如何存儲的以及常用的公共庫有哪些了吧,下面請查看TensorFlow必須提供的內容有哪些。
什麼是TensorFlow?
下面是官方定義:
TensorFlow是一個開源軟體庫,用於使用資料流程圖形進行數值計算。圖中的節點表徵數學運算,而圖形邊緣表徵的是在它們之間傳遞的多維資料陣列(又稱張量)。靈活的體系結構使得你能夠將計算部署到桌面,伺服器或具有單個API的移動設備中的一個或多個CPU或GPU。
可能這聽起來有點嚇人,但不用擔心。這裡有一個簡單定義,僅需要把TensorFlow看作一種有著一些難點的numpy。如果你以前曾使用過numpy,那理解TensorFlow也只不過是小菜一碟了! numpy和TensorFlow之間的一個主要區別在於TensorFlow遵循懶惰(lazy)的程式設計範式。它首先會構建一個需要完成的所有操作的圖表,然後當“session”被調用時,它將“run”該圖表。它的構建是可擴展的,因為它是通過將內部資料表征更改為張量(也就是多維陣列)來實現的。構建計算圖表可以被認為是TensorFlow的主要成分。要想瞭解更多關於計算圖表的數學構成,請閱讀本文。(http://colah.github.io/posts/2015-08-Backprop/)
將TensorFlow分類為神經網路庫是一件很容易的事情,但它為並不僅僅如此。實質上來講它是被設計成一個強大的神經網路庫。但它所擁有的力量、能夠做的事情遠遠不止如此。你可以在其上構建其他機器學習演算法,如決策樹或k最近鄰演算法。你可以使用它來做一切你經常使用numpy來做的事情!它恰恰稱為“numpy on steroids”。
使用TensorFlow的優點是:
•它有一個直觀的結構,顧名思義,它有一個“張量流”。你可以很容易將圖表的每一部分視覺化。
•輕鬆地在CPU / GPU上進行分散式運算。
•平臺靈活性,你可以隨時隨地運行模型,無論是在移動設備,伺服器還是PC上。
TensorFlow的典型 “流”
每個庫都有自己的“實現細節”,即一種按照編碼範式編寫的方式。例如,當實現scikit-learn時,首先創建所需演算法的物件,然後在訓練集上建立一個模型,並對測試集進行預測,如下所示:
# define hyperparamters of ML algorithm
clf = svm.SVC(gamma=0.001, C=100.)
# train
clf.fit(X, y)
# test
clf.predict(X_test)
正如我前面所說,TensorFlow遵循一種懶惰(lazy)的方法。在TensorFlow中運行程式的通常工作流程如下:
•建立一個計算圖,任何的數學運算可以使用TensorFlow支撐。
•初始化變數編譯預先定義的變數。
•創建session,這是神奇開始的地方 !
•在session中運行圖形,編譯圖形被傳遞到session,它開始執行操作。
•關閉session,結束這次使用。
TensorFlow 中使用的術語很少。
placeholder: A way to feed data into the graphs
feed_dict: A dictionary to pass numeric values to computational graph
讓我們寫一個小程式來添加兩個數位!
# import tensorflow
import tensorflow as tf
# build computational graph
a = tf.placeholder(tf.int16)
b = tf.placeholder(tf.int16)
addition = tf.add(a, b)
# initialize variables
init = tf.initialize_all_variables()
# create session and run the graph
with tf.Session() as sess:
sess.run(init)
print "Addition: %i" % sess.run(addition, feed_dict={a: 2, b: 3})
# close session
sess.close()
在TensorFlow中實現神經網路
注意:我們可以使用不同的神經網路架構來解決這個問題,但是為了簡單起見,我們深入實現了前饋多層感知器。
讓我們先記住對神經網路的瞭解。
神經網路的典型實現如下:
•定義要編譯的神經網路架構
•將資料傳輸到模型
•在引擎蓋下,資料首先分成批次,以便可以獲取。批次首先進行預處理、增強,然後送入神經網路進行訓練。
•然後模型被逐步地訓練。
•顯示特定數量的時間步長的精度。
•訓練後保存模型供將來使用。
•在新資料上測試模型並檢查其執行情況。
在這裡,我們解決深度學習實踐問題,以用來識別數字。讓我們再花一點時間看看問題陳述。
我們的問題是圖像識別,以識別來自給定的 28×28 圖像的數位。 我們有一部分圖像用於訓練,其餘的用於測試模型。首先,下載訓練和測試檔。資料集包含資料集中所有圖像的壓縮檔,train.csv和test.csv都具有相應訓練和測試圖像的名稱。資料集中不提供任何其他功能,只是原始圖像以 “.png” 格式提供。
如你所知,我們將使用TensorFlow來構建神經網路模型。所以,你應該先在系統中安裝TensorFlow。根據你的系統規格,請參閱官方安裝指南(https://github.com/tensorflow/tensorflow/blob/master/tensorflow/g3doc/get_started/os_setup.md)進行安裝。
我們將按照上述範本,使用Python 2.7內核創建Jupyter notebook ,並按照以下步驟操作。
導入所有必需的模組:
%pylab inline
import os
import numpy as np
import pandas as pd
from scipy.misc import imread
from sklearn.metrics import accuracy_score
import tensorflow as tf
設置種子值,以便我們可以控制模型的隨機性:
# To stop potential randomness
seed = 128
rng = 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 existence
os.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,
由於這是一個典型的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_hot
def preproc(unclean_batch_x):
"""Convert values to range 0-1"""
temp_batch = unclean_batch_x / unclean_batch_x.max()
return temp_batch
def 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向量。我們在隱藏層中採集500個神經元。這個數位可以根據你的需要而變化。我們還為剩餘的變數賦值。閱讀文章以訪問完整的代碼(https://www.analyticsvidhya.com/blog/2016/10/an-introduction-to-implementing-neural-networks-using-tensorflow/?utm_source=dzone&utm_medium=social),並深入瞭解其工作原理。
### set all variables
# number of neurons in each layer
input_num_units = 28*28
hidden_num_units = 500
output_num_units = 10
# define placeholders
x = tf.placeholder(tf.float32, [None, input_num_units])
y = tf.placeholder(tf.float32, [None, output_num_units])
# set remaining variables
epochs = 5
batch_size = 128
learning_rate = 0.01
### define weights and biases of the neural network (refer this article if you don't understand the terminologies)
weights = {
'hidden': tf.Variable(tf.random_normal([input_num_units, hidden_num_units], seed=seed)),
'output': tf.Variable(tf.random_normal([hidden_num_units, output_num_units], seed=seed))
}
biases = {
'hidden': tf.Variable(tf.random_normal([hidden_num_units], seed=seed)),
'output': tf. Variable(tf.random_normal([output_num_units], seed=seed))
}
現在創建我們的神經網路計算圖:
hidden_layer = tf.add(tf.matmul(x, weights['hidden']), biases['hidden'])
hidden_layer = tf.nn.relu(hidden_layer)
output_layer = tf.matmul(hidden_layer, weights['output']) + biases['output']
此外,我們需要定義神經網路的成本:
cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(output_layer, y))
設置優化器,即我們的反向傳播演算法。這裡我們使用 Adam,這是梯度下降演算法的高效變體。有在 tensorflow 中可用許多其它優化(參照此處(https://www.tensorflow.org/versions/r0.11/api_docs/python/train.html#optimizers)。
optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(cost)
定義我們的神經網路結構後,讓我們來初始化所有的變數。
init = tf.initialize_all_variables()
現在讓我們創建一個Session,並在Session中運行神經網路。我們還驗證創建的驗證集的模型準確性。
with tf.Session() as sess:
# create initialized variables
sess.run(init)
### for each epoch, do:
### for each batch, do:
### create pre-processed batch
### run optimizer by feeding batch
### find cost and reiterate to minimize
for epoch in range(epochs):
avg_cost = 0
total_batch = int(train.shape[0]/batch_size)
for i in range(total_batch):
batch_x, batch_y = batch_creator(batch_size, train_x.shape[0], 'train')
_, c = sess.run([optimizer, cost], feed_dict = {x: batch_x, y: batch_y})
avg_cost += c / total_batch
print "Epoch:", (epoch+1), "cost =", "{:.5f}".format(avg_cost)
print "Training complete!"
# find predictions on val set
pred_temp = tf.equal(tf.argmax(output_layer, 1), tf.argmax(y, 1))
accuracy = tf.reduce_mean(tf.cast(pred_temp, "float"))
print "Validation Accuracy:", accuracy.eval({x: val_x.reshape(-1, input_num_units), y: dense_to_one_hot(val_y)})
predict = tf.argmax(output_layer, 1)
pred = predict.eval({x: test_x.reshape(-1, input_num_units)})
這將是上面代碼的輸出。
Epoch: 1 cost = 8.93566
Epoch: 2 cost = 1.82103
Epoch: 3 cost = 0.98648
Epoch: 4 cost = 0.57141
Epoch: 5 cost = 0.44550
Training complete!
Validation Accuracy: 0.952823
眼見為實,我們將預測視覺化:
img_name = rng.choice(test.filename)
filepath = os.path.join(data_dir, 'Train', 'Images', 'test', img_name)
img = imread(filepath, flatten=True)
test_index = int(img_name.split('.')[0]) - 49000
print "Prediction is: ", pred[test_index]
pylab.imshow(img, cmap='gray')
pylab.axis('off')
pylab.show()
Prediction is: 8(下圖所示:)
我們看到模型性能是相當不錯的!現在讓我們創建一個提交:
sample_submission.filename = test.filename
sample_submission.label = pred
sample_submission.to_csv(os.path.join(sub_dir, 'sub01.csv'), index=False)
終於完成了!我們剛剛創建了自己的訓練神經網路!
TensorFlow的局限性
•儘管TensorFlow功能強大,但它仍然是一個低水準庫,例如,它可以被認為是機器級語言,但對於大多數功能,你需要自己進行模組化和高級介面,如 keras。
•它仍然在繼續開發和維護。
•它取決於你的硬體規格,配置越高越好。
•不是所有語言都能使用它的API。
•TensorFlow中仍然有很多庫需要手動導入,比如OpenCL支持。
上面提到的大多數是TensorFlow開發人員的願景,他們已經制定了一個路線圖,計畫庫未來應該如何開發。
TensorFlow與其他庫
TensorFlow建立在類似的原理,如使用數學計算圖表的Theano和Torch,但是隨著分散式運算的額外支持,TensorFlow能更好地解決複雜的問題。此外,TensorFlow模型的部署已經獲得支援,這使得它更容易用於工業目的,打擊了一些商業的三庫,如Deeplearning4j、H2O和Turi。TensorFlow有用於Python,C ++和Matlab的API。最近還出現了對Ruby和R等其他語言的支援。因此,TensorFlow正試圖獲得通用語言的支援。
下一步在哪裡?
以上你看到了如何用TensorFlow構建一個簡單的神經網路,這段代碼是為了讓人們瞭解如何開始實現TensorFlow。要解決更複雜的現實生活中的問題,你必須在這篇文章的基礎上再調整一些代碼才行。
許多上述功能可以被抽象為提供無縫的端到端工作流,如果你使用scikit-learn,你可能知道一個高級庫如何抽象“底層”實現,給終端使用者一個更容易的介面。儘管TensorFlow已經提取了大多數實現,但是也有更高級的庫,如TF-slim和TFlearn。
參考資源
TensorFlow官方庫 https://github.com/tensorflow/tensorflow。
Rajat Monga(TensorFlow技術負責人) “TensorFlow為大家” 的視頻https://youtu.be/wmw8Bbb_eIE。
專門的資源列表:https://github.com/jtoy/awesome-tensorflow/#github-projects。
例如,如果是序列生成的問題,則選擇迴圈神經網路是最為合適的,而如果它是一個和圖像相關的問題,那麼你可能就需要做些改變,採用卷積神經網路才是一個合適的選擇。如何使用神經網路解決問題
神經網路是一種特殊類型的機器學習(ML)演算法。因此,與每個ML演算法一樣,它遵循資料預處理,模型構建和模型評估的通用ML工作流。為了簡明起見,我列出了一個如何處理神經網路問題的待辦事項清單。
•檢查神經網路是否提升了傳統演算法(參考上述章節中的檢查列表)。
•做一項關於哪個神經網路架構最適合亟待解決問題的調查。
•通過你所選擇的語言/庫來定義神經網路架構。
•將資料轉換為正確的格式,並將其分為若干批量。
•根據需要對資料進行預處理。
•添加資料以增加大小並做出更好的訓練模型。
•將批量饋送到神經網路。
•訓練、監測訓練過程中的變化並驗證資料集。
•對模型進行測試並保存以備將來使用。
對於這篇文章,我將重點介紹圖像資料。在深入瞭解TensorFlow之前,需要首先對其有基本瞭解。
理解圖像資料及用以解決問題的流行庫
圖像大部分以三維陣列的形式排列,其中三維是指高度、寬度和顏色信號通道。例如,如果你在此刻拍攝個人電腦的螢幕截圖,則首先將其轉換成三維陣列,然後將其壓縮為PNG或JPG檔案格式。
監管這些圖像對於人類來說是很容易理解的,但對電腦來說就沒有那麼容易了。這種現象被稱為語義鴻溝(semantic gap)。我們的大腦可以在幾秒鐘內看到圖像,並對完整的圖像加以瞭解。而另一方面,電腦則將圖像視為一個陣列。所以問題是,我們該如何將這個圖像向機器加以解釋。
在早期,人們試圖將這種圖像分解為像一個“範本”一樣的機器 “可理解”的格式。例如,一張臉中總有一個特定的結構,它以某種形式在每個人身上保留下來,比如我眼睛和鼻子的位置,或者臉型。但是這種方法將會非常繁瑣,因為當要識別的目標數量增加時,“範本”就不存在了。
到了2012年,深度神經網路架構贏得了ImageNet挑戰賽,這是一個在從自然場景中識別目標領域的很有聲望的挑戰。後來在所有即將到來的ImageNet挑戰中,神經網路都佔據著主導地位,從而證明了其在解決圖像問題的有效性。
那麼人們通常會使用哪些庫/語言來解決圖像識別問題呢?最近的一項調查結果顯示,大多數受歡迎的深度學習庫都有一個Python介面,其次是Lua、Java和Matlab。下面是最受歡迎的庫中的一些代表:
•Caffe(http://caffe.berkeleyvision.org/)
•DeepLearning4j(https://deeplearning4j.org/)
•TensorFlow(https://www.tensorflow.org/)
•Theano(http://www.deeplearning.net/software/theano/)
•Torch(http://torch.ch/)
現在,你應該瞭解圖像是如何存儲的以及常用的公共庫有哪些了吧,下面請查看TensorFlow必須提供的內容有哪些。
什麼是TensorFlow?
下面是官方定義:
TensorFlow是一個開源軟體庫,用於使用資料流程圖形進行數值計算。圖中的節點表徵數學運算,而圖形邊緣表徵的是在它們之間傳遞的多維資料陣列(又稱張量)。靈活的體系結構使得你能夠將計算部署到桌面,伺服器或具有單個API的移動設備中的一個或多個CPU或GPU。
可能這聽起來有點嚇人,但不用擔心。這裡有一個簡單定義,僅需要把TensorFlow看作一種有著一些難點的numpy。如果你以前曾使用過numpy,那理解TensorFlow也只不過是小菜一碟了! numpy和TensorFlow之間的一個主要區別在於TensorFlow遵循懶惰(lazy)的程式設計範式。它首先會構建一個需要完成的所有操作的圖表,然後當“session”被調用時,它將“run”該圖表。它的構建是可擴展的,因為它是通過將內部資料表征更改為張量(也就是多維陣列)來實現的。構建計算圖表可以被認為是TensorFlow的主要成分。要想瞭解更多關於計算圖表的數學構成,請閱讀本文。(http://colah.github.io/posts/2015-08-Backprop/)
將TensorFlow分類為神經網路庫是一件很容易的事情,但它為並不僅僅如此。實質上來講它是被設計成一個強大的神經網路庫。但它所擁有的力量、能夠做的事情遠遠不止如此。你可以在其上構建其他機器學習演算法,如決策樹或k最近鄰演算法。你可以使用它來做一切你經常使用numpy來做的事情!它恰恰稱為“numpy on steroids”。
使用TensorFlow的優點是:
•它有一個直觀的結構,顧名思義,它有一個“張量流”。你可以很容易將圖表的每一部分視覺化。
•輕鬆地在CPU / GPU上進行分散式運算。
•平臺靈活性,你可以隨時隨地運行模型,無論是在移動設備,伺服器還是PC上。
TensorFlow的典型 “流”
每個庫都有自己的“實現細節”,即一種按照編碼範式編寫的方式。例如,當實現scikit-learn時,首先創建所需演算法的物件,然後在訓練集上建立一個模型,並對測試集進行預測,如下所示:
# define hyperparamters of ML algorithm
clf = svm.SVC(gamma=0.001, C=100.)
# train
clf.fit(X, y)
# test
clf.predict(X_test)
正如我前面所說,TensorFlow遵循一種懶惰(lazy)的方法。在TensorFlow中運行程式的通常工作流程如下:
•建立一個計算圖,任何的數學運算可以使用TensorFlow支撐。
•初始化變數編譯預先定義的變數。
•創建session,這是神奇開始的地方 !
•在session中運行圖形,編譯圖形被傳遞到session,它開始執行操作。
•關閉session,結束這次使用。
TensorFlow 中使用的術語很少。
placeholder: A way to feed data into the graphs
feed_dict: A dictionary to pass numeric values to computational graph
讓我們寫一個小程式來添加兩個數位!
# import tensorflow
import tensorflow as tf
# build computational graph
a = tf.placeholder(tf.int16)
b = tf.placeholder(tf.int16)
addition = tf.add(a, b)
# initialize variables
init = tf.initialize_all_variables()
# create session and run the graph
with tf.Session() as sess:
sess.run(init)
print "Addition: %i" % sess.run(addition, feed_dict={a: 2, b: 3})
# close session
sess.close()
在TensorFlow中實現神經網路
注意:我們可以使用不同的神經網路架構來解決這個問題,但是為了簡單起見,我們深入實現了前饋多層感知器。
讓我們先記住對神經網路的瞭解。
神經網路的典型實現如下:
•定義要編譯的神經網路架構
•將資料傳輸到模型
•在引擎蓋下,資料首先分成批次,以便可以獲取。批次首先進行預處理、增強,然後送入神經網路進行訓練。
•然後模型被逐步地訓練。
•顯示特定數量的時間步長的精度。
•訓練後保存模型供將來使用。
•在新資料上測試模型並檢查其執行情況。
在這裡,我們解決深度學習實踐問題,以用來識別數字。讓我們再花一點時間看看問題陳述。
我們的問題是圖像識別,以識別來自給定的 28×28 圖像的數位。 我們有一部分圖像用於訓練,其餘的用於測試模型。首先,下載訓練和測試檔。資料集包含資料集中所有圖像的壓縮檔,train.csv和test.csv都具有相應訓練和測試圖像的名稱。資料集中不提供任何其他功能,只是原始圖像以 “.png” 格式提供。
如你所知,我們將使用TensorFlow來構建神經網路模型。所以,你應該先在系統中安裝TensorFlow。根據你的系統規格,請參閱官方安裝指南(https://github.com/tensorflow/tensorflow/blob/master/tensorflow/g3doc/get_started/os_setup.md)進行安裝。
我們將按照上述範本,使用Python 2.7內核創建Jupyter notebook ,並按照以下步驟操作。
導入所有必需的模組:
%pylab inline
import os
import numpy as np
import pandas as pd
from scipy.misc import imread
from sklearn.metrics import accuracy_score
import tensorflow as tf
設置種子值,以便我們可以控制模型的隨機性:
# To stop potential randomness
seed = 128
rng = 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 existence
os.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,
由於這是一個典型的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_hot
def preproc(unclean_batch_x):
"""Convert values to range 0-1"""
temp_batch = unclean_batch_x / unclean_batch_x.max()
return temp_batch
def 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向量。我們在隱藏層中採集500個神經元。這個數位可以根據你的需要而變化。我們還為剩餘的變數賦值。閱讀文章以訪問完整的代碼(https://www.analyticsvidhya.com/blog/2016/10/an-introduction-to-implementing-neural-networks-using-tensorflow/?utm_source=dzone&utm_medium=social),並深入瞭解其工作原理。
### set all variables
# number of neurons in each layer
input_num_units = 28*28
hidden_num_units = 500
output_num_units = 10
# define placeholders
x = tf.placeholder(tf.float32, [None, input_num_units])
y = tf.placeholder(tf.float32, [None, output_num_units])
# set remaining variables
epochs = 5
batch_size = 128
learning_rate = 0.01
### define weights and biases of the neural network (refer this article if you don't understand the terminologies)
weights = {
'hidden': tf.Variable(tf.random_normal([input_num_units, hidden_num_units], seed=seed)),
'output': tf.Variable(tf.random_normal([hidden_num_units, output_num_units], seed=seed))
}
biases = {
'hidden': tf.Variable(tf.random_normal([hidden_num_units], seed=seed)),
'output': tf. Variable(tf.random_normal([output_num_units], seed=seed))
}
現在創建我們的神經網路計算圖:
hidden_layer = tf.add(tf.matmul(x, weights['hidden']), biases['hidden'])
hidden_layer = tf.nn.relu(hidden_layer)
output_layer = tf.matmul(hidden_layer, weights['output']) + biases['output']
此外,我們需要定義神經網路的成本:
cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(output_layer, y))
設置優化器,即我們的反向傳播演算法。這裡我們使用 Adam,這是梯度下降演算法的高效變體。有在 tensorflow 中可用許多其它優化(參照此處(https://www.tensorflow.org/versions/r0.11/api_docs/python/train.html#optimizers)。
optimizer = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(cost)
定義我們的神經網路結構後,讓我們來初始化所有的變數。
init = tf.initialize_all_variables()
現在讓我們創建一個Session,並在Session中運行神經網路。我們還驗證創建的驗證集的模型準確性。
with tf.Session() as sess:
# create initialized variables
sess.run(init)
### for each epoch, do:
### for each batch, do:
### create pre-processed batch
### run optimizer by feeding batch
### find cost and reiterate to minimize
for epoch in range(epochs):
avg_cost = 0
total_batch = int(train.shape[0]/batch_size)
for i in range(total_batch):
batch_x, batch_y = batch_creator(batch_size, train_x.shape[0], 'train')
_, c = sess.run([optimizer, cost], feed_dict = {x: batch_x, y: batch_y})
avg_cost += c / total_batch
print "Epoch:", (epoch+1), "cost =", "{:.5f}".format(avg_cost)
print "Training complete!"
# find predictions on val set
pred_temp = tf.equal(tf.argmax(output_layer, 1), tf.argmax(y, 1))
accuracy = tf.reduce_mean(tf.cast(pred_temp, "float"))
print "Validation Accuracy:", accuracy.eval({x: val_x.reshape(-1, input_num_units), y: dense_to_one_hot(val_y)})
predict = tf.argmax(output_layer, 1)
pred = predict.eval({x: test_x.reshape(-1, input_num_units)})
這將是上面代碼的輸出。
Epoch: 1 cost = 8.93566
Epoch: 2 cost = 1.82103
Epoch: 3 cost = 0.98648
Epoch: 4 cost = 0.57141
Epoch: 5 cost = 0.44550
Training complete!
Validation Accuracy: 0.952823
眼見為實,我們將預測視覺化:
img_name = rng.choice(test.filename)
filepath = os.path.join(data_dir, 'Train', 'Images', 'test', img_name)
img = imread(filepath, flatten=True)
test_index = int(img_name.split('.')[0]) - 49000
print "Prediction is: ", pred[test_index]
pylab.imshow(img, cmap='gray')
pylab.axis('off')
pylab.show()
Prediction is: 8(下圖所示:)
我們看到模型性能是相當不錯的!現在讓我們創建一個提交:
sample_submission.filename = test.filename
sample_submission.label = pred
sample_submission.to_csv(os.path.join(sub_dir, 'sub01.csv'), index=False)
終於完成了!我們剛剛創建了自己的訓練神經網路!
TensorFlow的局限性
•儘管TensorFlow功能強大,但它仍然是一個低水準庫,例如,它可以被認為是機器級語言,但對於大多數功能,你需要自己進行模組化和高級介面,如 keras。
•它仍然在繼續開發和維護。
•它取決於你的硬體規格,配置越高越好。
•不是所有語言都能使用它的API。
•TensorFlow中仍然有很多庫需要手動導入,比如OpenCL支持。
上面提到的大多數是TensorFlow開發人員的願景,他們已經制定了一個路線圖,計畫庫未來應該如何開發。
TensorFlow與其他庫
TensorFlow建立在類似的原理,如使用數學計算圖表的Theano和Torch,但是隨著分散式運算的額外支持,TensorFlow能更好地解決複雜的問題。此外,TensorFlow模型的部署已經獲得支援,這使得它更容易用於工業目的,打擊了一些商業的三庫,如Deeplearning4j、H2O和Turi。TensorFlow有用於Python,C ++和Matlab的API。最近還出現了對Ruby和R等其他語言的支援。因此,TensorFlow正試圖獲得通用語言的支援。
下一步在哪裡?
以上你看到了如何用TensorFlow構建一個簡單的神經網路,這段代碼是為了讓人們瞭解如何開始實現TensorFlow。要解決更複雜的現實生活中的問題,你必須在這篇文章的基礎上再調整一些代碼才行。
許多上述功能可以被抽象為提供無縫的端到端工作流,如果你使用scikit-learn,你可能知道一個高級庫如何抽象“底層”實現,給終端使用者一個更容易的介面。儘管TensorFlow已經提取了大多數實現,但是也有更高級的庫,如TF-slim和TFlearn。
參考資源
TensorFlow官方庫 https://github.com/tensorflow/tensorflow。
Rajat Monga(TensorFlow技術負責人) “TensorFlow為大家” 的視頻https://youtu.be/wmw8Bbb_eIE。
專門的資源列表:https://github.com/jtoy/awesome-tensorflow/#github-projects。