騷年,一看就懂的深度學習來了!直接用Python直接寫一個自己的

怎麼入門機器/深度學習?可能很多人辛苦的花了幾個月學了線性代數,高數後,再開始很辛苦的不來由的懵懂的看著神經網絡,為什麼有隱藏層?為什麼有反饋?

以下就是為了解救有這些煩惱的你而來!用Python來從0搭建一個神經網絡,關鍵,你看得懂,很簡單的就搭建了一個你懂的神經網絡。

Have Fun!!


騷年,一看就懂的深度學習來了!直接用Python直接寫一個自己的


使用Python製作神經網絡

現在,我們將開始旅程,使用我們剛剛學習的Python知識製作神經網絡。

我們會沿著這個旅程,從簡單開始,小步前進,逐步建立Python程序。

從小處入手,然後讓程序慢慢長大,這是構建中等複雜度計算機代碼的一種簡捷的方式。

在完成了剛才的工作之後,我們非常自然地從建立神經網絡類的框架開始,讓我們直接前進吧!

框架代碼

讓我們勾勒神經網絡類的大概樣子。我們知道,它應該至少有3個函數:

  • 初始化函數——設定輸入層節點、隱藏層節點和輸出層節點的數量。
  • 訓練——學習給定訓練集樣本後,優化權重。
  • 查詢——給定輸入,從輸出節點給出答案。

目前,這些函數還未完全定義,也許還需要更多的函數,但是,就目前而言,讓我們從這些函數起步。

所編寫的代碼框架如下所示:

# neural network class definition
class neuralNetwork :

# initialise the neural network
def __init__() :
pass

# train the neural network
def train() :
pass

# query the neural network
def query() :
pass

這個開局不錯。事實上,這是一個堅實的框架,在這個框架上,你可以充實神經網絡工作的詳細細節了。

初始化網絡

從初始化網絡開始。我們需要設置輸入層節點、隱藏層節點和輸出層節點的數量。這些節點數量定義了神經網絡的形狀和尺寸。我們不會將這些數量固定,而是當我們使用參數創建一個新的神經網絡對象時,才會確定這些數量。通過這種方式,我們保留了選擇的餘地,輕鬆地創建不同大小的新神經網絡。

在我們剛剛所做出決定中,其底層蘊含著一個重要意義。優秀的程序員、計算機科學家和數學家,只要可能,都盡力創建一般代碼,而不是具體的代碼。這是一種好習慣,它迫使我們以一種更深更廣泛的適用方式思考求解問題。如果能做到這點,就意味著我們的解決方案可以適用於不同的場景。在此處,這意味著,我們將盡可能地為神經網絡開發代碼,使神經網絡保持儘可能多地開放有用的選項,並將假設降低到最低限度,從而使代碼很容易根據不同需要得到使用。我們希望同一個類可以創建一個小型的神經網絡,也可創建一個大型的神經網絡——只需傳遞所需的大小給參數即可。


騷年,一看就懂的深度學習來了!直接用Python直接寫一個自己的


同時也請不要忘了學習率。當創建新的神經網絡時,這也是待設置的有用參數。讓我們看看__init __()函數是什麼樣子的:

    # initialise the neural network
def __init__( self , inputnodes, hiddennodes, outputnodes,
learningrate ) :
# set number of nodes in each input, hidden, output layer
self . inodes = inputnodes
self . hnodes = hiddennodes
self . onodes = outputnodes

# learning rate
self . lr = learningrate
pass

讓我們使用所定義的神經網絡類,嘗試創建每層3個節點、學習率為0.5的小型神經網絡對象。

# number of input, hidden and output nodes
input_nodes = 3
hidden_nodes = 3
output_nodes = 3

# learning rate is 0.5
learning_rate = 0.5

# create instance of neural network
n = neuralNetwork(input_nodes,hidden_nodes,output_nodes,
learning_rate)

當然,這段代碼創建了一個對象,但是由於我們還沒有編碼任何函數執行實際的工作,因此這個對象還沒有任何用途。沒關係,從小處著眼,讓代碼逐步成長,在通往目標的途中,查找並解決問題,這是一種很好的技術。

為了確保讀者沒有迷失方向,下圖顯示了在這個階段的IPython Notebook,其中包含了神經網絡類的定義以及創建對象的代碼。


騷年,一看就懂的深度學習來了!直接用Python直接寫一個自己的


下一步該做些什麼呢?我們已經告訴神經網絡的對象,希望有多少個輸入層節點、隱藏層節點和輸出層節點,但是實際上,有關這個方面的任何工作都還沒有開始進行呢。

騷年,一看就懂的深度學習來了!直接用Python直接寫一個自己的

權重——網絡的核心

下一步是創建網絡的節點和鏈接。網絡中最重要的部分是鏈接權重,我們使用這些權重來計算前饋信號、反向傳播誤差,並且在試圖改進網絡時優化鏈接權重本身。


騷年,一看就懂的深度學習來了!直接用Python直接寫一個自己的


前面我們看到,可以使用矩陣簡明地表示權重。因此,我們可以創建:

  • 在輸入層與隱藏層之間的鏈接權重矩陣W input_hidden ,大小為hidden_ nodes 乘以 input_nodes。
  • 在隱藏層和輸出層之間的鏈接權重矩陣W hidden_output ,大小為hidden_nodes乘以 output_nodes。

請謹記先前的規則,來看看為什麼第一個矩陣的大小是input_nodes乘以 hidden_nodes,而不是hidden_node 乘以input_nodes。

請記住,在本書的第1章中,鏈接權重的初始值應該較小,並且是隨機的。下面的numpy函數生成一個數組,數組中元素為0~1的隨機值,數組的大小為rows乘以columns。

numpy. random. rand( rows , columns )

所有優秀的程序員都使用互聯網搜索引擎來查找關於使用酷炫的Python函數的在線文檔,甚至找到了他們不知道的、已存在的非常實用的函數。Google在查找關於編程的信息方面特別有用,例如此處描述的numpy.random.rand()函數。

如果要使用numpy的擴展包,那麼需要在代碼頂端導入庫。

試試這個函數,並自己確認函數能夠工作。下圖顯示了這個函數可以生成3×3的numpy數組。數組中的每個值都是0~1的隨機值。

騷年,一看就懂的深度學習來了!直接用Python直接寫一個自己的

我們其實可以做得更好。我們忽略了權重可以為正數也可以為負數。權重的範圍可以在-1.0到+1.0之間。為了簡單起見,我們可以將上面數組中的每個值減去0.5,這樣,在效果上,數組中的每個值都成為了-0.5到0.5之間的隨機值。下圖顯示這個小訣竅成功了,你可以看到一些小於0的隨機值。

騷年,一看就懂的深度學習來了!直接用Python直接寫一個自己的

我們已經準備好了,在Python程序中創建初始權重矩陣。權重是神經網絡的固有部分,與神經網絡共存亡,它不是一個臨時數據集,不會隨著函數調用結束而消失。這意味著,權重必須也是初始化的一部分,並且可以使用其他函數(如訓練函數和查詢函數)來訪問。

下面的代碼包括了註釋,創建了兩個鏈接權重矩陣,並使用self. inodes、self. hnodes和 self. onodes為兩個鏈接權重矩陣設置了合適的大小。

# link weight matrices, wih and who
# weights inside the arrays are w_i_j, where link is from node
i to node j in the next layer
# w11 w21
# w12 w22 etc
self.wih = (numpy.random.rand(self.hnodes, self.inodes) - 0.5)
self.who = (numpy.random.rand(self.onodes, self.hnodes) - 0.5)

做得好!我們已經實現了神經網絡的心臟——鏈接權重矩陣!

可選項:較複雜的權重

我們可以選擇這種簡單卻是流行的優化初始權重的方式。

如果閱讀本書第1章關於準備數據以及初始化權重的討論,你將會發現,有些人更喜歡稍微複雜的方法來創建初始隨機權重。他們使用正態概率分佈採樣權重,其中平均值為0,標準方差為節點傳入鏈接數目的開方,即1/

騷年,一看就懂的深度學習來了!直接用Python直接寫一個自己的

在numpy程序庫的幫助下,這是很容易實現的。同樣,Google可以幫助我們找到合適的文檔。numpy.random.normal()函數可以幫助我們以正態分佈的方式採樣。由於我們所需要的是隨機矩陣,而不是單個數字,因此採用分佈中心值、標準方差和numpy數組的大小作為參數。

初始化權重的更新代碼看起來如下所示:

self.wih = numpy.random.normal ( 0.0 , pow(self.hnodes, -0.5) ,
(self.hnodes, self.inodes) )
self.who = numpy.random.normal ( 0.0 , pow(self.onodes, -0.5) ,
(self.onodes, self.hnodes) )

我們將正態分佈的中心設定為0.0。與下一層中節點相關的標準方差的表達式,按照Python的形式,就是pow(self.hnodes, -0.5),簡單說來,這個表達式就是表示節點數目的-0.5次方。最後一個參數,就是我們希望的numpy數組的形狀大小。

查詢網絡

接下來,順理成章,我們現在應該編寫訓練神經網絡的代碼,填寫當前空的train()函數。但是,還是等一下再寫train()函數,讓我們先編寫簡單的query()函數吧。這將會給我們更多的時間來逐步建立信心,獲得使用Python和神經網絡對象內部權重矩陣的實踐經驗。

query()函數接受神經網絡的輸入,返回網絡的輸出。這個功能非常簡單,但是,為了做到這一點,你要記住,我們需要傳遞來自輸入層節點的輸入信號,通過隱藏層,最後從輸出層輸出。你還要記住,當信號饋送至給定的隱藏層節點或輸出層節點時,我們使用鏈接權重調節信號,還應用S激活函數抑制來自這些節點的信號。

如果有很多節點,那麼我們就面臨著一個很可怕的任務,即為這些節點中的每一個寫出Python代碼,進行權重調節,加和信號,應用激活函數。節點越多,代碼越多。這簡直是一場噩夢!好在我們知道了如何使用簡單簡潔的矩陣形式寫出這些指令,因此無需這樣做。下式顯示了輸入層和隱藏層之間的鏈接權重矩陣如何與輸入矩陣相乘,給出隱藏層節點的輸入信號。

X hidden = W input_hidden · I

這樣做的好處,不僅是更容易書寫,而且如Python這樣的編程語言也可以理解矩陣,由於這些編程語言認識到所有這些基礎計算之間的相似之處,它們可以非常有效率地完成所有實際工作。

你會驚訝於Python代碼實際上是多麼簡單!以下代碼應用了numpy代碼庫,將鏈接權重矩陣 W input_hidden 點乘輸入矩陣I。

hidden_inputs = numpy.dot(self.wih, inputs)

計算結束!

這一段簡單的Python完成了所有的工作,將所有的輸入與所有正確的鏈接權重組合,生成了組合調節後的信號矩陣,傳輸給每個隱藏層節點。如果下一次選擇使用不同數量的輸入層節點或隱藏層節點,不必重寫這段代碼就可以進行工作。這種力量與優雅就是我們先前將精力投入到理解如何使用矩陣乘法的原因。

為了獲得從隱藏層節點處出現的信號,我們簡單地將S抑制函數應用到每一個出現的信號上:

O hidden = sigmoid( X hidden )

如果在某個現成的Python庫中,已經定義了這個S函數,那麼這種操作就變得非常容易。果不其然!SciPy Python庫有一組特殊的函數,在這組函數中,S函數稱為expit()。不要問我為什麼S函數有這樣一個愚蠢的名字。可以像導入numpy程序庫一樣,導入scipy函數庫:

# scipy.special for the sigmoid function expit() 
import scipy.special

由於我們可能希望進行實驗和調整,甚至完全改變激活函數,因此當神經網絡對象初始化時,在神經網絡對象內部只定義一次S函數,這麼做是有道理的。在此之後,我們也多次引用了S函數,例如在query()函數中。這樣的安排意味著只需要改變S函數的定義一次,而無需找到使用激活函數的每個位置以改變其代碼。

在神經網絡初始化部分的代碼內部,下列代碼定義了希望使用的激活函數。

# activation function is the sigmoid function 
self.activation_function = lambda x: scipy.special.expit(x)

這是什麼代碼?它看起來不像我們以前見過的任何代碼。lambda是什麼?這看起來可能有點令人生畏,但是實際上,這並不可怕。這裡所做的一切就是創建一個函數,就像創建其他函數一樣,不過我們使用了較短的方式將這個函數寫出來了。我們不使用通常的def()來定義函數,在此,我們使用神奇的lambda來創建函數,方便又快捷。這個函數接受了x,返回scipy.special.expit(x),這就是S函數。使用lambda創建的函數是沒有名字的,經驗豐富的程序員喜歡稱它們為匿名函數,但是這裡分配給它一個名字self.activation_function()。所有這些事情意味著,無論何時任何人需要使用激活函數,那麼他所需做的就是調用self.activation_function()。

回到手上的任務,我們要將激活函數應用到組合調整後,準備進入隱藏層節點的信號。其代碼與下面的代碼一樣簡單:

# calculate the signals emerging from hidden layer 
hidden_outputs = self.activation_function(hidden_inputs)

也就是說,隱藏層節點的輸出信號在名為hidden_outputs的矩陣中。

這讓信號到達了中間隱藏層,那麼信號如何到達最終輸出層呢?其實,在隱藏層節點和最終輸出層節點之間沒有什麼本質的區別,因此過程也是一樣的。這意味著代碼也非常相似。

看看下面的代碼,這些代碼總結了我們如何計算隱藏層信號和輸出層信號。

# calculate signals into hidden layer
hidden_inputs = numpy.dot(self.wih, inputs)
# calculate the signals emerging from hidden layer
hidden_outputs = self.activation_function(hidden_inputs)

# calculate signals into final output layer
final_inputs = numpy.dot(self.who, hidden_outputs)
# calculate the signals emerging from final output layer
final_outputs = self.activation_function(final_inputs)

如果刪除註釋,那麼只有四行粗體顯示的代碼進行了所需的計算,兩行為隱藏層,兩行為最終輸出層。

迄今為止的代碼

讓我們喘一口氣,停下來,檢查一下正在構建的神經網絡類的代碼看起來怎麼樣了。這看起來應該如下所示。

# neural network class definition
class neuralNetwork :


# initialise the neural network
def __init__(self, inputnodes, hiddennodes, outputnodes,
learningrate) :
# set number of nodes in each input, hidden, output

layer
self.inodes = inputnodes
self.hnodes = hiddennodes
self.onodes = outputnodes

# link weight matrices, wih and who
# weights inside the arrays are w_i_j, where link is
from node i to node j in the next layer
# w11 w21
# w12 w22 etc
self.wih = numpy.random.normal(0.0, pow(self.hnodes,
-0.5), (self.hnodes, self.inodes))
self.who = numpy.random.normal(0.0, pow(self.onodes,
-0.5), (self.onodes, self.hnodes))
# learning rate
self.lr = learningrate

# activation function is the sigmoid function
self.activation_function = lambda x:
scipy.special.expit(x)

pass


# train the neural network
def train() :
pass


# query the neural network
def query(self, inputs_list) :
# convert inputs list to 2d array
inputs = numpy.array(inputs_list, ndmin=2).T

# calculate signals into hidden layer
hidden_inputs = numpy.dot(self.wih, inputs)
# calculate the signals emerging from hidden layer
hidden_outputs =
self.activation_function(hidden_inputs)

# calculate signals into final output layer
final_inputs = numpy.dot(self.who, hidden_outputs)
# calculate the signals emerging from final output
layer
final_outputs = self.activation_function(final_inputs)

return final_outputs

這就是類的代碼。除此之外,應該在Notebook的第一個單元格中,在代碼頂部導入numpy和scipy.special:

import numpy 
# scipy.special for the sigmoid function expit()
import scipy.special

值得一提的是,query()函數只需要input_list。它不需要任何其他輸入。

我們已經取得了很好的進展,現在,我們來看看缺少的train()函數。請記住,在訓練神經網絡的過程中有兩個階段,第一個階段就是計算輸出,如同query()所做的事情,第二個階段就是反向傳播誤差,告知如何優化鏈接權重。

在繼續編寫train()函數並使用樣本訓練網絡之前,讓我們測試目前得到的所有的代碼。我們創建一個小網絡,使用一些隨機輸入查詢網絡,看看網絡如何工作。顯而易見,這樣做不會有任何實際意義,只是為了使用剛剛創建的函數。

下圖顯示的是所創建的小型網絡,其中,在輸入層、隱藏層和輸出層中,每層有3個節點,並且使用隨機選擇的輸入(1.0,0.5,-1.5)查詢網絡。

騷年,一看就懂的深度學習來了!直接用Python直接寫一個自己的

你可以發現,神經網絡對象的創建確實需要設置學習率,即使現在還不使用這個學習率。神經網絡類的定義有一個初始化函數__init __(),這個函數需要指定一個學習率。如果不設置學習率,Python代碼將不會成功運行,並且會拋出錯誤信息。

輸入是一個列表,Python語言將列表寫在方括號內。輸出也是數字列表。由於還沒有訓練網絡,這個輸出沒有實際意義,但是我們還是很高興代碼沒有出錯。

訓練網絡

現在來解決這個稍微複雜的訓練任務。訓練任務分為兩個部分:

  • 第一部分,針對給定的訓練樣本計算輸出。這與我們剛剛在query()函數上所做的沒什麼區別。
  • 第二部分,將計算得到的輸出與所需輸出對比,使用差值來指導網絡權重的更新。

我們已經完成了第一部分,現在,先把這部分寫出來:

# train the neural network
def train(self, inputs_list, targets_list):
# convert inputs list to 2d array

inputs = numpy.array(inputs_list, ndmin=2).T
targets = numpy.array(targets_list, ndmin=2).T

# calculate signals into hidden layer
hidden_inputs = numpy.dot(self.wih, inputs)
# calculate the signals emerging from hidden layer
hidden_outputs = self.activation_function(hidden_inputs)

# calculate signals into final output layer
final_inputs = numpy.dot(self.who, hidden_outputs)
# calculate the signals emerging from final output layer
final_outputs = self.activation_function(final_inputs)

pass

我們使用完全相同的方式從輸入層前饋信號到最終輸出層,所以這段代碼與在query()函數中的幾乎完全一樣。

由於需要使用包含期望值或目標答案的訓練樣本來訓練網絡——因此唯一的區別是,這部分代碼中有一個額外的參數,即在函數的名稱中定義的targets_list。

def train (self, inputs_list, targets_list) 

這段代碼還把targets_list變成了numpy數組,就像inputs_list變成numpy數組一樣。

targets = numpy.array(targets_list, ndmin=2).T

現在,我們越來越接近神經網絡工作的核心,即基於所計算輸出與目標輸出之間的誤差,改進權重。

讓我們按照輕柔可控的步驟,進行這種操作。

首先需要計算誤差,這個值等於訓練樣本所提供的預期目標輸出值與實際計算得到的輸出值之差。這個差也就是將矩陣targets和矩陣final_outputs中每個對應元素相減得到的。Python代碼非常簡單,這再次優雅地顯示了矩陣的力量。

# error is the (target - actual) 
output_errors = targets - final_outputs

我們可以計算出隱含層節點反向傳播的誤差。請回憶一下如何根據所連接的權重分割誤差,為每個隱藏層節點重組這些誤差。對於這個計算過程,我們得到了其矩陣形式:

errors hidden = weights T hidden_output · errors output

由於Python有能力使用numpy進行點乘,因此,這段代碼再簡單不過了:

# hidden layer error is the output_errors, split by weights,
recombined at hidden nodes
hidden_errors = numpy.dot(self.who.T, output_errors)

這樣,我們就擁有了所需要的一切,可以優化各個層之間的權重了。對於在隱蔽層和最終層之間的權重,我們使用output_errors進行優化。對於輸入層和隱藏層之間的權重,我們使用剛才計算得到的hidden_errors進行優化。

先前,我們得到了用於更新節點j與其下一層節點k之間鏈接權重的矩陣形式的表達式:

騷年,一看就懂的深度學習來了!直接用Python直接寫一個自己的

α是學習率,sigmoid是先前看到的激活函數。請記住,*乘法是正常的對應元素的乘法,·點乘是矩陣點積。最後一點要注意,來自上一層的輸出矩陣被轉置了。實際上,這意味著輸出矩陣的列變成了行。

在Python代碼中,這種轉換很容易。我們首先為隱藏層和最終層之間的權重進行編碼。

# update the weights for the links between the hidden and output
layers
self.who += self.lr * numpy.dot( ( output_errors * final_outputs *
(1.0 - final_outputs) ) , numpy.transpose(hidden_outputs) )

雖然這是一段很長的代碼,但是,彩色標記應該有助於發現代碼與數學表達式的聯繫。學習率是self.lr,它就是很簡單地與表達式的其餘部分進行相乘。我們使用numpy.dot進行矩陣乘法,紅色的元素顯示了與來自下一層的誤差和S函數相關的部分,綠色的元素顯示了與來自前一層轉置輸出矩陣的相關部分。

簡單說來,+ = 意思是將先前變量增加一個量。因此,x + = 3,意思就是x增加3。這是x = x + 3的簡短寫法。也可以使用這種方法表示其他運算,如x / = 3表示x除以3。

用於輸入層和隱藏層之間權重的代碼也是類似的。我們只是利用對稱性,重寫代碼,更換名字,這樣它們指的就是神經網絡的前一層了。下面是這兩個權重集的代碼,代碼著色了,這樣你可以發現它們之間的異同點:

# update the weights for the links between the hidden and output
layers
self. who += self.lr * numpy.dot(( output_errors * final_outputs *
(1.0 - final_outputs) ), numpy.transpose(hidden_outputs) )

# update the weights for the links between the input and hidden
layers
self. wih += self.lr * numpy.dot(( hidden_errors * hidden_outputs *
(1.0 - hidden_outputs) ), numpy.transpose(inputs) )

計算結束!

我們先前進行的所有工作、海量的計算、努力得到的矩陣方法、通過梯度下降法最小化網絡誤差……所有的這些都變成了以上簡短而簡潔的代碼,這真是難以置信!在某種意義上,這是Python力量的表現,但是,實際上,這是我們努力工作並簡化那些很容易變得複雜而可怕事情的結果。

完整的神經網絡代碼

我們已經完成了神經網絡類。以下代碼僅供參考,你可以通過以下鏈接訪問GitHub,這是一個共享代碼的在線網站:

  • https://github.com/makeyourownneuralnetwork/makeyourownneuralnetwork/ blob/master/part2_neural_network.ipynb
# neural network class definition
class neuralNetwork :
# initialise the neural network
def __init__(self, inputnodes, hiddennodes, outputnodes,
learningrate) :
# set number of nodes in each input, hidden, output layer
self.inodes = inputnodes
self.hnodes = hiddennodes

self.onodes = outputnodes

# link weight matrices, wih and who
# weights inside the arrays are w_i_j, where link is from
node i to node j in the next layer
# w11 w21
# w12 w22 etc
self.wih = numpy.random.normal(0.0, pow(self.hnodes, -0.5),
(self.hnodes, self.inodes))
self.who = numpy.random.normal(0.0, pow(self.onodes, -0.5),
(self.onodes, self.hnodes))


# learning rate
self.lr = learningrate

# activation function is the sigmoid function
self.activation_function = lambda x: scipy.special.expit(x)

pass


# train the neural network
def train(self, inputs_list, targets_list) :
# convert inputs list to 2d array
inputs = numpy.array(inputs_list, ndmin=2).T
targets = numpy.array(targets_list, ndmin=2).T

# calculate signals into hidden layer
hidden_inputs = numpy.dot(self.wih, inputs)
# calculate the signals emerging from hidden layer
hidden_outputs = self.activation_function(hidden_inputs)

# calculate signals into final output layer
final_inputs = numpy.dot(self.who, hidden_outputs)
# calculate the signals emerging from final output layer
final_outputs = self.activation_function(final_inputs)
# output layer error is the (target - actual)
output_errors = targets - final_outputs
# hidden layer error is the output_errors, split by weights,
recombined at hidden nodes
hidden_errors = numpy.dot(self.who.T, output_errors)

# update the weights for the links between the hidden and
output layers
self.who += self.lr * numpy.dot((output_errors *
final_outputs * (1.0 - final_outputs)),
numpy.transpose(hidden_outputs))

# update the weights for the links between the input and

hidden layers
self.wih += self.lr * numpy.dot((hidden_errors *
hidden_outputs * (1.0 - hidden_outputs)), numpy.transpose
(inputs))
pass


# query the neural network
def query(self, inputs_list) :
# convert inputs list to 2d array
inputs = numpy.array(inputs_list, ndmin=2).T

# calculate signals into hidden layer
hidden_inputs = numpy.dot(self.wih, inputs)
# calculate the signals emerging from hidden layer
hidden_outputs = self.activation_function(hidden_inputs)

# calculate signals into final output layer
final_inputs = numpy.dot(self.who, hidden_outputs)
# calculate the signals emerging from final output layer
final_outputs = self.activation_function(final_inputs)

return final_outputs

這些代碼可用於創建、訓練和查詢3層神經網絡,進行幾乎任何任務,這麼看來,代碼不算太多。

下一步,我們將進行特定任務,學習識別手寫數字。

點擊更多獲取


騷年,一看就懂的深度學習來了!直接用Python直接寫一個自己的


分享到:


相關文章: