人人都可以做深度學習應用:入門篇

本文由雲+社區發表

作者:徐漢彬

一、人工智能和新科技革命

2017年圍棋界發生了一件比較重要事,Master(Alphago)以60連勝橫掃天下,擊敗各路世界冠軍,人工智能以氣勢如虹的姿態出現在我們人類的面前。圍棋曾經一度被稱爲“人類智慧的堡壘”,如今,這座堡壘也隨之成爲過去。從2016年三月份AlphaGo擊敗李世石開始,AI全面進入我們大衆的視野,對於它的討論變得更爲火熱起來,整個業界普遍認爲,它很可能帶來下一次科技革命,並且,在未來可預見的10多年裏,深刻得改變我們的生活。

img

其實,AI除了可以做我們熟知的人臉、語音等識別之外,它可以做蠻多有趣的事情。

例如,讓AI學習大量古詩之後寫古詩,並且可以寫出質量非常不錯的古詩。

img

又或者,將兩部設計造型不同的汽車進行融合,形成全新一種設計風格的新汽車造型。

img

還有,之前大家在朋友圈裏可能看過的,將相片轉換成對應的藝術風格的畫作。

img

當前,人工智能已經在圖像、語音等多個領域的技術上,取得了全面的突破。與此同時,另外一個問題隨之而來,如果這一輪的AI浪潮真的將會掀起新的科技革命,那麼在可預見的未來,我們整個互聯網都將發生翻天覆地的變化,深刻影響我們的生活。那麼作爲普通業務開發工程師的我,又應該以何種態度和方式應對這場時代洪流的衝擊呢?

在回答這個問題之前,我們先一起看看上一輪由計算機信息技術引領的科技革命中,過去30多年中國程序員的角色變化:

img

通過上圖可以簡總結:編程技術在不斷地發展並且走向普及,從最開始掌握在科學家和專家學者手中的技能,逐漸發展爲一門大衆技能。換而言之,我們公司內很多資深的工程師,如果帶着今天對編程和計算機的理解和理念回到1980年,那麼他無疑就是那個時代的計算機專家。

如果這一輪AI浪潮真的會帶來新的一輪科技革命,那麼我們相信,它也會遵循類似的發展軌跡,逐步發展和走向普及。如果基於這個理解,或許,我們可以通過積極學習,爭取成爲第一代AI工程師。

二、深度學習技術

這一輪AI的技術突破,主要源於深度學習技術,而關於AI和深度學習的發展歷史我們這裏不重複講述,可自行查閱。我用了一個多月的業務時間,去了解和學習了深度學習技術,在這裏,我嘗試以一名業務開發工程師的視角,以儘量容易讓大家理解的方式一起探討下深度學習的原理,儘管,受限於我個人的技術水平和掌握程度,未必完全準確。

1. 人的智能和神經元

人類智能最重要的部分是大腦,大腦雖然複雜,它的組成單元卻是相對簡單的,大腦皮層以及整個神經系統,是由神經元細胞組成的。而一個神經元細胞,由樹突和軸突組成,它們分別代表輸入和輸出。連在細胞膜上的分叉結構叫樹突,是輸入,那根長長的“尾巴”叫軸突,是輸出。神經元輸出的有電信號和化學信號,最主要的是沿着軸突細胞膜表面傳播的一個電脈衝。忽略掉各種細節,神經元,就是一個積累了足夠的輸入,就產生一次輸出(興奮)的相對簡單的裝置。

img

樹突和軸突都有大量的分支,軸突的末端通常連接到其他細胞的樹突上,連接點上是一個叫“突觸”的結構。一個神經元的輸出通過突觸傳遞給成千上萬個下游的神經元,神經元可以調整突觸的結合強度,並且,有的突觸是促進下游細胞的興奮,有的是則是抑制。一個神經元有成千上萬個上游神經元,積累它們的輸入,產生輸出。

img

人腦有1000億個神經元,1000萬億個突觸,它們組成人腦中龐大的神經網絡,最終產生的結果即是人的智能。

2. 人工神經元和神經網絡

一個神經元的結構相對來說是比較簡單的,於是,科學家們就思考,我們的AI是否可以從中獲得借鑑?神經元接受激勵,輸出一個響應的方式,同計算機中的輸入輸出非常類似,看起來簡直就是量身定做的,剛好可以用一個函數來模擬。

img

通過借鑑和參考神經元的機制,科學家們模擬出了人工神經元和人工神經網絡。當然,通過上述這個抽象的描述和圖,比較難讓大家理解它的機制和原理。我們以“房屋價格測算”作爲例子,一起來看看:

一套房子的價格,會受到很多因素的影響,例如地段、朝向、房齡、面積、銀行利率等等,這些因素如果細分,可能會有幾十個。一般在深度學習模型裏,這些影響結果的因素我們稱之爲特徵。我們先假設一種極端的場景,例如影響價格的特徵只有一種,就是房子面積。於是我們收集一批相關的數據,例如,50平米50萬、93平米95萬等一系列樣本數據,如果將這些樣本數據放到而爲座標裏看,則如下圖:

img

然後,正如我們前面所說的,我們嘗試用一個“函數”去擬合這個輸入(面積x)和輸出(價格y),簡而言之,我們就是要通過一條直線或者曲線將這些點“擬合”起來。

假設情況也比較極端,這些點剛好可以用一條“直線”擬合(真實情況通常不會是直線),如下圖:

img

那麼我們的函數是一個一次元方程f(x) = ax +b,當然,如果是曲線的話,我們得到的將是多次元方程。我們獲得這個f(x) = ax +b的函數之後,接下來就可以做房價“預測”,例如,我們可以計算一個我們從未看見的面積案例81.5平方米,它究竟是多少錢?

這個新的樣本案例,可以通過直線找到對應的點(黃色的點),如圖下:

img

粗略的理解,上面就是AI的概括性的運作方式。這一切似乎顯得過於簡單了?當然不會,因爲,我們前面提到,影響房價其實遠不止一個特徵,而是有幾十個,這樣問題就比較複雜了,接下來,這裏則要繼續介紹深度學習模型的訓練方式。這部分內容相對複雜一點,我儘量以業務工程師的視角來做一個粗略而簡單的闡述。

3. 深度學習模型的訓練方式

當有好幾十個特徵共同影響價格的時候,自然就會涉及權重分配的問題,例如有一些對房價是主要正權重的,例如地段、面積等,也有一些是負權重的,例如房齡等。

(1)初始化權重計算

那麼,第一個步其實是給這些特徵加一個權重值,但是,最開始我們根本不知道這些權重值是多少?怎麼辦呢?不管那麼多了,先給它們隨機賦值吧。隨機賦值,最終計算出來的估算房價肯定是不準確的,例如,它可能將價值100萬的房子,計算成了10萬。

(2)損失函數

因爲現在模型的估值和實際估值差距比較大,於是,我們需要引入一個評估“不準確”程度的衡量角色,也就是損失(loss)函數,它是衡量模型估算值和真實值差距的標準,損失函數越小,則模型的估算值和真實值的察覺越小,而我們的根本目的,就是降低這個損失函數。讓剛剛的房子特徵的模型估算值,逼近100萬的估算結果。

(3)模型調整

通過梯度下降和反向傳播,計算出朝着降低損失函數的方向調整權重參數。舉一個不恰當的比喻,我們給面積增加一些權重,然後給房子朝向減少一些權重(實際計算方式,並非針對單個個例特徵的調整),然後損失函數就變小了。

(4)循環迭代

調整了模型的權重之後,就可以又重新取一批新的樣本數據,重複前面的步驟,經過幾十萬次甚至更多的訓練次數,最終估算模型的估算值逼近了真實值結果,這個模型的則是我們要的“函數”。

img

爲了讓大家更容易理解和直觀,採用的例子比較粗略,並且講述深度學習模型的訓練過程,中間省略了比較多的細節。講完了原理,那麼我們就開始講講如何學習和搭建demo。

三、深度學習環境搭建

在2個月前,人工智能對我來說,只是一個高大上的概念。但是,經過一個多月的業餘時間的認真學習,我發現還是能夠學到一些東西,並且跑一些demo和應用出來的。

1. 學習的提前準備

(1)部分數學內容的複習,高中數學、概率、線性代數等部分內容。(累計花費了10個小時,挑了關鍵的點看了下,其實還是不太夠,只能讓自己看公式的時候,相對沒有那麼懵)

(2)Python基礎語法學習。(花費了3個小時左右,我以前從未寫過Python,因爲後面Google的TensorFlow框架的使用是基於Python的)

(3)Google的TensorFlow深度學習開源框架。(花費了10多個小時去看)

數學基礎好或者前期先不關注原理的同學,數學部分不看也可以開始做,全憑個人選擇。

2. Google的TensorFlow開源深度學習框架

深度學習框架,我們可以粗略的理解爲是一個“數學函數”集合和AI訓練學習的執行框架。通過它,我們能夠更好的將AI的模型運行和維護起來。

深度學習的框架有各種各樣的版本(Caffe、Torch、Theano等等),我只接觸了Google的TensorFlow,因此,後面的內容都是基於TensorFlow展開的,它的詳細介紹這裏不展開講述,建議直接進入官網查看。非常令人慶幸的是TensorFlow比較早就有中文社區了,儘管裏面的內容有一點老,搭建環境方面有一些坑,但是已經屬於爲數不多的中文文檔了,大家且看且珍惜。

TensorFlow 的中文社區

TensorFlow 的英文社區

3. TensorFlow環境搭建

環境搭建本身並不複雜,主要解決相關的依賴。但是,基礎庫的依賴可以帶來很多問題,因此,建議儘量一步到位,會簡單很多。

(1)操作系統

我搭建環境使用的機器是騰訊雲上的機器,軟件環境如下:

操作系統:CentOS 7.2 64位(GCC 4.8.5)

因爲這個框架依賴於python2.7和glibc 2.17。比較舊的版本的CentOS一般都是python2.6以及版本比較低的glibc,會產生比較的多基礎庫依賴問題。而且,glibc作爲Linux的底層庫,牽一髮動全身,直接對它升級是比較複雜,很可能會帶來更多的環境異常問題。

(2)軟件環境

我目前安裝的Python版本是python-2.7.5,建議可以採用yum install python的方式安裝相關的原來軟件。然後,再安裝 python內的組件包管理器pip,安裝好pip之後,接下來的其他軟件的安裝就相對比較簡單了。

例如安裝TensorFlow,可通過如下一句命令完成(它會自動幫忙解決一些庫依賴問題):

pip install -U tensorflow

這裏需要特別注意的是,不要按照TensorFlow的中文社區的指引去安裝,因爲它會安裝一個非常老的版本(0.5.0),用這個版本跑很多demo都會遇到問題的。而實際上,目前通過上述提供的命令安裝,是tensorflow (1.0.0)的版本了。

img

Python(2.7.5)下的其他需要安裝的關鍵組件:

  • tensorflow (0.12.1),深度學習的核心框架
  • image (1.5.5),圖像處理相關,部分例子會用到
  • PIL (1.1.7),圖像處理相關,部分例子會用到

除此之後,當然還有另外的一些依賴組件,通過pip list命令可以查看我們安裝的python組件:

  • appdirs (1.4.0)
  • backports.ssl-match-hostname (3.4.0.2)
  • chardet (2.2.1)
  • configobj (4.7.2)
  • decorator (3.4.0)
  • Django (1.10.4)
  • funcsigs (1.0.2)
  • image (1.5.5)
  • iniparse (0.4)
  • kitchen (1.1.1)
  • langtable (0.0.31)
  • mock (2.0.0)
  • numpy (1.12.0)
  • packaging (16.8)
  • pbr (1.10.0)
  • perf (0.1)
  • PIL (1.1.7)
  • Pillow (3.4.2)
  • pip (9.0.1)
  • protobuf (3.2.0)
  • pycurl (7.19.0)
  • pygobject (3.14.0)
  • pygpgme (0.3)
  • pyliblzma (0.5.3)
  • pyparsing (2.1.10)
  • python-augeas (0.5.0)
  • python-dmidecode (3.10.13)
  • pyudev (0.15)
  • pyxattr (0.5.1)
  • setuptools (34.2.0)
  • six (1.10.0)
  • slip (0.4.0)
  • slip.dbus (0.4.0)
  • tensorflow (1.0.0)
  • urlgrabber (3.10)
  • wheel (0.29.0)
  • yum-langpacks (0.4.2)
  • yum-metadata-parser (1.1.4)

按照上述提供的來搭建系統,可以規避不少的環境問題。

搭建環境的過程中,我遇到不少問題。例如:在跑官方的例子時的某個報錯,AttributeError: ‘module’ object has no attribute ‘gfile’,就是因爲安裝的TensorFlow的版本比較老,缺少gfile模塊導致的。而且,還有各種各樣的。(不要問我是怎麼知道的,說多了都是淚啊~)

更詳細的安裝說明:Installing TensorFlow on Ubuntu

(3)TensorFlow環境測試運行

測試是否安裝成功,可以採用官方的提供的一個短小的例子,demo生成了一些三維數據, 然後用一個平面擬合它們(官網的例子採用的初始化變量的函數是initialize_all_variables,該函數在新版本里已經被廢棄了):

#!/usr/bin/python
#coding=utf-8

import tensorflow as tf
import numpy as np

# 使用 NumPy 生成假數據(phony data), 總共 100 個點.
x_data = np.float32(np.random.rand(2, 100)) # 隨機輸入
y_data = np.dot([0.100, 0.200], x_data) + 0.300

# 構造一個線性模型
# 
b = tf.Variable(tf.zeros([1]))
W = tf.Variable(tf.random_uniform([1, 2], -1.0, 1.0))
y = tf.matmul(W, x_data) + b

# 最小化方差
loss = tf.reduce_mean(tf.square(y - y_data))
optimizer = tf.train.GradientDescentOptimizer(0.5)
train = optimizer.minimize(loss)

# 初始化變量,舊函數(initialize_all_variables)已經被廢棄,替換爲新函數
init = tf.global_variables_initializer()

# 啓動圖 (graph)
sess = tf.Session()
sess.run(init)

# 擬合平面
for step in xrange(0, 201):
    sess.run(train)
    if step % 20 == 0:
        print step, sess.run(W), sess.run(b)

# 得到最佳擬合結果 W: [[0.100  0.200]], b: [0.300]

運行的結果類似如下:

img

經過200次的訓練,模型的參數逐漸逼近最佳擬合的結果(W: [[0.100 0.200]], b: [0.300]),另外,我們也可以從代碼的“風格”中,瞭解到框架樣本訓練的基本運行方式。雖然,官方的教程後續會涉及越來越多更復雜的例子,但從整體上看,也是類似的模式。

img

步驟劃分

  • 準備數據:獲得有標籤的樣本數據(帶標籤的訓練數據稱爲有監督學習);
  • 設置模型:先構建好需要使用的訓練模型,可供選擇的機器學習方法其實也挺多的,換而言之就是一堆數學函數的集合; 損失函數和優化方式:衡量模型計算結果和真實標籤值的差距;
  • 真實訓練運算:訓練之前構造好的模型,讓程序通過循環訓練和學習,獲得最終我們需要的結果“參數”;
  • 驗證結果:採用之前模型沒有訓練過的測試集數據,去驗證模型的準確率。

其中,TensorFlow爲了基於python實現高效的數學計算,通常會使用到一些基礎的函數庫,例如Numpy(採用外部底層語言實現),但是,從外部計算切回到python也是存在開銷的,尤其是在幾萬幾十萬次的訓練過程。因此,Tensorflow不單獨地運行單一的函數計算,而是先用圖描述一系列可交互的計算操作流程,然後全部一次性提交到外部運行(在其他機器學習的庫裏,也是類似的實現)。

所以,上述流程圖中,藍色部分都只是設置了“計算操作流程”,而綠色部分開始纔是真正的提交數據給到底層庫進行實際運算,而且,每次訓練一般是批量執行一批數據的。

此文已由騰訊雲+社區在各渠道發佈

獲取更多新鮮技術乾貨,可以關注我們騰訊雲技術社區-雲加社區官方號及知乎機構號

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章