上一節說到,大多的AI問題,會有不少個變量,這裏深刻的解釋一下這個問題。
好比說某個網站要作用戶行爲分析,從而指導網站建設的改進。一般而言若是沒有行爲分析,並不須要採集用戶太多的數據。
好比用戶註冊,最少只須要用戶名、用戶密碼就夠了。隨後好比爲了當用戶過生日的時候,自動給用戶發送一封賀卡(潛臺詞,咱們可能須要給用戶推送廣告),咱們再增長兩項生日日期和郵箱地址。再下來國家規定網站註冊必須實名制,咱們可能又增長了用戶姓名和身份證號碼,可能還須要增長用戶手機號碼,用於同移動通訊部門打通,驗證用戶實名制的真實性。這樣一共是七個數據字段(僅爲示例,事實比本例確定要複雜不少倍)。
隨後經過網站的運營,用戶數不斷增長,到了某一天,網站的技術人員發現,數據量太大了,併發也過高了,一組服務器已經沒法負擔網站的運營。最重要其中的基礎數據庫也變得太大,系統沒法容納,須要分庫、集羣的新技術,才能保證網站的運營。
從網站的運維來說,這的確是一項重要的技術改進。但從「機器學習」的角度看,這些數據量的變化,並無什麼不一樣,可能在算法上,也不須要有太大的改變。因此嚴格上講,這樣的數據管理,還不能叫大數據。
咱們繼續向下看,爲了進行用戶行爲的分析。咱們還要增長不少用戶數據的採集點。好比用戶每次訪問網頁的IP地址、用戶的點擊習慣、每一個頁面停留的時間、在頁面上習慣點哪些位置的連接、操做上有什麼習慣、用戶的設備是什麼型號、用戶每次上網在什麼時間段,這樣須要關注的數據,咱們還能列出不少。甚至可能會付費去第三方的公司購買不少其它的信息,好比個人用戶還喜歡在什麼網站停留,停留在其它網站的時候關注了什麼內容,最近購買了什麼東西等等信息。
這些信息有下面幾個特色:html
還有一些數據,天生就是多維的,好比圖片識別。每幅圖片,數字化保存到電腦以後,極可能是一大筆數據,好比某副照片320x240分辨率,那就至關於320x240x(RGB 3色)=230400維的一個數據集。這個在後面講到具體案例的時候還會說到。python
在數據維度很是多的時候,也就是咱們的方程可能有n個變量(n值很大)的時候,原有的公式、解法都已經失效了。多是計算量過大致使速度沒法接受,也多是空間需求太大致使咱們的計算機沒法作到,因此咱們須要有新的辦法來完成解方程----也就是機器學習的過程。
梯度降低法是咱們經常使用的一種方式,實際上這種算法包括其針對性或者改進型算法有不少種,應當稱爲梯度降低法家族。好比批量梯度降低法(BGD)、隨機梯度降低法(SGD)、小批量梯度降低法(MBGD)等。
這是統計學家和經濟學家在大量數據分析過程當中經常使用的手段,因此其實早期的機器學習專家每每也是來自於統計專業。
在大多機器學習的課程中,對梯度降低法及相關算法的講解是最重要的一部分,但如今狀況有所改變。TensorFlow以及其它一些流行框架,已經內置了函數用於運行梯度降低法及其它經常使用算法,技術人員即使不瞭解這些知識,也可以上手機器學習項目。因此本來我計劃略去這部分算法的細節。但發現實際上仍是不能,由於我看到了不少在TensorFlow官方樣例運行很好,但到了具體項目中就失敗的例子,歸根結底仍是對算法自己瞭解太少,碰到問題不知道如何下手解決。
因此幾經修改,我決定既不略去,也再也不做爲重點。這裏用僞代碼的方式來簡略描述一下這個算法的工做流程:算法
這裏的講解,把先前的常量a/b替換成了Θ0/Θ1,緣由是,咱們未來的參數集可不會只有兩個這麼少,多是n個,但願你明白這裏只是在降維模擬一個過程。
這張圖描述了梯度降低法解方程的過程。須要說明的是圖中手繪的部分,就是咱們一開始隨機取了初始值,也就是初始點,而後逐步的梯度降低,直到代價函數值最小的時候,獲得兩個未知數的解。
同時從圖中能夠看出來,由於初始值的不一樣及步長的不一樣,梯度降低法極可能會陷入某個局部最小值,這時候梯度降低法由於已經最小,向周圍任何一點繼續都沒法獲得更小的代價函數值,從而終止了繼續求解。但實際上離最優解還有很大差距.下面這張圖是降維到2維的一張示意圖,能夠看的更清楚:
圖中的G點是最優解,A/B/C/D點都是局部最優解。當咱們的變量不少的時候,很高的維度使得獲取全局最優解每每是很不容易的。
陷入局部最優解的時候實際上只有這樣幾個選擇:1.隨機產生另一組初始值,同時增長嘗試求解過程的次數,從而獲得不一樣的解,取其中最好的值;2.變動梯度降低步長;3.變動或者優化算法。數據庫
局部最優解是《機器學習》算法調優重點之一bash
具體的算法自己是純粹的數學問題,有網友收集、撰寫的參考資料在最下面的參考連接裏面,寫的很不錯。我建議有志於算法研究的朋友必定仔細閱讀。剛纔說了,實際上在不少《機器學習》課程中,這部分佔了至關的篇幅,可見其重要性。從這個角度上說,現代機器學習的框架一方面下降了學習的門檻,不須要懂梯度降低法也能使用機器學習,另一方面,是否是也就此屏蔽了不少人真正上升的空間呢?服務器
行文這麼長了,終於要進入TensorFlow的世界。估計你讀的很辛苦,我盡力用非專業的語言來解釋不少基礎的概念和前因後果,忍得也很辛苦。
在正式例子以前,再補充一個「機器學習」的重要概念,數據「規範化」。
咱們注意到了,爲了進行「機器學習」,咱們從不少維度獲取相關數據,創建複雜的數學模型,以求獲得比較好的結果。
但這些方方面面的數據,差異很是大,好比有價格因素,取值範圍極可能是幾千到上億;也極可能是面積因素,取值幾十到幾百。未來還可能有朝向因素,若是把方向數字化,可能不過是1-4;相似的還不少,好比樓層數。
總的來講,這些數字如此大的量級差距,在一個試圖創建較爲通用(注:後面還會對「較爲通用」這個詞再詳細解釋)的數學化公式的算法中,會對結果產生不可估量的影響。好比面積多1平米或者少1平米,原本應當對最終房價有很大的影響。但對於一樣的數字,計算機並不理解這個數量級跟另一個參數數量級之間的差異,它看起來增長1平米跟增長1塊錢是同樣的。最後的結果,不可避免的會傾向數字大的參數所致使的影響,從而讓計算結果徹底不可用。
所以,全部採集到的數據在真正進入運算以前,首先要規範化,比較通用的規範化方式,是計算某個具體值在該參量取值範圍中的比例值,讓最終的結果是0-1之間的浮點小數,這樣能夠保證全部的參量,最終是工做在同一個量級維度上,從而保證結果的正確性。併發
數據的「規範化」,是影響「機器學習」精度的重要因素,絕對不可省略。框架
終於能夠進入源代碼部分了,我習慣於在代碼中加入詳細的註釋讓你作到每一行都看懂,我認爲這是重要的學習手段之一。
源碼中隨機生成了100套住房面積和對應價格的數據集,而後經過TensorFlow使用內置的梯度降低法解出每平米價格及基礎費用兩個係數。在這裏要求讀者已經有python的基礎知識,由於至少當前,機器學習的首選語言仍是python。運維
#!/usr/bin/env python # -*- coding=UTF-8 -*- #本代碼在mac電腦,python2.7環境測試經過 #第一行是mac/Linux系統腳本程序的標誌,表示從環境參量中尋找python程序解釋器來執行本腳本 #省去了每次在命令行使用 python <腳本名> 這樣的執行方式 #第二行表示本腳本文本文件存盤使用的代碼是utf-8,而且字符串使用的編碼也是utf-8, #在本源碼中,這一點其實沒有什麼區別,但若是須要中文輸出的時候,這一行就必需要加了。 #引入TensorFlow庫 import tensorflow as tf #引入數值計算庫 import numpy as np #使用 NumPy 生成假數據集x,表明房間的平米數,這裏的取值範圍是0-1的浮點數, #緣由請看正文中的說明,屬因而「規範化」以後的數據 # 生成的數據共100個,式樣是100行,每行1個數據 x = np.float32(np.random.rand(100,1)) #咱們假設每平米0.5萬元,基礎費用0.7萬,這個數值也是規範化以後的,僅供示例 #最終運行的結果,應當求出來0.5/0.7這兩個值表明計算成功 #計算最終房價y,x和y一同當作咱們的樣本數據 # np.dot的意思就是向量x * 0.5 y = np.dot(x,0.5) + 0.7 #---------------------------------數據集準備完成 #如下使用TensorFlow構建數學模型,在這個過程當中, #直到調用.run以前,實際上都是構造模型,而沒有真正的運行。 #這跟上面的numpy庫每一次都是真正執行是大相徑庭的區別 # 請參考正文,咱們假定房價的公式爲:y=a*x+b #tf.Variable是在TensorFlow中定義一個變量的意思 #咱們這裏簡單起見,人爲給a/b兩個初始值,都是0.3,注意這也是至關於規範化以後的數值 b = tf.Variable(np.float32(0.3)) a = tf.Variable(np.float32(0.3)) #這是定義主要的數學模型,模型來自於上面的公式 #注意這裏必須使用tf的公式,這樣的公式纔是模型 #上面使用np的是直接計算,而不是定義模型 # TensorFlow的函數名基本就是完整英文,你應當能讀懂 y_value = tf.multiply(x,a) + b # 這裏是代價函數,同咱們文中所講的惟一區別是用平方來取代求絕對值, #目標都是爲了獲得一個正數值,功能徹底相同, #平方計算起來會更快更容易,這種方式也稱爲「方差「 loss = tf.reduce_mean(tf.square(y_value - y)) # TensorFlow內置的梯度降低算法,每步長0.5 optimizer = tf.train.GradientDescentOptimizer(0.5) # 代價函數值最小化的時候,表明求得解 train = optimizer.minimize(loss) # 初始化全部變量,也就是上面定義的a/b兩個變量 init = tf.global_variables_initializer() #啓動圖 sess = tf.Session() #真正的執行初始化變量,仍是老話,上面只是定義模型,並無真正開始執行 sess.run(init) #重複梯度降低200次,每隔5次打印一次結果 for step in xrange(0, 200): sess.run(train) if step % 5 == 0: print step, sess.run(loss),sess.run(a), sess.run(b)
隨後咱們看看上面腳本運行的結果:dom
0 0.017659416 0.56524247 0.7991155 5 4.084394e-06 0.50660795 0.6963032 10 1.9465895e-06 0.5046281 0.697532 15 9.344591e-07 0.50320655 0.69828993 20 4.4858396e-07 0.5022217 0.69881517 25 2.1534281e-07 0.5015393 0.69917905 30 1.0337125e-07 0.5010665 0.6994312 35 4.9617547e-08 0.5007389 0.69960594 40 2.3823773e-08 0.500512 0.69972694 45 1.1437169e-08 0.50035477 0.6998108 50 5.4911653e-09 0.5002458 0.6998689 55 2.6369513e-09 0.50017035 0.69990915 60 1.2654721e-09 0.500118 0.69993705 65 6.075896e-10 0.5000818 0.69995636 70 2.9137154e-10 0.5000566 0.69996977 75 1.4008027e-10 0.5000393 0.69997907 80 6.7331245e-11 0.50002724 0.69998544 85 3.2336054e-11 0.5000189 0.6999899 90 1.5535804e-11 0.5000131 0.699993 95 7.4518525e-12 0.50000906 0.69999516 100 3.5502267e-12 0.50000626 0.69999665 105 1.648246e-12 0.5000043 0.6999977 110 8.017054e-13 0.500003 0.6999984 115 3.877787e-13 0.5000021 0.6999989 120 1.8626878e-13 0.50000143 0.6999992 125 8.9173115e-14 0.500001 0.69999945 130 4.515499e-14 0.5000007 0.69999963 135 2.1138646e-14 0.5000005 0.69999975 140 1.20437e-14 0.50000036 0.6999998 145 1.20437e-14 0.50000036 0.6999998 150 1.20437e-14 0.50000036 0.6999998 155 1.20437e-14 0.50000036 0.6999998 160 1.20437e-14 0.50000036 0.6999998 165 1.20437e-14 0.50000036 0.6999998 170 1.20437e-14 0.50000036 0.6999998 175 1.20437e-14 0.50000036 0.6999998 180 1.20437e-14 0.50000036 0.6999998 185 1.20437e-14 0.50000036 0.6999998 190 1.20437e-14 0.50000036 0.6999998 195 1.20437e-14 0.50000036 0.6999998
由於數據集是隨機產生的,因此上面結果每次運行都會不一樣,但基本上在150步之內都能有效收斂,請看打印出來的兩個結果值,也是很使人滿意的。
(待續...)
(原創博文,謝絕一切商業轉載,我的轉載請註明出處。)