【一】零基礎入門深度學習:用numpy實現神經網絡訓練

(給機器學習算法與Python學習加星標,提升AI技能) 

作者 | 畢然 百度深度學習技術平臺部主任架構師

內容來源 | 百度飛槳深度學習集訓營

本文轉自飛槳PaddlePaddle

本課程是百度官方開設的零基礎入門深度學習課程,主要面向沒有深度學習技術基礎或者基礎薄弱的同學,幫助大家實現從0到1的跨越。從本課程中,你將學習到:

  1. 深度學習基礎知識

  2. numpy實現神經網絡構建和梯度下降算法

  3. 計算機視覺領域主要方向的原理、實踐

  4. 自然語言處理領域主要方向的原理、實踐

  5. 個性化推薦算法的原理、實踐

本文總結了畢然老師的講課要點,不免疏漏一些生動的講課案例,感興趣的同學可從文末鏈接中直接觀看課程。

01

深度學習介紹

對於深度學習初學者來說,容易遇到三個入門級問題:

  1. 人工智能、機器學習、深度學習三者之間關係是什麼?

  2. 一般的機器學習方法是什麼?

  3. 爲什麼那麼多人看好深度學習,其未來的發展趨勢是什麼?

本次課程在第一講中則優先解決這些問題。首先對第一個問題,以人工智能、機器學習、深度學習三者的關係開始。三者覆蓋的技術範疇是逐層遞減的,人工智能是最寬泛的概念,機器學習則是實現人工智能的一種方式,也是目前較有效的方式。深度學習是機器學習算法中最熱的一個分支,在近些年取得了顯著的進展,並代替了多數傳統機器學習算法。所以,三者的關係可用下圖表示,人工智能 > 機器學習 > 深度學習。

圖1:人工智能、機器學習和深度學習三者之間的概念範圍

其次,對於第二個問題,一般的機器學習方法是什麼?

課程以“機器從牛頓第二定律實驗中學習知識”爲案例,生動的講解了機器學習(監督學習)到底是怎樣的一種技術方法。

舉例類比,機器如一個機械的學生一樣,只能通過嘗試答對(最小化損失)大量的習題(已知樣本)來學習知識(模型參數w),期望用學習到的知識w組成完整的模型,能回答不知道答案的考試題(未知樣本)。最小化損失是模型的優化目標,實現損失最小化的方法稱爲優化算法,也稱爲尋解算法(找到使得損失函數最小的參數解)。參數和輸入X組成公式的基本結構稱爲假設。

在中學期間,傾斜滑動法計算重力加速度時,基於對物體重量和作用力數據的觀測,我們提出的是線性假設,即作用力和加速度是線性關係。牛頓第二定律的驗證過程也是機器學習的參數確定過程。由此可見,模型假設,評價函數(損失/優化目標)和優化算法是構成一個模型的三個部分。

圖2:學習確定參數的方法

最後以講解歷史課的形式,對深度學習的歷史做了簡單的介紹,

圖3:深度學習有悠久的發展歷史,但在2010年後才逐漸成熟。

在深度學習框架出現之前,機器學習工程師處於手工業作坊生產的時代。爲了完成建模,工程師需要儲備大量數學知識,併爲特徵工程工作積累大量行業知識。每個模型是極其個性化的,建模者如同手工業者一樣,將自己的積累形成模型的“個性化簽名”。而今,“深度學習工程師”進入了工業化大生產時代。只要掌握深度學習必要但少量的理論知識,掌握Python編程即可以在深度學習框架實現極其有效的模型,甚至與該領域最領先的實現模型不相上下。建模這個被“老科學家”們長期把持的建模領域面臨着顛覆,也是新入行者的機遇。

02

用Python搭建神經網絡

實踐出真知,理論知識說的天花亂墜也不如多寫幾行代碼。瞭解到大多數用戶即使使用一些深度學習框架搭建出了一個神經網絡,但是對神經網絡和梯度下降算法理解並不深刻。針對學員的訴求,本次課程增加了使用numpy構建神經網絡、實現梯度下降的實踐課程。本次實驗實現波士頓房價預測的迴歸模型。

應用於不同場景的深度學習模型具備一定的通用性,均分爲五個步驟來完成模型的構建和訓練,使用numpy實現神經網絡也不外乎如此,步驟如下:

  • 數據處理:從本地文件或網絡地址讀取數據,並做預處理操作,如校驗數據的正確性等。

  • 模型設計:完成網絡結構的設計(模型要素1),相當於模型的假設空間,即模型能夠表達的關係集合。

  • 訓練配置:設定模型採用的尋解算法(模型要素2),即優化器,並指定計算資源。

  • 訓練過程:循環調用訓練過程,每輪均包括前向計算 、損失函數(優化目標,模型要素3)和後向傳播這三個步驟。

  • 保存模型:將訓練好的模型保存,以備預測時調用。

下面使用Python編寫預測波士頓房價的模型,一樣遵循這樣的五個步驟。正是由於這個建模和訓練的過程存在通用性,即不同的模型僅僅在模型三要素上不同,而五個步驟中的其它部分保持一致,深度學習框架纔有用武之地。

數據處理與讀取

首先進行數據處理,完成數據集劃分、數據歸一化,以及構建數據讀取生成器。代碼如下:

 1def load_data():
 2# 從文件導入數據
 3    datafile =  ./work/housing.data 
 4    data = np.fromfile(datafile, sep=   )
 5# 每條數據包括14項,其中前面13項是影響因素,第14項是相應的房屋價格中位數
 6    feature_names = [  CRIM ,  ZN ,  INDUS ,  CHAS ,  NOX ,  RM ,  AGE , 
 7 DIS ,  RAD ,  TAX ,  PTRATIO ,  B ,  LSTAT ,  MEDV  ]
 8    feature_num = len(feature_names)
 9# 將原始數據進行Reshape,變成[N, 14]這樣的形狀
10    data = data.reshape([data.shape[0] // feature_num, feature_num])
11# 將原數據集拆分成訓練集和測試集
12# 這裏使用80%的數據做訓練,20%的數據做測試
13# 測試集和訓練集必須是沒有交集的
14    ratio = 0.8
15    offset = int(data.shape[0] * ratio)
16    training_data = data[:offset]
17# 計算train數據集的最大值,最小值,平均值
18    maximums, minimums, avgs = training_data.max(axis=0), training_data.min(axis=0), 
19                                 training_data.sum(axis=0) / training_data.shape[0]
20# 對數據進行歸一化處理
21for i in range(feature_num):
22
23#print(maximums[i], minimums[i], avgs[i])
24        data[:, i] = (data[:, i] - avgs[i]) / (maximums[i] - minimums[i])
25
26# 訓練集和測試集的劃分比例
27    training_data = data[:offset]
28    test_data = data[offset:]
29return training_data, test_data

構建神經網絡

將波士頓房價預測輸出的過程以“類和對象”的方式來描述,實現的方案如下所示。類成員變量有參數 w 和 b,並寫了一個forward函數(代表“前向計算”)完成上述從特徵和參數到輸出預測值的計算過程。

 1class Network(object):
 2    def __init__(self, num_of_weights):
 3        # 隨機產生w的初始值
 4        # 爲了保持程序每次運行結果的一致性,
 5        # 此處設置固定的隨機數種子
 6        np.random.seed(0)
 7        self.w = np.random.randn(num_of_weights, 1)
 8        self.b = 0.
 9    def forward(self, x):
10        z = np.dot(x, self.w) + self.b
11

目前已經實現了房價預測模型的前向過程,但是如何知道預測的結果呢,假設預測值爲而真是房價爲,這時我們需要有某種指標來衡量預測值跟真實值之間的差距。對於迴歸問題,最常採用的衡量方法是使用均方誤差作爲評價模型好壞的指標,具體定義如下:

上式中的(簡記爲: ) 通常也被稱作損失函數,它是衡量模型好壞的指標,在迴歸問題中均方誤差是一種比較常見的形式。

由於實現的房價預測模型的權重是隨機初始化的,這個權重參數處在模型極小值的概率幾乎爲0,我們需要使用梯度下降算法不斷更新權重,直到該權重處於模型的極小值或最小值附近。

03

numpy實現梯度下降算法

當使用深度學習框架實現的時候,這部分是不需要我們手動實現的。但是不代表我們不需要去了解它,本次課程以瞎子下坡的方式爲例,講解了梯度下降的基本原理和使用numpy實現梯度下降。

前文已提到,構建機器學習模型的首要是從一個假設空間,構建算法,去達到這個假設空間的最優值。以下圖爲例,

圖4:梯度下降方向示意圖

從隨機初始化的點達到坡底(最優值)的過程,特別類似於一位想從山峯走到坡谷的盲人,他看不見坡谷在哪(無法逆向求解出Loss導數爲0時的參數值),但可以伸腳探索身邊的坡度(當前點的導數值,也稱爲梯度)。那麼,求解Loss函數最小值可以“從當前的參數取值,一步步的按照下坡的方向下降,直到走到最低點”實現。

現在我們要找出一組的值,使得損失函數最小,實現梯度下降法的方案如下:

  • 隨機的選一組初始值,例如: 

  • 選取下一個點使得 

  • 重複上面的步驟2,直到損失函數幾乎不再下降

上面我們講過了損失函數的計算方法,公式定義損失函數如下:

其中是網絡對第個樣本的預測值

根據公式,可以計算出的偏導數

從導數的計算過程可以看出,因子被消掉了,這是因爲二次函數求導的時候會產生因子,這也是我們將損失函數改寫的原因

這裏我們感興趣的是

則可以在Network類中定義如下的梯度計算函數。

梯度計算公式

藉助於numpy裏面的矩陣操作,我們可以直接對所有 一次性的計算出13個參數所對應的梯度來

公式看不懂沒關係,本次課程主要以理論和實踐結合的方案進行。且看下述代碼如何實現梯度計算,網絡訓練和參數更新。

 1def gradient(self, x, y):
 2    z = self.forward(x)
 3    gradient_w = (z-y)*x
 4    gradient_w = np.mean(gradient_w, axis=0)
 5    gradient_w = gradient_w[:, np.newaxis]
 6    gradient_b = (z - y)
 7    gradient_b = np.mean(gradient_b)
 8    return gradient_w, gradient_b
 9def update(self, graident_w5, gradient_w9, eta=0.01):
10    net.w[5] = net.w[5] - eta * gradient_w5
11    net.w[9] = net.w[9] - eta * gradient_w9
12def train(self, x, y, iterations=100, eta=0.01):
13    points = []
14    losses = []
15    for i in range(iterations):
16        points.append([net.w[5][0], net.w[9][0]])
17        z = self.forward(x)
18        L = self.loss(z, y)
19gradient_w, gradient_b = self.gradient(x, y)
20        gradient_w5 = gradient_w[5][0]
21        gradient_w9 = gradient_w[9][0]
22        self.update(gradient_w5, gradient_w9, eta)
23        losses.append(L)
24        if i % 50 == 0:
25            print( iter {}, point {}, loss {} .format(i, [net.w[5][0], net.w[9][0]], L))
26    return points, losses
27

運行代碼後,從下面這個圖裏可以清晰的看到損失函數的下降過程。

圖5:損失函數下降過程

以機器學習深度學習概述開篇,講解了深度學習的基礎知識,通過使用numpy實現房價預測模型,詳細講解了構建深度學習模型的五個步驟,以及梯度下降的基本原理、如何使用numpy實現梯度下降等內容。

掃碼或點擊鏈接觀看課程及錄播視頻:https://aistudio.baidu.com/aistudio/course/introduce/888

本課程的實驗代碼可見:https://github.com/PaddlePaddle/tutorials

推薦閱讀
60分鐘詳解Bert原理及京東商城的應用實踐

勿謝!你需要的NumPy基礎都在這了

2020全球頂尖計算機科學家排名發佈:兩位華人學者入全球前10,Top 1000華人學者過百
曲線救國:提高github下載速度到2MB/s

PyTorch官方教程大更新:增加標籤索引,更加新手友好

必讀!53個Python經典面試題詳解


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