用Keras編寫你的第一個(gè)神經(jīng)網(wǎng)絡(luò),用不了30行代碼!
譯文【51CTO.com快譯】回想起剛接觸AI時(shí),我清楚地記得一些概念看起來(lái)有多難。閱讀神經(jīng)網(wǎng)絡(luò)的簡(jiǎn)單介紹常常碰到科學(xué)論文,里面的公式有你從未見過(guò)的符號(hào),但開始編寫第一個(gè)神經(jīng)網(wǎng)絡(luò)實(shí)際上容易得多!
那么神經(jīng)網(wǎng)絡(luò)是什么呢?
這個(gè)問(wèn)題提得好!在自行用Python代碼編寫一個(gè)簡(jiǎn)單的神經(jīng)網(wǎng)絡(luò)之前,不妨介紹一下神經(jīng)網(wǎng)絡(luò)以及為何它如此令人興奮!
HNC Software的聯(lián)合創(chuàng)始人Robert Hecht-Nielsen博士簡(jiǎn)單地說(shuō)。
……神經(jīng)網(wǎng)絡(luò)是由許多簡(jiǎn)單又高度互連的處理單元組成的計(jì)算系統(tǒng),這些處理單元通過(guò)對(duì)外部輸入的動(dòng)態(tài)狀態(tài)響應(yīng)來(lái)處理信息。
——人工智能專家Maureen Caudill撰寫的《神經(jīng)網(wǎng)絡(luò)入門:第一部分》,1989年2月
實(shí)際上,神經(jīng)網(wǎng)絡(luò)是一組擅長(zhǎng)識(shí)別信息或數(shù)據(jù)中模式的數(shù)學(xué)表達(dá)式。神經(jīng)網(wǎng)絡(luò)通過(guò)一種模仿人類的感知來(lái)做到這點(diǎn),但它不是像人類那樣查看圖片,而是表示以數(shù)字方式包含在Vector或Scalar中的信息(一個(gè)Vector只含一個(gè)數(shù)字)。
它通過(guò)層來(lái)傳遞該信息,一層的輸出充當(dāng)下一層的輸入。經(jīng)過(guò)這些層時(shí),輸入通過(guò)權(quán)重和偏差加以修改,然后發(fā)送到激活函數(shù)以映射輸出。然后通過(guò)成本函數(shù)進(jìn)行學(xué)習(xí),該函數(shù)對(duì)實(shí)際輸出和所需輸出進(jìn)行比較,這進(jìn)而通過(guò)一種名為反向傳播的過(guò)程,幫助函數(shù)更改并調(diào)整權(quán)重和偏差,實(shí)現(xiàn)成本最小化。
對(duì)于我們實(shí)現(xiàn)的示例神經(jīng)網(wǎng)絡(luò),我們將使用MNIST數(shù)據(jù)集。
圖1. MNIST樣本數(shù)據(jù)集
MNIST好比是“Hello World”數(shù)據(jù)集,因?yàn)樗軌蚍浅:?jiǎn)明地演示神經(jīng)網(wǎng)絡(luò)的功能。數(shù)據(jù)集由手寫數(shù)字組成,我們將訓(xùn)練神經(jīng)網(wǎng)絡(luò)識(shí)別和分類這些數(shù)字。
Keras登場(chǎng)
為了便于實(shí)現(xiàn),我們將使用Keras框架。Keras是用Python編寫的一種高級(jí)API,它在TensorFlow和Theano等流行框架上運(yùn)行,為機(jī)器學(xué)習(xí)從業(yè)人員提供了抽象層,以降低編寫神經(jīng)網(wǎng)絡(luò)的固有復(fù)雜性。
建議你深入研究Keras說(shuō)明文檔(https://keras.io/),以真正熟悉該API。另外強(qiáng)烈推薦Francois Chollet撰寫的《用Python做深度學(xué)習(xí)》一書,本教程的靈感源自此書。
該考驗(yàn)GPU的時(shí)候了
我們?cè)诒窘坛讨袑⑹褂肒eras和TensorFlow后端,因此如果你尚未安裝其中任何一個(gè),現(xiàn)在趕緊安裝,只需在終端中運(yùn)行這些命令即可。如果你不單單想了解簡(jiǎn)單的入門示例,最好搭建Anaconda環(huán)境,改用conda安裝以下內(nèi)容。
- pip3 install Keras
- pip3 install Tensorflow
你已安裝了第一個(gè)神經(jīng)網(wǎng)絡(luò)所需的一切,現(xiàn)在打開常用的IDE,不妨導(dǎo)入我們所需的Python模塊!
- from keras.datasets import mnist
- from keras import models
- from keras import layers
- from keras.utils import to_categorical
Keras有許多數(shù)據(jù)集可以用來(lái)幫助你學(xué)習(xí),對(duì)我們來(lái)說(shuō)幸好有MNIST這個(gè)數(shù)據(jù)集。Models和Layers這兩個(gè)模塊可幫助我們構(gòu)建神經(jīng)網(wǎng)絡(luò),to_categorical用于數(shù)據(jù)編碼,不過(guò)稍后有詳細(xì)介紹。
我們已導(dǎo)入了所需的模塊,接下來(lái)應(yīng)將數(shù)據(jù)集分成訓(xùn)練集和測(cè)試集。只要用下面這一行即可完成。
- (train_images, train_labels), (test_images, test_labels) = mnist.load_data()
在該例子中,我們的神經(jīng)網(wǎng)絡(luò)通過(guò)對(duì)其輸出與標(biāo)記數(shù)據(jù)進(jìn)行比較來(lái)學(xué)習(xí)??梢园堰@看成我們讓神經(jīng)網(wǎng)絡(luò)猜測(cè)大量的手寫數(shù)字,然后將猜測(cè)結(jié)果與實(shí)際標(biāo)簽進(jìn)行比較。隨后饋入結(jié)果,幫助模型調(diào)整權(quán)重和偏差,以便實(shí)現(xiàn)總成本最小化。
訓(xùn)練集和數(shù)據(jù)集已建好,現(xiàn)在我們準(zhǔn)備構(gòu)建模型。
- network = models.Sequential()
- network.add(layers.Dense(784, activation='relu', input_shape=(28 * 28,)))
- network.add(layers.Dense(784, activation='relu', input_shape=(28 * 28,)))network.add(layers.Dense(10, activation='softmax'))network.compile(optimizer='adam',
- loss='categorical_crossentropy',
- metrics=['accuracy'])
這看起來(lái)代碼有很多,但不妨分解一下。我們初始化名為network的順序模型。
- network = models.Sequential()
然后我們添加神經(jīng)網(wǎng)絡(luò)層。針對(duì)該例子,我們將使用密集層。密集層是指,每個(gè)神經(jīng)元從上一層的所有神經(jīng)元接收輸入。[784]和[10]指輸出空間的維數(shù),這好比是后續(xù)層的輸入數(shù);由于我們?cè)噲D解決的分類問(wèn)題有10種可能的類別(數(shù)字0至9),最后層的潛在輸出是10個(gè)單位。激活參數(shù)指我們想要使用的激活函數(shù),實(shí)際上激活函數(shù)根據(jù)給定的輸入來(lái)計(jì)算輸出。 最后,28 * 28的輸入形狀是指圖片的像素寬度和高度。
- network.add(layers.Dense(784, activation='relu', input_shape=(28 * 28,)))
- network.add(layers.Dense(784, activation='relu', input_shape=(28 * 28,)))
- network.add(layers.Dense(10, activation='softmax'))
一旦模型定義完畢,并添加了神經(jīng)網(wǎng)絡(luò)層,我們只需用所選擇的優(yōu)化器、所選擇的損失函數(shù)以及想用來(lái)評(píng)估模型性能的度量標(biāo)準(zhǔn)來(lái)編譯該模型。
- network.compile(optimizer='adam',
- loss='categorical_crossentropy',
- metrics=['accuracy'])
恭喜!你剛構(gòu)建了你的第一個(gè)神經(jīng)網(wǎng)絡(luò)!
現(xiàn)在你可能仍有幾個(gè)問(wèn)題,比如relu和softmax是什么?adam又是誰(shuí)?那些都是值得思考的問(wèn)題……我們會(huì)在以后的文章中深入解釋這些問(wèn)題。
將數(shù)據(jù)饋入到剛創(chuàng)建的模型之前,我們需要將輸入整形成模型可以讀取的格式。輸入的原始形狀是[60000,28,28],實(shí)際上代表60000個(gè)像素高度和寬度是28 x28的圖片。我們可以對(duì)數(shù)據(jù)進(jìn)行整形,分為訓(xùn)練[60000]圖片和測(cè)試[10000]圖片。
- train_images = train_images.reshape((60000, 28 * 28))
- train_images = train_images.astype('float32') / 255
- test_images = test_images.reshape((10000, 28 * 28))
- test_images = test_images.astype('float32') / 255
除了整形數(shù)據(jù)外,我們還需要編碼數(shù)據(jù)。針對(duì)該例子,我們將使用分類編碼,這實(shí)際上將許多特征變成數(shù)值表示。
- train_labels = to_categorical(train_labels)
- test_labels = to_categorical(test_labels)
我們的數(shù)據(jù)集已分成訓(xùn)練集和測(cè)試集,而且模型經(jīng)過(guò)編譯、數(shù)據(jù)經(jīng)過(guò)整形和編碼,現(xiàn)在我們現(xiàn)在準(zhǔn)備訓(xùn)練神經(jīng)網(wǎng)絡(luò)!為此,我們要調(diào)用fit函數(shù),并傳遞所需的參數(shù)。
- network.fit(train_images, train_labels, epochs=5, batch_size=128)
我們傳遞訓(xùn)練圖片及其標(biāo)簽,另外傳遞輪次(epoch)和批大小(batch_size),前者表明了向后傳播和向前傳播的數(shù)量,后者表明了每個(gè)向后/向前傳播的訓(xùn)練樣本數(shù)量。
我們還想要設(shè)置性能衡量參數(shù),以便搞清楚這個(gè)模型的效果有多好。
- test_loss, test_acc = network.evaluate(test_images, test_labels)
- print('test_acc:', test_acc, 'test_loss', test_loss)
大功告成!你剛編寫了自己的神經(jīng)網(wǎng)絡(luò),整形并編碼了數(shù)據(jù)集,并擬合了訓(xùn)練的模型。如果你首次運(yùn)行Python腳本,Keras會(huì)下載MNIST數(shù)據(jù)集,開始訓(xùn)練5輪。
使用測(cè)試輸出的訓(xùn)練周期
你的測(cè)試準(zhǔn)確度應(yīng)該達(dá)到98%左右,這意味著模型運(yùn)行測(cè)試時(shí)在98%的時(shí)間段內(nèi)正確預(yù)測(cè)了數(shù)字,這對(duì)你的第一個(gè)神經(jīng)網(wǎng)絡(luò)來(lái)說(shuō)不賴!實(shí)際上,如果你的模型擬合過(guò)度/擬合不足,你希望同時(shí)查看測(cè)試結(jié)果和訓(xùn)練結(jié)果,以便想出好主意。
鼓勵(lì)你調(diào)整一下層數(shù)、優(yōu)化器、損失函數(shù)、輪次以及批大小,看看各自對(duì)模型的整體性能有何影響!
原文標(biāo)題:Writing Your First Neural Net in Less Than 30 Lines of Code with Keras,作者:David Gündisch
【51CTO譯稿,合作站點(diǎn)轉(zhuǎn)載請(qǐng)注明原文譯者和出處為51CTO.com】