python神經網路dnn,Python神經網路庫

本文目錄一覽:

python的機器學習是什麼?

機器學習是一門多領域交叉學科,涉及概率論、統計學、逼近論、凸分析、演算法複雜度理論等多門學科。專門研究計算機怎樣模擬或實現人類的學習行為,以獲取新的知識或技能,重新組織已有的知識結構使之不斷改善自身的性能。它是人工智慧核心,是使計算機具有智能的根本途徑。

而數據分析與機器學習不同,機器學習比數據分析更深一個層次,就業前景、薪資待遇也更高。

深度學習 python怎麼入門 知乎

自學深度學習是一個漫長而艱巨的過程。您需要有很強的線性代數和微積分背景,良好的Python編程技能,並紮實掌握數據科學、機器學習和數據工程。即便如此,在你開始將深度學習應用於現實世界的問題,並有可能找到一份深度學習工程師的工作之前,你可能需要一年多的學習和實踐。然而,知道從哪裡開始,對軟化學習曲線有很大幫助。如果我必須重新學習Python的深度學習,我會從Andrew Trask寫的Grokking deep learning開始。大多數關於深度學習的書籍都要求具備機器學習概念和演算法的基本知識。除了基本的數學和編程技能之外,Trask的書不需要任何先決條件就能教你深度學習的基礎知識。這本書不會讓你成為一個深度學習的嚮導(它也沒有做這樣的聲明),但它會讓你走上一條道路,讓你更容易從更高級的書和課程中學習。用Python構建人工神經元

大多數深度學習書籍都是基於一些流行的Python庫,如TensorFlow、PyTorch或Keras。相比之下,《運用深度學習》(Grokking Deep Learning)通過從零開始、一行一行地構建內容來教你進行深度學習。

《運用深度學習》

你首先要開發一個人工神經元,這是深度學習的最基本元素。查斯克將帶領您了解線性變換的基本知識,這是由人工神經元完成的主要計算。然後用普通的Python代碼實現人工神經元,無需使用任何特殊的庫。

這不是進行深度學習的最有效方式,因為Python有許多庫,它們利用計算機的圖形卡和CPU的並行處理能力來加速計算。但是用普通的Python編寫一切對於學習深度學習的來龍去是非常好的。

在Grokking深度學習中,你的第一個人工神經元只接受一個輸入,將其乘以一個隨機權重,然後做出預測。然後測量預測誤差,並應用梯度下降法在正確的方向上調整神經元的權重。有了單個神經元、單個輸入和單個輸出,理解和實現這個概念變得非常容易。您將逐漸增加模型的複雜性,使用多個輸入維度、預測多個輸出、應用批處理學習、調整學習速率等等。

您將通過逐步添加和修改前面章節中編寫的Python代碼來實現每個新概念,逐步創建用於進行預測、計算錯誤、應用糾正等的函數列表。當您從標量計算轉移到向量計算時,您將從普通的Python操作轉移到Numpy,這是一個特別擅長並行計算的庫,在機器學習和深度學習社區中非常流行。

Python的深度神經網路

有了這些人造神經元的基本構造塊,你就可以開始創建深層神經網路,這基本上就是你將幾層人造神經元疊放在一起時得到的結果。

當您創建深度神經網路時,您將了解激活函數,並應用它們打破堆疊層的線性並創建分類輸出。同樣,您將在Numpy函數的幫助下自己實現所有功能。您還將學習計算梯度和傳播錯誤通過層傳播校正跨不同的神經元。

隨著您越來越熟悉深度學習的基礎知識,您將學習並實現更高級的概念。這本書的特點是一些流行的正規化技術,如早期停止和退出。您還將獲得自己版本的卷積神經網路(CNN)和循環神經網路(RNN)。

在本書結束時,您將把所有內容打包到一個完整的Python深度學習庫中,創建自己的層次結構類、激活函數和神經網路體系結構(在這一部分,您將需要面向對象的編程技能)。如果您已經使用過Keras和PyTorch等其他Python庫,那麼您會發現最終的體系結構非常熟悉。如果您沒有,您將在將來更容易地適應這些庫。

在整本書中,查斯克提醒你熟能生巧;他鼓勵你用心編寫自己的神經網路,而不是複製粘貼任何東西。

代碼庫有點麻煩

並不是所有關於Grokking深度學習的東西都是完美的。在之前的一篇文章中,我說過定義一本好書的主要內容之一就是代碼庫。在這方面,查斯克本可以做得更好。

在GitHub的Grokking深度學習庫中,每一章都有豐富的jupiter Notebook文件。jupiter Notebook是一個學習Python機器學習和深度學習的優秀工具。然而,jupiter的優勢在於將代碼分解為幾個可以獨立執行和測試的小單元。Grokking深度學習的一些筆記本是由非常大的單元格組成的,其中包含大量未注釋的代碼。

這在後面的章節中會變得尤其困難,因為代碼會變得更長更複雜,在筆記本中尋找自己的方法會變得非常乏味。作為一個原則問題,教育材料的代碼應該被分解成小單元格,並在關鍵區域包含注釋。

此外,Trask在Python 2.7中編寫了這些代碼。雖然他已經確保了代碼在Python 3中也能順暢地工作,但它包含了已經被Python開發人員棄用的舊編碼技術(例如使用「for i in range(len(array))」範式在數組上迭代)。

更廣闊的人工智慧圖景

Trask已經完成了一項偉大的工作,它彙集了一本書,既可以為初學者,也可以為有經驗的Python深度學習開發人員填補他們的知識空白。

但正如泰溫·蘭尼斯特(Tywin Lannister)所說(每個工程師都會同意),「每個任務都有一個工具,每個工具都有一個任務。」深度學習並不是一根可以解決所有人工智慧問題的魔杖。事實上,對於許多問題,更簡單的機器學習演算法,如線性回歸和決策樹,將表現得和深度學習一樣好,而對於其他問題,基於規則的技術,如正則表達式和幾個if-else子句,將優於兩者。

關鍵是,你需要一整套工具和技術來解決AI問題。希望Grokking深度學習能夠幫助你開始獲取這些工具。

你要去哪裡?我當然建議選擇一本關於Python深度學習的深度書籍,比如PyTorch的深度學習或Python的深度學習。你還應該加深你對其他機器學習演算法和技術的了解。我最喜歡的兩本書是《動手機器學習》和《Python機器學習》。

你也可以通過瀏覽機器學習和深度學習論壇,如r/MachineLearning和r/deeplearning subreddits,人工智慧和深度學習Facebook組,或通過在Twitter上關注人工智慧研究人員來獲取大量知識。

AI的世界是巨大的,並且在快速擴張,還有很多東西需要學習。如果這是你關於深度學習的第一本書,那麼這是一個神奇旅程的開始。

從零開始用Python構建神經網路

從零開始用Python構建神經網路

動機:為了更加深入的理解深度學習,我們將使用 python 語言從頭搭建一個神經網路,而不是使用像 Tensorflow 那樣的封裝好的框架。我認為理解神經網路的內部工作原理,對數據科學家來說至關重要。

這篇文章的內容是我的所學,希望也能對你有所幫助。

神經網路是什麼?

介紹神經網路的文章大多數都會將它和大腦進行類比。如果你沒有深入研究過大腦與神經網路的類比,那麼將神經網路解釋為一種將給定輸入映射為期望輸出的數學關係會更容易理解。

神經網路包括以下組成部分

? 一個輸入層,x

? 任意數量的隱藏層

? 一個輸出層,?

? 每層之間有一組權值和偏置,W and b

? 為隱藏層選擇一種激活函數,σ。在教程中我們使用 Sigmoid 激活函數

下圖展示了 2 層神經網路的結構(注意:我們在計算網路層數時通常排除輸入層)

2 層神經網路的結構

用 Python 可以很容易的構建神經網路類

訓練神經網路

這個網路的輸出 ? 為:

你可能會注意到,在上面的等式中,輸出 ? 是 W 和 b 函數。

因此 W 和 b 的值影響預測的準確率. 所以根據輸入數據對 W 和 b 調優的過程就被成為訓練神經網路。

每步訓練迭代包含以下兩個部分:

? 計算預測結果 ?,這一步稱為前向傳播

? 更新 W 和 b,,這一步成為反向傳播

下面的順序圖展示了這個過程:

前向傳播

正如我們在上圖中看到的,前向傳播只是簡單的計算。對於一個基本的 2 層網路來說,它的輸出是這樣的:

我們在 NeuralNetwork 類中增加一個計算前向傳播的函數。為了簡單起見我們假設偏置 b 為0:

但是我們還需要一個方法來評估預測結果的好壞(即預測值和真實值的誤差)。這就要用到損失函數。

損失函數

常用的損失函數有很多種,根據模型的需求來選擇。在本教程中,我們使用誤差平方和作為損失函數。

誤差平方和是求每個預測值和真實值之間的誤差再求和,這個誤差是他們的差值求平方以便我們觀察誤差的絕對值。

訓練的目標是找到一組 W 和 b,使得損失函數最好小,也即預測值和真實值之間的距離最小。

反向傳播

我們已經度量出了預測的誤差(損失),現在需要找到一種方法來傳播誤差,並以此更新權值和偏置。

為了知道如何適當的調整權值和偏置,我們需要知道損失函數對權值 W 和偏置 b 的導數。

回想微積分中的概念,函數的導數就是函數的斜率。

梯度下降法

如果我們已經求出了導數,我們就可以通過增加或減少導數值來更新權值 W 和偏置 b(參考上圖)。這種方式被稱為梯度下降法。

但是我們不能直接計算損失函數對權值和偏置的導數,因為在損失函數的等式中並沒有顯式的包含他們。因此,我們需要運用鏈式求導發在來幫助計算導數。

鏈式法則用於計算損失函數對 W 和 b 的導數。注意,為了簡單起見。我們只展示了假設網路只有 1 層的偏導數。

這雖然很簡陋,但是我們依然能得到想要的結果—損失函數對權值 W 的導數(斜率),因此我們可以相應的調整權值。

現在我們將反向傳播演算法的函數添加到 Python 代碼中

為了更深入的理解微積分原理和反向傳播中的鏈式求導法則,我強烈推薦 3Blue1Brown 的如下教程:

Youtube:

整合併完成一個實例

既然我們已經有了包括前向傳播和反向傳播的完整 Python 代碼,那麼就將其應用到一個例子上看看它是如何工作的吧。

神經網路可以通過學習得到函數的權重。而我們僅靠觀察是不太可能得到函數的權重的。

讓我們訓練神經網路進行 1500 次迭代,看看會發生什麼。 注意觀察下面每次迭代的損失函數,我們可以清楚地看到損失函數單調遞減到最小值。這與我們之前介紹的梯度下降法一致。

讓我們看看經過 1500 次迭代後的神經網路的最終預測結果:

經過 1500 次迭代訓練後的預測結果

我們成功了!我們應用前向和方向傳播演算法成功的訓練了神經網路並且預測結果收斂於真實值。

注意預測值和真實值之間存在細微的誤差是允許的。這樣可以防止模型過擬合併且使得神經網路對於未知數據有著更強的泛化能力。

下一步是什麼?

幸運的是我們的學習之旅還沒有結束,仍然有很多關於神經網路和深度學習的內容需要學習。例如:

? 除了 Sigmoid 以外,還可以用哪些激活函數

? 在訓練網路的時候應用學習率

? 在面對圖像分類任務的時候使用卷積神經網路

我很快會寫更多關於這個主題的內容,敬請期待!

最後的想法

我自己也從零開始寫了很多神經網路的代碼

雖然可以使用諸如 Tensorflow 和 Keras 這樣的深度學習框架方便的搭建深層網路而不需要完全理解其內部工作原理。但是我覺得對於有追求的數據科學家來說,理解內部原理是非常有益的。

這種練習對我自己來說已成成為重要的時間投入,希望也能對你有所幫助

深度神經網路dnn怎麼調節參數

深度神經網路(DNN)目前是許多現代AI應用的基礎。

自從DNN在語音識別和圖像識別任務中展現出突破性的成果,使用DNN的應用數量呈爆炸式增加。這些DNN方法被大量應用在無人駕駛汽車,癌症檢測,遊戲AI等方面。

在許多領域中,DNN目前的準確性已經超過人類。與早期的專家手動提取特徵或制定規則不同,DNN的優越性能來自於在大量數據上使用統計學習方法,從原始數據中提取高級特徵的能力,從而對輸入空間進行有效的表示。

然而,DNN超高的準確性是以超高的計算複雜度為代價的。

通常意義下的計算引擎,尤其是GPU,是DNN的基礎。因此,能夠在不犧牲準確性和增加硬體成本的前提下,提高深度神經網路的能量效率和吞吐量的方法,對於DNN在AI系統中更廣泛的應用是至關重要的。研究人員目前已經更多的將關注點放在針對DNN計算開發專用的加速方法。

鑒於篇幅,本文主要針對論文中的如下幾部分詳細介紹:

DNN的背景,歷史和應用

DNN的組成部分,以及常見的DNN模型

簡介如何使用硬體加速DNN運算

DNN的背景

人工智慧與深度神經網路

深度神經網路,也被稱為深度學習,是人工智慧領域的重要分支,根據麥卡錫(人工智慧之父)的定義,人工智慧是創造像人一樣的智能機械的科學工程。深度學習與人工智慧的關係如圖1所示:

圖1:深度神經網路與人工智慧的關係

人工智慧領域內,一個大的子領域是機器學習,由Arthur Samuel在1959年定義為:讓計算機擁有不需要明確編程即可學習的能力。

這意味著創建一個程序,這個程序可以被訓練去學習如何去做一些智能的行為,然後這個程序就可以自己完成任務。而傳統的人工啟發式方法,需要對每個新問題重新設計程序。

高效的機器學習演算法的優點是顯而易見的。一個機器學習演算法,只需通過訓練,就可以解決某一領域中每一個新問題,而不是對每個新問題特定地進行編程。

在機器學習領域,有一個部分被稱作brain-inspired computation。因為人類大腦是目前學習和解決問題最好的「機器」,很自然的,人們會從中尋找機器學習的方法。

儘管科學家們仍在探索大腦工作的細節,但是有一點被公認的是:神經元是大腦的主要計算單元。

人類大腦平均有860億個神經元。神經元相互連接,通過樹突接受其他神經元的信號,對這些信號進行計算之後,通過軸突將信號傳遞給下一個神經元。一個神經元的軸突分支出來並連接到許多其他神經元的樹突上,軸突分支和樹突之間的連接被稱為突觸。據估計,人類大腦平均有1014-1015個突觸。

突觸的一個關鍵特性是它可以縮放通過它的信號大小。這個比例因子可以被稱為權重(weight),普遍認為,大腦學習的方式是通過改變突觸的權重實現的。因此,不同的權重導致對輸入產生不同的響應。注意,學習過程是學習刺激導致的權重調整,而大腦組織(可以被認為是程序)並不改變。

大腦的這個特徵對機器學習演算法有很好的啟示。

神經網路與深度神經網路

神經元的計算是輸入值的加權和這個概念啟發了神經網路的研究。這些加權和對應於突觸的縮放值以及神經元所接收的值的組合。此外,神經元並不僅僅是輸入信號的加權和,如果是這樣的話,級聯的神經元的計算將是一種簡單的線性代數運算。

相反的是,神經元組合輸入的操作似乎是一種非線性函數,只有輸入達到某個閾值的時候,神經元才會生成輸出。因此,通過類比,我們可以知道神經網路在輸入值的加權和的基礎上應用了非線性函數。

圖2(a)展示了計算神經網路的示意圖,圖的最左邊是接受數值的「輸入層」。這些值被傳播到中間層神經元,通常也叫做網路的「隱藏層」。通過一個或更多隱藏層的加權和最終被傳播到「輸出層」,將神經網路的最終結果輸出給用戶。

圖2:神經網路示意圖

在神經網路領域,一個子領域被稱為深度學習。最初的神經網路通常只有幾層的網路。而深度網路通常有更多的層數,今天的網路一般在五層以上,甚至達到一千多層。

目前在視覺應用中使用深度神經網路的解釋是:將圖像所有像素輸入到網路的第一層之後,該層的加權和可以被解釋為表示圖像不同的低階特徵。隨著層數的加深,這些特徵被組合,從而代表更高階的圖像特徵。

例如,線可以被組合成形狀,再進一步,可以被組合成一系列形狀的集合。最後,再訓練好這些信息之後,針對各個圖像類別,網路給出由這些高階特徵組成各個對象的概率,即分類結果。

推理(Inference)與訓練(Training)

既然DNN是機器學習演算法中的一員,那麼它的基本編程思想仍然是學習。DNN的學習即確定網路的權重值。通常,學習過程被稱為訓練網路(training)。一旦訓練完成,程序可以使用由訓練確定的權值進行計算,這個使用網路完成任務的操作被被稱為推斷(inference)。

接下來,如圖3所示,我們用圖像分類作為例子來展示如何訓練一個深度神經網路。當我們使用一個DNN的時候,我們輸入一幅圖片,DNN輸出一個得分向量,每一個分數對應一個物體分類;得到最高分數的分類意味著這幅圖片最有可能屬於這個分類。

訓練DNN的首要目標就是確定如何設置權重,使得正確分類的得分最高(圖片所對應的正確分類在訓練數據集中標出),而使其他不正確分類的得分儘可能低。理想的正確分類得分與目前的權重所計算出的得分之間的差距被稱為損失函數(loss)。

因此訓練DNN的目標即找到一組權重,使得對一個較大規模數據集的loss最小。

圖3:圖像分類

權重(weight)的優化過程類似爬山的過程,這種方法被稱為梯度下降(gradient decent)。損失函數對每個權值的梯度,即損失函數對每個權值求偏導數,被用來更新權值(例:第t到t+1次迭代:,其中α被稱為學習率(Learning rate)。梯度值表明權值應該如何變化以減小loss。這個減小loss值的過程是重複迭代進行的。

梯度可以通過反向傳播(Back-Propagation)過程很高效地進行計算,loss的影響反向通過網路來計算loss是如何被每個權重影響的。

訓練權重有很多種方法。前面提到的是最常見的方法,被稱為監督學習,其中所有的訓練樣本是有標籤的。

無監督學習是另一種方法,其中所有訓練樣本都沒有標籤,最終目標是在數據中查找結構或聚類。半監督學習結合了兩種方法,只有訓練數據的一小部分被標記(例如,使用未標記的數據來定義集群邊界,並使用少量的標記數據來標記集群)。

最後,強化學習可以用來訓練一個DNN作為一個策略網路,對策略網路給出一個輸入,它可以做出一個決定,使得下一步的行動得到相應的獎勵;訓練這個網路的過程是使網路能夠做出使獎勵(即獎勵函數)最大化的決策,並且訓練過程必須平衡嘗試新行為(Exploration)和使用已知能給予高回報的行為(Exploitation)兩種方法。

用於確定權重的另一種常用方法是fine-tune,使用預先訓練好的模型的權重用作初始化,然後針對新的數據集(例如,傳遞學習)或新的約束(例如,降低的精度)調整權重。與從隨機初始化開始相比,能夠更快的訓練,並且有時會有更好的準確性。

如何用 Python 構建神經網路擇時模型

import math

import random

random.seed(0)

def rand(a,b): #隨機函數

return (b-a)*random.random()+a

def make_matrix(m,n,fill=0.0):#創建一個指定大小的矩陣

mat = []

for i in range(m):

mat.append([fill]*n)

return mat

#定義sigmoid函數和它的導數

def sigmoid(x):

return 1.0/(1.0+math.exp(-x))

def sigmoid_derivate(x):

return x*(1-x) #sigmoid函數的導數

class BPNeuralNetwork:

def __init__(self):#初始化變數

self.input_n = 0

self.hidden_n = 0

self.output_n = 0

self.input_cells = []

self.hidden_cells = []

self.output_cells = []

self.input_weights = []

self.output_weights = []

self.input_correction = []

self.output_correction = []

#三個列表維護:輸入層,隱含層,輸出層神經元

def setup(self,ni,nh,no):

self.input_n = ni+1 #輸入層+偏置項

self.hidden_n = nh #隱含層

self.output_n = no #輸出層

#初始化神經元

self.input_cells = [1.0]*self.input_n

self.hidden_cells= [1.0]*self.hidden_n

self.output_cells= [1.0]*self.output_n

#初始化連接邊的邊權

self.input_weights = make_matrix(self.input_n,self.hidden_n) #鄰接矩陣存邊權:輸入層-隱藏層

self.output_weights = make_matrix(self.hidden_n,self.output_n) #鄰接矩陣存邊權:隱藏層-輸出層

#隨機初始化邊權:為了反向傳導做準備—隨機初始化的目的是使對稱失效

for i in range(self.input_n):

for h in range(self.hidden_n):

self.input_weights[i][h] = rand(-0.2 , 0.2) #由輸入層第i個元素到隱藏層第j個元素的邊權為隨機值

for h in range(self.hidden_n):

for o in range(self.output_n):

self.output_weights[h][o] = rand(-2.0, 2.0) #由隱藏層第i個元素到輸出層第j個元素的邊權為隨機值

#保存校正矩陣,為了以後誤差做調整

self.input_correction = make_matrix(self.input_n , self.hidden_n)

self.output_correction = make_matrix(self.hidden_n,self.output_n)

#輸出預測值

def predict(self,inputs):

#對輸入層進行操作轉化樣本

for i in range(self.input_n-1):

self.input_cells[i] = inputs[i] #n個樣本從0~n-1

#計算隱藏層的輸出,每個節點最終的輸出值就是權值*節點值的加權和

for j in range(self.hidden_n):

total = 0.0

for i in range(self.input_n):

total+=self.input_cells[i]*self.input_weights[i][j]

# 此處為何是先i再j,以隱含層節點做大循環,輸入樣本為小循環,是為了每一個隱藏節點計算一個輸出值,傳輸到下一層

self.hidden_cells[j] = sigmoid(total) #此節點的輸出是前一層所有輸入點和到該點之間的權值加權和

for k in range(self.output_n):

total = 0.0

for j in range(self.hidden_n):

total+=self.hidden_cells[j]*self.output_weights[j][k]

self.output_cells[k] = sigmoid(total) #獲取輸出層每個元素的值

return self.output_cells[:] #最後輸出層的結果返回

#反向傳播演算法:調用預測函數,根據反向傳播獲取權重後前向預測,將結果與實際結果返回比較誤差

def back_propagate(self,case,label,learn,correct):

#對輸入樣本做預測

self.predict(case) #對實例進行預測

output_deltas = [0.0]*self.output_n #初始化矩陣

for o in range(self.output_n):

error = label[o] – self.output_cells[o] #正確結果和預測結果的誤差:0,1,-1

output_deltas[o]= sigmoid_derivate(self.output_cells[o])*error#誤差穩定在0~1內

#隱含層誤差

hidden_deltas = [0.0]*self.hidden_n

for h in range(self.hidden_n):

error = 0.0

for o in range(self.output_n):

error+=output_deltas[o]*self.output_weights[h][o]

hidden_deltas[h] = sigmoid_derivate(self.hidden_cells[h])*error

#反向傳播演算法求W

#更新隱藏層-輸出權重

for h in range(self.hidden_n):

for o in range(self.output_n):

change = output_deltas[o]*self.hidden_cells[h]

#調整權重:上一層每個節點的權重學習*變化+矯正率

self.output_weights[h][o] += learn*change + correct*self.output_correction[h][o]

#更新輸入-隱藏層的權重

for i in range(self.input_n):

for h in range(self.hidden_n):

change = hidden_deltas[h]*self.input_cells[i]

self.input_weights[i][h] += learn*change + correct*self.input_correction[i][h]

self.input_correction[i][h] = change

#獲取全局誤差

error = 0.0

for o in range(len(label)):

error = 0.5*(label[o]-self.output_cells[o])**2 #平方誤差函數

return error

def train(self,cases,labels,limit=10000,learn=0.05,correct=0.1):

for i in range(limit): #設置迭代次數

error = 0.0

for j in range(len(cases)):#對輸入層進行訪問

label = labels[j]

case = cases[j]

error+=self.back_propagate(case,label,learn,correct) #樣例,標籤,學習率,正確閾值

def test(self): #學習異或

cases = [

[0, 0],

[0, 1],

[1, 0],

[1, 1],

] #測試樣例

labels = [[0], [1], [1], [0]] #標籤

self.setup(2,5,1) #初始化神經網路:輸入層,隱藏層,輸出層元素個數

self.train(cases,labels,10000,0.05,0.1) #可以更改

for case in cases:

print(self.predict(case))

if __name__ == ‘__main__’:

nn = BPNeuralNetwork()

nn.test()

利用Python實現卷積神經網路的可視化

在本文中,將探討如何可視化卷積神經網路(CNN),該網路在計算機視覺中使用最為廣泛。首先了解CNN模型可視化的重要性,其次介紹可視化的幾種方法,同時以一個用例幫助讀者更好地理解模型可視化這一概念。

正如上文中介紹的癌症腫瘤診斷案例所看到的,研究人員需要對所設計模型的工作原理及其功能掌握清楚,這點至關重要。一般而言,一名深度學習研究者應該記住以下幾點:

1.1 理解模型是如何工作的

1.2 調整模型的參數

1.3 找出模型失敗的原因

1.4 向消費者/終端用戶或業務主管解釋模型做出的決定

2.可視化CNN模型的方法

根據其內部的工作原理,大體上可以將CNN可視化方法分為以下三類:

初步方法:一種顯示訓練模型整體結構的簡單方法

基於激活的方法:對單個或一組神經元的激活狀態進行破譯以了解其工作過程

基於梯度的方法:在訓練過程中操作前向傳播和後向傳播形成的梯度

下面將具體介紹以上三種方法,所舉例子是使用Keras深度學習庫實現,另外本文使用的數據集是由「識別數字」競賽提供。因此,讀者想復現文中案例時,請確保安裝好Kears以及執行了這些步驟。

研究者能做的最簡單的事情就是繪製出模型結構圖,此外還可以標註神經網路中每層的形狀及參數。在keras中,可以使用如下命令完成模型結構圖的繪製:

model.summary()_________________________________________________________________Layer (type)                 Output Shape              Param #  

=================================================================conv2d_1 (Conv2D)            (None, 26, 26, 32)        320_________________________________________________________________conv2d_2 (Conv2D)            (None, 24, 24, 64)        18496_________________________________________________________________max_pooling2d_1 (MaxPooling2 (None, 12, 12, 64)        0_________________________________________________________________dropout_1 (Dropout)          (None, 12, 12, 64)        0_________________________________________________________________flatten_1 (Flatten)          (None, 9216)              0_________________________________________________________________dense_1 (Dense)              (None, 128)               1179776_________________________________________________________________dropout_2 (Dropout)          (None, 128)               0_________________________________________________________________preds (Dense)                (None, 10)                1290      

=================================================================Total params: 1,199,882Trainable params: 1,199,882Non-trainable params: 0

還可以用一個更富有創造力和表現力的方式呈現模型結構框圖,可以使用keras.utils.vis_utils函數完成模型體系結構圖的繪製。

另一種方法是繪製訓練模型的過濾器,這樣就可以了解這些過濾器的表現形式。例如,第一層的第一個過濾器看起來像:

top_layer = model.layers[0]plt.imshow(top_layer.get_weights()[0][:, :, :, 0].squeeze(), cmap=’gray’)

一般來說,神經網路的底層主要是作為邊緣檢測器,當層數變深時,過濾器能夠捕捉更加抽象的概念,比如人臉等。

為了理解神經網路的工作過程,可以在輸入圖像上應用過濾器,然後繪製其卷積後的輸出,這使得我們能夠理解一個過濾器其特定的激活模式是什麼。比如,下圖是一個人臉過濾器,當輸入圖像是人臉圖像時候,它就會被激活。

from vis.visualization import visualize_activation

from vis.utils import utils

from keras import activations

from matplotlib import pyplot as plt

%matplotlib inline

plt.rcParams[‘figure.figsize’] = (18, 6)

# Utility to search for layer index by name.

# Alternatively we can specify this as -1 since it corresponds to the last layer.

layer_idx = utils.find_layer_idx(model, ‘preds’)

# Swap softmax with linear

model.layers[layer_idx].activation = activations.linear

model = utils.apply_modifications(model)

# This is the output node we want to maximize.filter_idx = 0

img = visualize_activation(model, layer_idx, filter_indices=filter_idx)

plt.imshow(img[…, 0])

同理,可以將這個想法應用於所有的類別,並檢查它們的模式會是什麼樣子。

for output_idx in np.arange(10):

  # Lets turn off verbose output this time to avoid clutter and just see the output.

  img = visualize_activation(model, layer_idx, filter_indices=output_idx, input_range=(0., 1.))

  plt.figure()

  plt.title(‘Networks perception of {}’.format(output_idx))

  plt.imshow(img[…, 0])

在圖像分類問題中,可能會遇到目標物體被遮擋,有時候只有物體的一小部分可見的情況。基於圖像遮擋的方法是通過一個灰色正方形系統地輸入圖像的不同部分並監視分類器的輸出。這些例子清楚地表明模型在場景中定位對象時,若對象被遮擋,其分類正確的概率顯著降低。

為了理解這一概念,可以從數據集中隨機抽取圖像,並嘗試繪製該圖的熱圖(heatmap)。這使得我們直觀地了解圖像的哪些部分對於該模型而言的重要性,以便對實際類別進行明確的區分。

def iter_occlusion(image, size=8):

    # taken from

  occlusion = np.full((size * 5, size * 5, 1), [0.5], np.float32)

  occlusion_center = np.full((size, size, 1), [0.5], np.float32)

  occlusion_padding = size * 2

  # print(‘padding…’)

  image_padded = np.pad(image, ( \  (occlusion_padding, occlusion_padding), (occlusion_padding, occlusion_padding), (0, 0) \  ), ‘constant’, constant_values = 0.0)

  for y in range(occlusion_padding, image.shape[0] + occlusion_padding, size):

      for x in range(occlusion_padding, image.shape[1] + occlusion_padding, size):

          tmp = image_padded.copy()

          tmp[y – occlusion_padding:y + occlusion_center.shape[0] + occlusion_padding, \

            x – occlusion_padding:x + occlusion_center.shape[1] + occlusion_padding] \            = occlusion

          tmp[y:y + occlusion_center.shape[0], x:x + occlusion_center.shape[1]] = occlusion_center          yield x – occlusion_padding, y – occlusion_padding, \

            tmp[occlusion_padding:tmp.shape[0] – occlusion_padding, occlusion_padding:tmp.shape[1] – occlusion_padding]i = 23 # for exampledata = val_x[i]correct_class = np.argmax(val_y[i])

# input tensor for model.predictinp = data.reshape(1, 28, 28, 1)# image data for matplotlib’s imshowimg = data.reshape(28, 28)

# occlusionimg_size = img.shape[0]

occlusion_size = 4print(‘occluding…’)heatmap = np.zeros((img_size, img_size), np.float32)class_pixels = np.zeros((img_size, img_size), np.int16)

from collections import defaultdict

counters = defaultdict(int)for n, (x, y, img_float) in enumerate(iter_occlusion(data, size=occlusion_size)):

    X = img_float.reshape(1, 28, 28, 1)

    out = model.predict(X)

    #print(‘#{}: {} @ {} (correct class: {})’.format(n, np.argmax(out), np.amax(out), out[0][correct_class]))

    #print(‘x {} – {} | y {} – {}’.format(x, x + occlusion_size, y, y + occlusion_size))

    heatmap[y:y + occlusion_size, x:x + occlusion_size] = out[0][correct_class]

    class_pixels[y:y + occlusion_size, x:x + occlusion_size] = np.argmax(out)

    counters[np.argmax(out)] += 1

正如之前的坦克案例中看到的那樣,怎麼才能知道模型側重於哪部分的預測呢?為此,可以使用顯著圖解決這個問題。顯著圖首先在這篇文章中被介紹。

使用顯著圖的概念相當直接——計算輸出類別相對於輸入圖像的梯度。這應該告訴我們輸出類別值對於輸入圖像像素中的微小變化是怎樣變化的。梯度中的所有正值告訴我們,像素的一個小變化會增加輸出值。因此,將這些梯度可視化可以提供一些直觀的信息,這種方法突出了對輸出貢獻最大的顯著圖像區域。

class_idx = 0indices = np.where(val_y[:, class_idx] == 1.)[0]

# pick some random input from here.idx = indices[0]

# Lets sanity check the picked image.from matplotlib import pyplot as plt%matplotlib inline

plt.rcParams[‘figure.figsize’] = (18, 6)plt.imshow(val_x[idx][…, 0])

from vis.visualization import visualize_saliency

from vis.utils import utilsfrom keras import activations# Utility to search for layer index by name.

# Alternatively we can specify this as -1 since it corresponds to the last layer.

layer_idx = utils.find_layer_idx(model, ‘preds’)

# Swap softmax with linearmodel.layers[layer_idx].activation = activations.linear

model = utils.apply_modifications(model)grads = visualize_saliency(model, layer_idx, filter_indices=class_idx, seed_input=val_x[idx])

# Plot with ‘jet’ colormap to visualize as a heatmap.plt.imshow(grads, cmap=’jet’)

# This corresponds to the Dense linear layer.for class_idx in np.arange(10):

    indices = np.where(val_y[:, class_idx] == 1.)[0]

    idx = indices[0]

    f, ax = plt.subplots(1, 4)

    ax[0].imshow(val_x[idx][…, 0])

    for i, modifier in enumerate([None, ‘guided’, ‘relu’]):

        grads = visualize_saliency(model, layer_idx, filter_indices=class_idx,

        seed_input=val_x[idx], backprop_modifier=modifier)

        if modifier is None:

            modifier = ‘vanilla’

        ax[i+1].set_title(modifier)

        ax[i+1].imshow(grads, cmap=’jet’)

類別激活映射(CAM)或grad-CAM是另外一種可視化模型的方法,這種方法使用的不是梯度的輸出值,而是使用倒數第二個卷積層的輸出,這樣做是為了利用存儲在倒數第二層的空間信息。

from vis.visualization import visualize_cam

# This corresponds to the Dense linear layer.for class_idx in np.arange(10):

indices = np.where(val_y[:, class_idx] == 1.)[0]

idx = indices[0]f, ax = plt.subplots(1, 4)

ax[0].imshow(val_x[idx][…, 0])

for i, modifier in enumerate([None, ‘guided’, ‘relu’]):

    grads = visualize_cam(model, layer_idx, filter_indices=class_idx,

    seed_input=val_x[idx], backprop_modifier=modifier)

    if modifier is None:

        modifier = ‘vanilla’

    ax[i+1].set_title(modifier)

    ax[i+1].imshow(grads, cmap=’jet’)

本文簡單說明了CNN模型可視化的重要性,以及介紹了一些可視化CNN網路模型的方法,希望對讀者有所幫助,使其能夠在後續深度學習應用中構建更好的模型。 免費視頻教程:

原創文章,作者:小藍,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/184763.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
小藍的頭像小藍
上一篇 2024-11-26 05:01
下一篇 2024-11-26 05:02

相關推薦

  • Python中引入上一級目錄中函數

    Python中經常需要調用其他文件夾中的模塊或函數,其中一個常見的操作是引入上一級目錄中的函數。在此,我們將從多個角度詳細解釋如何在Python中引入上一級目錄的函數。 一、加入環…

    編程 2025-04-29
  • 如何查看Anaconda中Python路徑

    對Anaconda中Python路徑即conda環境的查看進行詳細的闡述。 一、使用命令行查看 1、在Windows系統中,可以使用命令提示符(cmd)或者Anaconda Pro…

    編程 2025-04-29
  • Python計算陽曆日期對應周幾

    本文介紹如何通過Python計算任意陽曆日期對應周幾。 一、獲取日期 獲取日期可以通過Python內置的模塊datetime實現,示例代碼如下: from datetime imp…

    編程 2025-04-29
  • Python周杰倫代碼用法介紹

    本文將從多個方面對Python周杰倫代碼進行詳細的闡述。 一、代碼介紹 from urllib.request import urlopen from bs4 import Bea…

    編程 2025-04-29
  • Python列表中負數的個數

    Python列表是一個有序的集合,可以存儲多個不同類型的元素。而負數是指小於0的整數。在Python列表中,我們想要找到負數的個數,可以通過以下幾個方面進行實現。 一、使用循環遍歷…

    編程 2025-04-29
  • Python字典去重複工具

    使用Python語言編寫字典去重複工具,可幫助用戶快速去重複。 一、字典去重複工具的需求 在使用Python編寫程序時,我們經常需要處理數據文件,其中包含了大量的重複數據。為了方便…

    編程 2025-04-29
  • Python程序需要編譯才能執行

    Python 被廣泛應用於數據分析、人工智慧、科學計算等領域,它的靈活性和簡單易學的性質使得越來越多的人喜歡使用 Python 進行編程。然而,在 Python 中程序執行的方式不…

    編程 2025-04-29
  • 蝴蝶優化演算法Python版

    蝴蝶優化演算法是一種基於仿生學的優化演算法,模仿自然界中的蝴蝶進行搜索。它可以應用於多個領域的優化問題,包括數學優化、工程問題、機器學習等。本文將從多個方面對蝴蝶優化演算法Python版…

    編程 2025-04-29
  • python強行終止程序快捷鍵

    本文將從多個方面對python強行終止程序快捷鍵進行詳細闡述,並提供相應代碼示例。 一、Ctrl+C快捷鍵 Ctrl+C快捷鍵是在終端中經常用來強行終止運行的程序。當你在終端中運行…

    編程 2025-04-29
  • Python清華鏡像下載

    Python清華鏡像是一個高質量的Python開發資源鏡像站,提供了Python及其相關的開發工具、框架和文檔的下載服務。本文將從以下幾個方面對Python清華鏡像下載進行詳細的闡…

    編程 2025-04-29

發表回復

登錄後才能評論