深度神經網絡是一個多層次的網絡模型,包含了:輸入層,隱藏層和輸出層,其中隱藏層是最重要也是深度最多的,經過TensorFlow,python代碼能夠構建神經網絡層函數,好比咱們稱之爲add_layer()函數,因爲神經網絡層的工做原理是一層的神經元處理完成後獲得一個結果,而後傳遞給下一個神經元,這就相似於函數的return與參數變量,因此最終代碼的模型應該以下圖所示:python
經過add_layer的層層嵌套,實現上一個add_layer的結果返回給下一個add_layer做爲參數變量。網絡
在深度神經網絡中,激勵函數的概念很是重要,TensorFlow已經包含了許多的激勵函數。dom
什麼是激勵函數呢?機器學習
在神經網絡中,隱層和輸出層節點的輸入和輸出之間具備函數關係,這個函數稱爲激勵函數。常見的激勵函數有:線性激勵函數、閾值或階躍激勵函數、S形激勵函數、雙曲正切激勵函數和高斯激勵函數等。(百度百科)函數
簡而言之:隱藏層在處理後獲得一個值,這個值要麼直接傳遞給下一層,要麼先處理一下再傳遞下一層,這個處理的過程就是激勵函數。從數學角度說,激勵就是上一層輸出和下一層輸入存在一種映射關係,即:學習
F (上一層結果->下一層輸入)測試
爲什麼須要激勵函數?優化
想起上一回中介紹了使用TensorFlow求一次函數的係數與偏量的方法,那並無用到激勵函數,是由於輸入與輸出的數據呈現爲線性關係,也就是y=kx+b這樣的簡單關係,但實際的問題中輸入數據與輸出數據可能會存在某種非線性關係。人工智能
如圖要區分藍紅點,可使用線性函數y>kx+b或者kx+b>y讓神經網絡快速學會分類spa
如圖再要區分藍紅點,使用線性函數是作不到的,固然能夠選擇直接使用非線性函數來處理,在TensorFlow中亦可給出非線性計算的訓練單元,可是另外一種更爲取巧的辦法就是給線性函數嵌套一個非線性函數,使得原來的線性關係變成非線性關係,這就使得隱藏層處理的關注點放在了權重k與偏量b上,這就是激勵函數的做用!他把原本複雜的問題簡化爲只調整兩個簡單的參數上來。
爲何須要分層,深度對學習能力有什麼影響?
首先既然說到深度學習,隱藏層應該是多層纔算「深」,分層就是爲了提升學習能力嘛!那麼分層如何作到了學習能力提高?
假定以下場景,咱們有三層隱藏層,每一個層都有一個神經元,咱們對神經元在進行簡化,就說他是一個函數y=kx+b,咱們得出下圖:
圖中每一層都會產生出一個不一樣的f(x)=kx+b函數,並且不一樣層的函數的係數和偏量都是不同的,經過神經元鏈接將這些f(x)串聯起來,這有點像PHP裏的鏈式操做,並且圖中只是簡單的線性關係(正如前面所述這些y函數外層還能夠嵌套一個激勵函數作非線性化轉換)。
神經網絡存在一個「逆向工程」,就是當最終輸出神經元發現與真實值有差距時就會反向傳遞,經過調整每一層裏的函數來糾正,調整的就是係數k和偏量b,調整出來的k,b在不一樣層中也是不同的,具體如何調整這就是個黑盒,人類沒法掌控,但他最後就是會到達一個合適的值,這個專業名詞叫作:擬合!
綜上所述:層數越多,k,b可能性越多,函數越多,那麼所能表明的可能性越多,從數學上說,無窮多的可能性能夠表達宇宙一切信息。
Talking is cheap, show me the code!
如下咱們給出一個實際的案例,實現上述所述的神經網絡設計和構建過程:
import tensorflow as tf import numpy as np #the function to create layer def add_layer(inputs,in_size,out_size,activation_function=None): w = tf.Variable(tf.random_normal([in_size,out_size])) b = tf.Variable(tf.zeros([1,out_size])+0.1) f = tf.matmul(inputs,w) + b if activation_function is None: outputs = f else: outputs = activation_function(f) return outputs #create test data(as real data) x_data = np.linspace(-1,1,300,dtype=np.float32)[:,np.newaxis] noise = np.random.normal(0,0.05,x_data.shape) y_data = np.square(x_data)-0.5+noise #give tensorflow input placeholder xs = tf.placeholder(tf.float32,[None,1]) ys = tf.placeholder(tf.float32,[None,1]) l1 = add_layer(x_data,1,10,activation_function=tf.nn.relu) prediction = add_layer(l1,10,1,activation_function=None) loss = tf.reduce_mean(tf.reduce_sum(tf.square(y_data-prediction),reduction_indices=[1])) train = tf.train.GradientDescentOptimizer(0.1).minimize(loss) init = tf.global_variables_initializer() sess = tf.Session() sess.run(init) for i in range(1000): sess.run(train,feed_dict={xs:x_data,ys:y_data}) if(i % 50 == 0): print sess.run(loss,feed_dict={xs:x_data,ys:y_data})
額,不要在乎代碼中我垃圾的英語註釋。
咱們簡單分析一下代碼的含義,其實若是讀懂了代碼前所述的理論概念,代碼就能一下理解了。
首先,咱們開頭定義了一個create_layer函數,這個函數做用是建立一個神經網絡層!參數變量是:輸入值,輸入值的矩陣行數,矩陣列數,激勵函數。這裏爲何是矩陣?由於實際處理的現實問題所攜帶的數據是多個維度的,人類通常能理解到三維,三維以上計算機能夠理解。不用過於在乎這個細節,之後結合實際問題解釋爲何是矩陣的y=kx+b運算,如今要記住x是個多維矩陣就行了,不是簡單的數。
create_layer內部作了什麼?
函數內部首先是使用numpy給出了隨機數,這個隨機數也是個矩陣,表明了係數k與偏量b,tf.Varible()讓TensorFlow學習過程當中改變這兩個變量(叫作權重,偏量調整),而後tf.matmul進行了矩陣的運算,給出這一層的輸出值,if—else語句負責判斷是否要給輸出值套上一個激勵函數,將其非線性化。
placeholder幹什麼的?
因爲神經網絡的學習要求咱們輸入測試的數據,placeholder的做用是提供輸入數據的空位,實際問題產生的原始數據丟入到placeholder中,而後被一個叫feed_dict的對象收集到TensorFlow當中,再交給神經網絡去處理獲得一個預測結果。placeholder就是是原始數據的入口。
loss是什麼?
損失值,用於優化訓練過程,很簡單,咱們要讓學習結果和真實結果接近,就要求他們之間的差愈來愈小,這個值就表明了他們的「差」,這個差可不是數學上的減減就行的,能夠看到咱們用到了:
tf.reduce_sum(tf.square(y_data-prediction),reduction_indices=[1])
這麼長的計算方式,實際值和真實值的差的平方,而後還累加了矩陣中的差平方值,很複雜呢。反正這個值越小越好就對了。
控制檯輸出結果
運行以上python代碼,獲得的是損失值,這是爲了驗證TensorFlow在學習過程當中是否是真的在優化本身,loss愈來愈小就是優化了:
確認:損失值減少,學習優化了!
我的以爲如今的深度學習的人工智能和傳統的人工智能對比,就好像物理上的「量子力學」與「相對論」,怎麼說?傳統的人工智能認爲機器學習過程是正向的,人類爲機器設定好規則,在代碼中呈現爲if then if then......的特色,而深度學習是隻給出輸入值,讓機器去「推理」出一個結果,與正確結果對比,錯了就逆向去從新修改「推理」的邏輯,這就是一個無窮多可能的事情,這有點像「量子力學」中只有當觀察量子世界中某一個現象時,才能獲得一個肯定的狀態(結果),不觀察時,這個魔盒中的可能性是無窮多的,答案落在任何一塊區域中,怎麼樣,是否是很神奇?再通俗比喻一下,這就像武功的最高境界「無招勝有招」!只要能贏就是厲害!經過不斷的輸,修改招式,最後取得勝利,成爲大師的時候固定招式已經不復存在了。