Linux 桌面玩家指南:15. 深度學習可以這樣玩
特別說明:要在我的隨筆後寫評論的小夥伴們請注意了,我的部落格開啟了 MathJax 數學公式支援,MathJax 使用 $
標記數學公式的開始和結束。如果某條評論中出現了兩個 $
,MathJax 會將兩個 $
之間的內容按照數學公式進行排版,從而導致評論區格式混亂。如果大家的評論中用到了 $
,但是又不是為了使用數學公式,就請使用 \$
轉義一下,謝謝。
想從頭閱讀該系列嗎?下面是傳送門:
- LinuxDesktop001.html" rel="nofollow,noindex" target="_blank">Linux 桌面玩家指南:01. 玩轉 Linux 系統的方法論 【約 1.1 萬字,22 張圖片】
- Linux 桌面玩家指南:02. 以最簡潔的方式打造實用的 Vim 環境 【約 0.97 萬字,7 張圖片】
- Linux 桌面玩家指南:03. 針對 Gnome 3 的 Linux 桌面進行美化 【約 0.58 萬字,32 張圖片】
- Linux 桌面玩家指南:04. Linux 桌面系統字型配置要略 【約 1.2 萬字,34 張圖片】
- Linux 桌面玩家指南:05. 發部落格必備的圖片處理和視訊錄製神器 【約 0.25 萬字,14 張圖片】
- Linux 桌面玩家指南:06. 優雅地使用命令列及 Bash 指令碼程式語言中的美學與哲學 【約 1.4 萬字,16 張圖片】
- Linux 桌面玩家指南:07. Linux 中的 Qemu、KVM、VirtualBox、Xen 虛擬機器體驗 【約 0.95 萬字,31 張圖片】
- Linux 桌面玩家指南:08. 使用 GCC 和 GNU Binutils 編寫能在 x86 真實模式執行的 16 位程式碼 【約 0.6 萬字,17 張圖片】
- Linux 桌面玩家指南:09. X Window 的奧祕 【約 0.5 萬字,14 張圖片】
- Linux 桌面玩家指南:10. 沒有 GUI 的時候應該怎麼玩 【約 0.5 萬字,32 張圖片】
- Linux 桌面玩家指南:11. 在同一個硬碟上安裝多個 Linux 發行版以及為 Linux 安裝 Nvidia 顯示卡驅動 【約 0.4 萬字,22 張圖片】
- Linux 桌面玩家指南:12. 優秀的文字化編輯思想大碰撞(Markdown、LaTeX、MathJax) 【約 0.4 萬字,8 張圖片】
- Linux 桌面玩家指南:13. 使用 Git 及其 和 Eclipse 的整合 【約 0.6 萬字,31 張圖片】
- Linux 桌面玩家指南:14. 數值計算和符號計算 【約 0.6 萬字,15 張圖片】
前言
這一篇相當於是深度學習方面的一個 Hello World 吧。深度學習目前大火,吸引了無數人。但是很多時候,想了解深度學習的人總覺得雲山霧罩,怎麼也看不明白。如果要是有一個能執行的簡單的深度學習的例子該多好啊。我這裡就來玩一玩深度學習,來一個讓大家摸得著、看得見的例子,揭開深度學習的神祕面紗。語言方面,當然是選擇對科學計算極度友好的 Python 啦。我當然不會從頭擼程式碼,肯定會使用現成的庫的啦。目前最流行的深度學習框架是 Keras,在 Keras 中,它又使用了大名鼎鼎的 TensorFlow 作為後端。在 Python 中,安裝這幾個庫真的是太方便了。最後說一句,我用的是 Python3。
上一篇浮光掠影地講了一下科學計算,並探討了一下適合數值計算的語言需要什麼樣的特色。非常幸運,Python 正好具有這樣的特色,準確地說,應該是 Python 中的 numpy 庫正好具有這樣的特色。上一篇的內容略有過時,比如 IPython Notebook,目前就已經改成 Jupyter Notebook 了。但是在這一篇中,我就不用什麼 Notebook 了,我用 PyCharm。
JetBrains 大家都知道啦,JetBrains 全家桶是廣大程式員的福利啦。做科學計算,使用 PyCharm 的 Community 版就足夠了,沒必要下載 Professional 版啦,我更加是不鼓勵大家用破解版的啦。
環境安裝
到 JetBrains 的官網下載最新的 PyCharm 2018.3,正如前面所說,Community 版就夠了。解壓,執行之,用它建立一個 Python 專案,選擇使用虛擬環境,如下圖:

使用虛擬環境的好處,是可以為這個專案單獨安裝依賴的庫,不用擔心為了學一個什麼東西而把系統中的 Python 搞得亂七八糟。直接開啟 PyCharm 中的 Terminal,就可以進入這個專案的虛擬環境,在這個 Terminal 中執行的命令,預設就在這個專案的虛擬環境中執行。我們可以在這個 Terminal 中執行 pip3 install
命令安裝所有需要的庫。在 PyCharm 中使用 pip3 install
命令時,有一個令人頭痛的問題,那就是從國外的源下載的速度太慢,我們可以替換成國內的源。我太懶,都是使用臨時替換,只需要新增 -i 源地址
引數就可以了。例如,要安裝 numpy,並且選擇從阿里雲下載,就使用 pip3 install numpy -i https://mirrors.aliyun.com/pypi/simple/
命令。如下圖:

常用的國內源有:
- 清華:https://pypi.tuna.tsinghua.edu.cn/simple
- 阿里雲:https://mirrors.aliyun.com/pypi/simple/
- 中國科技大學 https://pypi.mirrors.ustc.edu.cn/simple/
- 華中理工大學:http://pypi.hustunique.com/
- 山東理工大學:http://pypi.sdutlinux.org/
- 豆瓣:http://pypi.douban.com/simple/
新版 Ubuntu 要求使用 https 源,要注意。
在這裡,我們需要安裝 numpy、keras、tensorflow、matplotlib 庫,numpy 用來操作向量和矩陣,matplotlib 用來畫圖。為了能夠讀取和預處理圖片,我還需要使用 PIL,可惜 PIL 不支援 Python 3,不過沒關係,使用 Pillow 就好了。安裝這幾個庫只需要如下幾個命令:
pip3 install numpy -i https://mirrors.aliyun.com/pypi/simple/ pip3 install tensorflow -i https://mirrors.aliyun.com/pypi/simple/ pip3 install keras -i https://mirrors.aliyun.com/pypi/simple/ pip3 install matplotlib -i https://mirrors.aliyun.com/pypi/simple/ pip3 install Pillow -i https://mirrors.aliyun.com/pypi/simple/
這些庫都直接安裝到了我們的專案內,不會和系統中的 Python 起衝突。如下圖:

PyCharm 最大的優勢當然是它的自動程式碼提示了。不管是寫一個 .py
檔案,還是直接使用 PyCharm 中的 Python Console,就是有非常好的程式碼提示的。Python Console 還有一個非常棒的功能,就是可以觀察每一個變數的值,真的是太方便了。如下圖:

而在系統的終端中直接執行 Python3,我們是得不到這麼好的輔助功能的。如下圖:

最簡單的深度學習示例
首先,我們看一個最簡單的深度學習示例,就是訓練一個能夠識別手寫數字的密集連線神經網路。在這裡,我們需要一個用於訓練和測試的資料集,而這個資料集就是 MNIST 資料集,該資料集包含 60000 張用於訓練的 28×28 畫素的手寫數字圖片,以及 10000 張用於訓練的 28×28 畫素的手寫數字圖片。Keras 能夠自動下載該資料集。訓練這個神經網路的程式碼如下:
from keras.datasets import mnist from keras import models from keras import layers from keras.utils import to_categorical (train_images, train_labels),(test_images, test_labels) = mnist.load_data() network = models.Sequential() network.add(layers.Dense(512, activation='relu', input_shape=(28*28,))) network.add(layers.Dense(10, activation='softmax')) network.compile(optimizer='rmsprop', loss='categorical_crossentropy', metrics=['accuracy']) 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 train_labels = to_categorical(train_labels) test_labels = to_categorical(test_labels) network.fit(train_images, train_labels, epochs=5, batch_size=128)
把以上這幾行程式碼逐行輸入到 PyCharm 的 Python 控制檯,就可以看到效果了。當輸入到 (train_images, train_labels),(test_images, test_labels) = mnist.load_data()
這一行時,Keras 就會自動下載 MNIST 資料集,可惜的是,由於下載地址被牆的原因,經常會出現下載失敗的情況。不過出現下載失敗也不用著急,用搜尋引擎找一下,很容易找到這個資料集的檔案: mnist.npz
檔案,大小才 11.5M,下載很快的。把下載的這個檔案放到 ~/.keras/datasets
目錄中即可。
以上所有的程式碼都輸入完成後,就開始了訓練,在這個例子中,訓練速度非常快,每個週期 4 秒多就完成了,總共 5 個週期。如下圖:

可以看到,這個神經網路達到了 98.9% 的精度。下面,我自己手寫一個數字測試一下。先開啟 Inkscape,自己隨便寫一個數字,如下圖:

儲存為 ~/test.png
。然後,用下面的程式碼把該圖片讀入記憶體,並更改大小為 28×28 畫素,最後轉化為灰度影象。這些操作都使用 PIL 完成。PIL 操作影象那是相當的方便。
from PIL import Image image = Image.open('/home/youxia/test.png').resize((28,28)).convert('L')
然後,將該影象轉化為 numpy 的陣列,並將其中的資料處理為 0 到 1 之間的浮點數。
import numpy as np im = np.array(image) im = 255 - im im = im.astype('float32') / 255.0
可以使用 matplotlib 檢視一下該影象,程式碼如下:
import matplotlib.pyplot as plt plt.imshow(im, cmap=plt.cm.binary)
這是我們處理好之後的影象是下面這個效果,和 MNIST 自帶的影象基本基本一致:

下面使用我們前面訓練的神經網路來識別該圖片,使用 predict 函式即可。識別時,需要將影象資料的 shape 更改為 (1,784):
network.predict(im.reshape(1,784))
返回的值是一個包含是個數字的列表,代表該圖片可能為數字 0-9 的概率,可以看到,其中第 6 項,也就是為數字 5 的概率最大,接近於 1:
array([[2.19245143e-11, 7.56166017e-13, 2.06190620e-10, 3.12406366e-04, 1.12510295e-13, 9.99686599e-01, 8.85503199e-11, 2.70172443e-11, 2.85677032e-07, 7.55779013e-07]], dtype=float32)
如果不想自己用眼睛去判斷哪個概率值最大,可以使用 numpy 的 argmax 函式,如下:
np.argmax(network.predict(im.reshape(1,784)))
返回結果為幾,就說明識別出的數字為幾,如下:
從密集連線神經網路到卷積神經網路
前面的例子使用的是密集連線神經網路,每一幅影象都轉化為一個以為向量進行處理。在對影象進行深度學習時,最常用的方法是二維卷積神經網路。卷積神經網路的優點一是學到的模式具有平移不變性,在影象某一個區域學習到的模式,如果模式出現在新位置,它仍然能夠識別;二是卷積神經網路可以學到模式的空間層次結構。
在 Keras 中,對卷積神經網路也提供了非常強大的支援。上一節的程式碼,只需要進行簡單的修改,就可以構建一個二維卷積神經網路,程式碼如下:
from keras import layers from keras import models from keras.datasets import mnist from keras.utils import to_categorical model = models.Sequential() model.add(layers.Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1))) model.add(layers.MaxPooling2D(2, 2)) model.add(layers.Conv2D(64, (3, 3), activation='relu')) model.add(layers.MaxPooling2D(2, 2)) model.add(layers.Conv2D(64, (3, 3), activation='relu')) model.add(layers.Flatten()) model.add(layers.Dense(64, activation='relu')) model.add(layers.Dense(10, activation='softmax')) model.compile(optimizer='rmsprop', loss='categorical_crossentropy', metrics=['accuracy']) (train_images, train_labels), (test_images, test_labels) = mnist.load_data() train_images = train_images.reshape((60000, 28, 28, 1)) train_images = train_images.astype('float32') / 255 test_images = test_images.reshape(10000, 28, 28, 1) test_images = test_images.astype('float32') / 255 train_labels = to_categorical(train_labels) test_labels = to_categorical(test_labels) model.fit(train_images, train_labels, epochs=5, batch_size=64)
主要的改變體現在以下幾個方面:一是使用 Conv2D 層、MaxPooling 層和 Flatten 層修改了深度學習框架的結構,二是修改了輸入陣列的形狀。除此之外,該深度學習框架使用的啟用函式、損失函式都和前面是一樣的。訓練該網路,發現它比前面的網路訓練起來要慢一些,但是達到了 99.3%的準確度。
使用如下程式碼進行驗證:
import numpy as np from PIL import Image im = np.array(Image.open('/home/youxia/test.png').resize((28,28)).convert('L')) im = 255 - im im = im.astype('float32') / 255.0 print(np.argmax(model.predict(im.reshape(1, 28, 28, 1))))
關於深度學習的理論和實戰
深度學習的理論相對來說比較難,所以我這篇隨筆裡面就沒有怎麼介紹。如果想全面瞭解深度學習的理論,可以閱讀這本“聖經”:

但是,光有理論而無實踐,這麼枯燥的知識是學不下去的。在實戰方面,我覺得這本書不錯:

我這裡的內容,就是參考了這本書。最後,再次對 Python 點贊,用 Python 寫科學計算的程式碼,真的是太舒服了。
求打賞
我對這次寫的這個系列要求是非常高的:首先內容要有意義、夠充實,資訊量要足夠豐富;其次是每一個知識點要講透徹,不能模稜兩可含糊不清;最後是包含豐富的截圖,讓那些不想裝 Linux 系統的朋友們也可以領略到 Linux 桌面的風采。如果我的努力得到大家的認可,可以掃下面的二維碼打賞一下:

版權申明
該隨筆由京山遊俠在2018年12月16日釋出於部落格園,引用請註明出處,轉載或出版請聯絡博主。QQ郵箱:[email protected]