深度學習的六個重要算法

姓名:米芃

學號:16040520018

【嵌牛導讀】深度學習發展到如今的地位,離不開下面這 6 段代碼。本文介紹了這些代碼的創作者及其完成這些突破性成就的故事背景。

【嵌牛鼻子】最小二乘法? ? 梯度下降? ? 線性回歸? ? 感知機? ? 人工神經網絡? ? 深度神經網絡

【嵌牛提問】深度學習是如何建立起來的,他是依靠什么擁有如今的成就的

【嵌牛正文】

最小二乘法

所有的深度學習算法都始于下面這個數學公式(我已將其轉成 Python 代碼)

# y = mx + b

# m is slope, b is y-intercept

def compute_error_for_line_given_points(b, m, coordinates):

? ? totalError = 0

? ? for i in range(0, len(coordinates)):

? ? ? ? x = coordinates[i][0]

? ? ? ? y = coordinates[i][1]

? ? ? ? totalError += (y - (m * x + b)) ** 2

? ? return totalError / float(len(coordinates))

# example

compute_error_for_line_given_points(1, 2, [[3,6],[6,9],[12,18]])

最小二乘法在 1805 年由 Adrien-Marie Legendre 首次提出(1805, Legendre),這位巴黎數學家也以測量儀器聞名。他極其癡迷于預測彗星的方位,堅持不懈地尋找一種可以基于彗星方位歷史數據計算其軌跡的算法。

他嘗試了許多種算法,一遍遍試錯,終于找到了一個算法與結果相符。Legendre 的算法是首先預測彗星未來的方位,然后計算誤差的平方,最終目的是通過修改預測值以減少誤差平方和。而這也正是線性回歸的基本思想。

讀者可以在 Jupyter notebook 中運行上述代碼來加深對這個算法的理解。m 是系數,b 是預測的常數項,coordinates 是彗星的位置。目標是找到合適的 m 和 b 使其誤差盡可能小。

這是深度學習的核心思想:給定輸入值和期望的輸出值,然后尋找兩者之間的相關性。

梯度下降

Legendre 這種通過手動嘗試來降低錯誤率的方法非常耗時。荷蘭的諾貝爾獎得主 Peter Debye 在一個世紀后(1909 年)正式提出了一種簡化這個過程的方法。

假設 Legendre 的算法需要考慮一個參數 —— 我們稱之為 X 。Y 軸表示每個 X 的誤差值。Legendre 的算法是找到使得誤差最小的 X。在下圖中,我們可以看到當 X = 1.1 時,誤差 Y 取到最小值。

Peter Debye 注意到最低點左邊的斜率是負的,而另一邊則是正的。因此,如果知道了任意給定 X 的斜率值,就可以找到 Y 的最小值點。

這便是梯度下降算法的基本思想。幾乎所有的深度學習模型都會用到梯度下降算法。

要實現這個算法,我們假設誤差函數是 Error = x ^ 5 -2x ^ 3-2。要得到任意給定 X 的斜率,我們需要對其求導,即 5x^4 – 6x^2:

如果您需要復習導數的相關知識,請觀看 Khan Academy 的視頻。

下面我們用 Python 實現 Debye 的算法:

current_x = 0.5 # the algorithm starts at x=0.5

learning_rate = 0.01 # step size multiplier

num_iterations = 60 # the number of times to train the function

#the derivative of the error function (x**4 = the power of 4 or x^4)

def slope_at_given_x_value(x):

? return 5 * x**4 - 6 * x**2

# Move X to the right or left depending on the slope of the error function

for i in range(num_iterations):

? previous_x = current_x

? current_x += -learning_rate * slope_at_given_x_value(previous_x)

? print(previous_x)

print("The local minimum occurs at %f" % current_x)

這里的竅門在于 learning_rate。我們通過沿斜率的相反方向行進來逼近最低點。此外,越接近最低點,斜率越小。因此當斜率接近零時,每一步下降的幅度會越來越小。

num_iterations 是你預計到達最小值之前所需的迭代次數。可以通過調試該參數訓練自己關于梯度下降算法的直覺。

線性回歸

最小二乘法配合梯度下降算法,就是一個完整的線性回歸過程。在 20 世紀 50 年代和 60 年代,一批實驗經濟學家在早期的計算機上實現了這些想法。這個過程是通過實體打卡 —— 真正的手工軟件程序實現的。準備這些打孔卡就需要幾天的時間,而通過計算機進行一次回歸分析最多需要 24 小時。

下面是用 Python 實現線性回歸的一個示例(我們不需要在打卡機上完成這個操作):

#Price of wheat/kg and the average price of bread

wheat_and_bread = [[0.5,5],[0.6,5.5],[0.8,6],[1.1,6.8],[1.4,7]]

def step_gradient(b_current, m_current, points, learningRate):

? ? b_gradient = 0

? ? m_gradient = 0

? ? N = float(len(points))

? ? for i in range(0, len(points)):

? ? ? ? x = points[i][0]

? ? ? ? y = points[i][1]

? ? ? ? b_gradient += -(2/N) * (y - ((m_current * x) + b_current))

? ? ? ? m_gradient += -(2/N) * x * (y - ((m_current * x) + b_current))

? ? new_b = b_current - (learningRate * b_gradient)

? ? new_m = m_current - (learningRate * m_gradient)

? ? return [new_b, new_m]

def gradient_descent_runner(points, starting_b, starting_m, learning_rate, num_iterations):

? ? b = starting_b

? ? m = starting_m

? ? for i in range(num_iterations):

? ? ? ? b, m = step_gradient(b, m, points, learning_rate)

? ? return [b, m]

gradient_descent_runner(wheat_and_bread, 1, 1, 0.01, 100)

線性回歸本身并沒有引入什么新的內容。但是,如何將梯度下降算法運用到誤差函數上就需要動動腦子了。運行代碼并使用這個線性回歸模擬器來加深你的理解吧。

感知機

接下來讓我們來認識一下 Frank Rosenblatt。這是一個白天解剖老鼠大腦,晚上尋找外星生命跡象的家伙。1958年,他發明了一個模仿神經元的機器(1958, Rosenblatt),并因此登上《紐約時報》的頭條:“New Navy Device Learns By Doing”。

如果向 Rosenblatt 的機器展示 50 組分別在左右兩側有標記的圖像,它可以在沒有預先編程的情況下分辨出兩張圖像(標記的位置)。大眾被這個可能真正擁有學習能力的機器震驚了。

如上圖所示,每個訓練周期都是從左側輸入數據開始。給所有輸入數據添加一個初始的隨機權重。然后將它們相加。如果總和為負,將其輸出為 0,否則輸出為 1。

如果預測結果是正確的,就不改變循環中的權重。如果預測結果是錯誤的,可以用誤差乘以學習率來相應地調整權重。

我們用經典的“或”邏輯來運行感知機。

下面是用 Python 實現的感知機模型:

from random import choice

from numpy import array, dot, random

1_or_0 = lambda x: 0 if x < 0 else 1

training_data = [ (array([0,0,1]), 0),

? ? ? ? ? ? ? ? ? ? (array([0,1,1]), 1),

? ? ? ? ? ? ? ? ? ? (array([1,0,1]), 1),

? ? ? ? ? ? ? ? ? ? (array([1,1,1]), 1), ]

weights = random.rand(3)

errors = []

learning_rate = 0.2

num_iterations = 100

for i in range(num_iterations):

? ? input, truth = choice(training_data)

? ? result = dot(weights, input)

? ? error = truth - 1_or_0(result)

? ? errors.append(error)

? ? weights += learning_rate * error * input

? ?

for x, _ in training_data:

? ? result = dot(x, w)

? ? print("{}: {} -> {}".format(input[:2], result, 1_or_0(result)))

經過最初的炒作一年之后,Marvin Minsky 和 Seymour Papert 擊碎了這個想法(1969, Minsky & Papert)。當時,Minsky 和 Papert 都在麻省理工學院的 AI 實驗室工作。他們寫了一本書,證明感知機只能解決線性問題。他們還批判了關于多層感知機的想法。可悲的是,Frank Rosenblatt 兩年后因船難去世。

在 Minsky 和 Papert 的書籍出版一年之后,一位芬蘭碩士研究生提出了用多層感知機解決非線性問題的理論(Linnainmaa, 1970)。由于業內主流對感知機普遍不看好,十多年來 AI 的研究資金也非常短缺。這是 AI 首次遇冷。

Minsky 和 Papert 對感知機的批判主要針對“異或”問題。這個邏輯與“或”邏輯相同,但有一個例外 —— 對兩個 true 語句取和(1&1)時,結果返回 False(0)。

如上圖所示,在“或”邏輯中,我們可以將 true 和 false 分開。但是可以看出,我們無法使用一個線性函數將“異或”邏輯的結果進行區分。

人工神經網絡

到 1986 年,幾項實驗證明,神經網絡可以解決復雜的非線性問題(Rumelhart et al., 1986)。 當時計算機的運算速度比該理論提出的時候快了一萬倍。Rumelhart 等人是這樣介紹他們赫赫有名的論文的:

我們描述了一種新的類神經元網絡學習過程——反向傳播。該過程通過反復調整網絡中的連接權重,最小化網絡的實際輸出向量與期望輸出向量之間的差異。調整權重的結果就是,不屬于輸入或輸出的內部“隱藏”單元成為了描述任務域的重要特征,并且這些單元的交互項還捕獲了任務中的正則條件。 相較于早期更簡單的方法,如“感知機收斂過程” Nature 323, 533 – 536 (09 October 1986),反向傳播可以創造出有用的新特征。

為了理解這篇文章的核心內容,我會在下面重現 DeepMind 團隊 Andrew Trask 的代碼。這不是一段普通的代碼。它曾被用于斯坦福大學 Andrew Karpathy 的深度學習課程,以及 Siraj Raval 的 Udacity 課程。最重要的是,它解決了“異或”問題,也結束了 AI 遇冷的時代。

學習這段代碼之前,我們首先通過這個模擬器交互學習一到兩個小時來掌握神經網絡的核心邏輯。然后閱讀 Trask 的博客,然后再閱讀四次。需要注意到,X_XOR 數據中添加的參數 [1] 是偏置神經元,它們等價于線性函數中的常數項。

import numpy as np

X_XOR = np.array([[0,0,1], [0,1,1], [1,0,1],[1,1,1]])

y_truth = np.array([[0],[1],[1],[0]])

np.random.seed(1)

syn_0 = 2*np.random.random((3,4)) - 1

syn_1 = 2*np.random.random((4,1)) - 1

def sigmoid(x):

? ? output = 1/(1+np.exp(-x))

? ? return output

def sigmoid_output_to_derivative(output):

? ? return output*(1-output)

for j in range(60000):

? ? layer_1 = sigmoid(np.dot(X_XOR, syn_0))

? ? layer_2 = sigmoid(np.dot(layer_1, syn_1))

? ? error = layer_2 - y_truth

? ? layer_2_delta = error * sigmoid_output_to_derivative(layer_2)

? ? layer_1_error = layer_2_delta.dot(syn_1.T)

? ? layer_1_delta = layer_1_error * sigmoid_output_to_derivative(layer_1)

? ? syn_1 -= layer_1.T.dot(layer_2_delta)

? ? syn_0 -= X_XOR.T.dot(layer_1_delta)

? ?

print("Output After Training: n", layer_2)

反向傳播,矩陣乘法和梯度下降放在一起會讓人很難理解。這個過程的可視化通常是對其背后原理的簡化。專注于理解其背后的邏輯,但不要過多地考慮直覺上的理解。

另外,讀者們也可以看看 Andrew Karpathy 關于反向傳播的課程,在這個可視化網站交互學習,以及閱讀 Michael Nielsen 關于反向傳播的章節。

深度神經網絡

深度神經網絡就是在輸入層和輸出層之間具有多個中間層的神經網絡。這個概念最早是由 Rina Dechter (Dechter, 1986) 引入的,但在2012年,也就是在 IBM 的人工智能程序 Watson 贏得美國電視智力競賽節目 Jeopardy 和 Google 推出貓咪識別器之后才受到廣泛關注。

深度神經網絡與之前神經網絡的核心結構相同,但是應用于一些不同的問題。在正則化方面也有很大改進。最初,這只是一組用來簡化冗雜的地球數據的數學函數(Tikhonov,A.N.,1963)。而現在被用于神經網絡中,以加強其泛化能力。

這種技術創新很大程度上依賴于計算機的運算能力。而運算能力的提升大大縮短了研究者的創新周期 —— 如今的 GPU 技術只需半秒鐘就可以完成一個八十年代中期的超級計算機一年的運算量。

計算成本的降低和各種深度學習庫的發展將深度學習帶入了大眾視野。我們來看一個常見的深度學習堆棧示例,從底層開始:

GPU > Nvidia Tesla K80。該硬件常用于圖形處理。它們深度學習的速度平均要比 CPU 快50-200倍。

CUDA > GPU 的底層編程語言

CuDNN > Nvidia 的庫,用來優化 CUDA

Tensorflow > 由 Google 開發,基于 CuDNN 的深度學習框架

TFlearn > Tensorflow 的前端框架

下面我們來看看 MNIST 數字分類圖像,它被稱作深度學習的 “Hello World”。

我們用 TFlearn 來實現:

from __future__ import division, print_function, absolute_import

import tflearn

from tflearn.layers.core import dropout, fully_connected

from tensorflow.examples.tutorials.mnist import input_data

from tflearn.layers.conv import conv_2d, max_pool_2d

from tflearn.layers.normalization import local_response_normalization

from tflearn.layers.estimator import regression

# Data loading and preprocessing

mnist = input_data.read_data_sets("/data/", one_hot=True)

X, Y, testX, testY = mnist.train.images, mnist.train.labels, mnist.test.images, mnist.test.labels

X = X.reshape([-1, 28, 28, 1])

testX = testX.reshape([-1, 28, 28, 1])

# Building convolutional network

network = tflearn.input_data(shape=[None, 28, 28, 1], name='input')

network = conv_2d(network, 32, 3, activation='relu', regularizer="L2")

network = max_pool_2d(network, 2)

network = local_response_normalization(network)

network = conv_2d(network, 64, 3, activation='relu', regularizer="L2")

network = max_pool_2d(network, 2)

network = local_response_normalization(network)

network = fully_connected(network, 128, activation='tanh')

network = dropout(network, 0.8)

network = fully_connected(network, 256, activation='tanh')

network = dropout(network, 0.8)

network = fully_connected(network, 10, activation='softmax')

network = regression(network, optimizer='adam', learning_rate=0.01,

? ? ? ? ? ? ? ? ? ? ? ? loss='categorical_crossentropy', name='target')

# Training

model = tflearn.DNN(network, tensorboard_verbose=0)

model.fit({'input': X}, {'target': Y}, n_epoch=20,

? ? ? ? ? ? validation_set=({'input': testX}, {'target': testY}),

? ? ? ? ? ? snapshot_step=100, show_metric=True, run_id='convnet_mnist')

關于 MNIST 問題,有很多不錯的文章:

https://www.tensorflow.org/get_started/mnist/beginners

https://www.youtube.com/watch?v=NMd7WjZiCzc

https://www.oreilly.com/learning/not-another-mnist-tutorial-with-tensorflow

摘自微信公眾號“大數據與機器學習文摘”

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,106評論 6 542
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,441評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,211評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,736評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,475評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,834評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,829評論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,009評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,559評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,306評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,516評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,038評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,728評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,132評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,443評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,249評論 3 399
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,484評論 2 379

推薦閱讀更多精彩內容

  • 文章作者:Tyan博客:noahsnail.com | CSDN | 簡書 聲明:作者翻譯論文僅為學習,如有侵權請...
    SnailTyan閱讀 5,132評論 0 8
  • 聲明:作者翻譯論文僅為學習,如有侵權請聯系作者刪除博文,謝謝! 翻譯論文匯總:https://github.com...
    SnailTyan閱讀 12,377評論 1 27
  • 聲明:作者翻譯論文僅為學習,如有侵權請聯系作者刪除博文,謝謝! 翻譯論文匯總:https://github.com...
    SnailTyan閱讀 12,556評論 3 13
  • 真的要下筆去寫他,卻足足呆在稿紙前快一個小時。 寫了那么多文章,卻仍然不知道該從哪里說起。 他,是我父親。一個再普...
    也是木頭閱讀 245評論 0 3
  • 1.這顆曇花樹是我六年前用一匹曇花葉子在花缽里插栽而成的。在這六年間,天天盼望著它長大。時間一天一天的過去,一年一...
    金碧阿塔姆閱讀 941評論 0 1