Keras學習筆記:Chapter1-Keras入門
Keras
Keras是一個高層神經網路庫。Keras是由Python編寫而成的,後端實現是基於Tensorflow,CNTK或Theano(Keras是一個庫,可以理解為一個基於多種不同機器學習庫提供相同api的庫)。
Keras發展的要義是:將想法快速轉換實驗成果,(類似Python的理念:人生苦短,我用Python),正因為這樣,Keras很適合做研究使用。
如果你對深度學習庫有以下要求:
- 能夠快速的、簡便的實現idea
- 支援CNN和RNN
- 在CPU和GPU上快速切換
那麼Keras會是一個非常好的選擇~
安裝Keras
Keras依賴
在安裝Keras之前,需要安裝一個Keras需要的任意一個後端引擎
- TensorFlow
- CNTK
- Theano
還有一些可選的依賴:
- cuDNN (使用GPU加速Keras執行)
- HDF5 and h5py (用於儲存Keras模型)
- graphviz and pydot (繪製模型圖)
我個人覺得安裝Anaconda+TensorFlow+Keras這一套,省心省力~
安裝Keras庫本身
安裝Keras有兩種方法:
使用PyPI安裝(推薦)
sudo pip install keras
也可以使用原始碼安裝
First: 從github上將Keras原始碼clone下來
git clone https://github.com/fchollet/keras.git
Then: 進入Keras目錄,並執行安裝程式
cd keras sudo python setup.py install
檢視是否安裝和Keras的後端設定
開啟終端
>>>python # 進入python環境
>>>import keras # 匯入keras
Using TensorFlow backend.
>>>keras.__version__ # 檢視當前Keras版本
'2.0.8'
如何切換後端為CNTK或Theano
Keras預設使用TensorFlow作為後端實現張量計算,如果你想切換Keras的後端為CNTK或Theano,參考Keras backends。
(現在Theano已經停止更新了,建議還是用TensorFlow吧)
一些基本概念
在學習Keras之前,需要有一些關於Keras、深度學習的基本概念。
張量
通常,在機器學習系統中使用張量
(tensors)作為資料的基本結構,張量是這個領域的基礎概念,那麼tensor是啥?
張量是包含資料的容器,可以看做數字、向量、矩陣的擴充套件,它們都是張量的特殊表現。
0維的張量就是數字,即
標量
(0D tensors:Scale
)>>> import numpy as np >>> x = np.array(12) >>> x array(12) >>> x.ndim 0
只包含一個數字的張量稱之為標量,在numpy中可通過
ndim
屬性訪問張量的維度1維的張量就是一組資料,即
向量
(1D tensors:Vectors
)>>> x = np.array([12, 3, 6, 14]) >>> x array([12, 3, 6, 14]) >>> x.ndim 1
2維的張量就是一組向量,即
矩陣
(2D tensors:Matrices
)>>> x = np.array([[5, 78, 2, 34, 0], [6, 79, 3, 35, 1], [7, 80, 4, 36, 2]]) >>> x.ndim 2
3維(例如一張彩色圖片)及更多維度的張量
>>> x = np.array([[[5, 78, 2, 34, 0], [6, 79, 3, 35, 1], [7, 80, 4, 36, 2]], [[5, 78, 2, 34, 0], [6, 79, 3, 35, 1], [7, 80, 4, 36, 2]], [[5, 78, 2, 34, 0], [6, 79, 3, 35, 1], [7, 80, 4, 36, 2]]]) >>> x.ndim 3
在張量的表述上,一般把維度(dimension)稱為軸
(axis)。在深度學習中,一般使用的是從0D到4D的張量,在處理video data時可能會用到5D的張量
下圖是4D張量的表示:
多張圖片組成的4D張量,分別為長、寬、通道數、樣本數。一般的我們在訓練CNN模型時,定義的輸入張量就是這樣的形式。
張量的屬性
一個張量有3個關鍵屬性:
- 張量的
axes
(階數)。 張量的
shape
。shape描述的張量每個axis的維度。例如上面舉例的3D張量的shape為(3,3,5);2D的張量shape為(2,5);1D的張量shape為(4,);0D的張量shape為()。張量的資料型別(
data type
)。在numpy中dtype表示。
函式式模型
在原本的Keras版本中,模型其實有兩種:
一種叫Sequential,稱為序貫模型,也就是單輸入單輸出,一條路通到底,層與層之間只有相鄰關係,跨層連線統統沒有。這種模型編譯速度快,操作上也比較簡單。
第二種模型稱為Graph,即圖模型(大部分機器學習庫都是基於這個模型),這個模型支援多輸入多輸出,層與層之間想怎麼連怎麼連,但是編譯速度慢。
可以看到,Sequential其實是Graph的一個特殊情況。新版Keras中,圖模型被移除,而增加了functional model API
,這更加強調了Sequential是特殊情況。一般的模型就稱為Model,如果你要用簡單的Sequential,還有一個快捷方式Sequential。
functional model API
將其譯為泛型模型,即只要是接收一個或一些張量作為輸入,然後輸出的也是一個或一些張量,統統都稱作“model”。
Pyhon和深度學習基礎
- Keras使用的是Python語言,所以應該對Python有一定得了解。
- Keras是一個深度學習庫,所以基本的深度學習基礎是要有的。
- 模型:監督學習、無監督學習、分類、迴歸等
- 損失函式、啟用函式、過擬合、欠擬合等
- BP演算法、梯度下降法、SGD、batch、epoch等
- 訓練集、校驗集、測試集等
開發環境
我的開發環境:
- Ubuntu16.04(強烈建議在linux上開發)
- TensorFlow 1.3-GPU(我的後端是tensorflow)
- i7-7700k+GTX1080(沒有顯示卡也能搞,就是速度慢點)
在MNIST上構建一個簡單的神經網路
MNIST資料集
Keras內建操作MNIST資料集的函式MNIST資料集介紹。可通過下面格式載入:
>>>from keras.datasets import mnist
>>>(train_images, train_labels), (test_images, test_labels) = mnist.load_data() # 下載完MNIST資料集並載入
# ... 下載
>>>train_images.shape # 看一下訓練集
(60000, 28, 28)
>>>len(train_labels)
60000
>>>test_images.shape # 看一下測試集
(10000, 28, 28)
>>>len(test_labels)
10000
在使用之前,我們對資料做reshape
以便於後面直接塞給model,同時對資料做歸一化處理。原本我們的訓練圖片shape為(60000, 28, 28);dtype為uint8;值為[0, 255]之間。我們將其轉化為dtype為float32; shape為(60000, 28 * 28);值為[0, 1].
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
同樣的,我們也需要對labels做編碼,用如下程式碼:
from keras.utils import to_categorical
train_labels = to_categorical(train_labels)
test_labels = to_categorical(test_labels)
這樣我們算是準備好了資料集了~
構建網路模型
神經網路的核心組成模型是層
,層
就是資料處理模組,也稱之為過濾器
(filter)。一般的有輸入層、隱藏層、輸出層。
from keras import models
from keras import layers
network = models.Sequential()
network.add(layers.Dense(512, activation='relu', input_shape=(28 * 28,)))
network.add(layers.Dense(10, activation='softmax'))
這裡我們構建的模型由兩個Dense
層組成,Dense
層就是densely-connected (也稱之為”fully-connected”,即FC)層。(我就在琢磨17年的整出來了DenseNet,Keras該怎麼起名字)。第二層是softmax層,輸出是一個10維向量,對應的就是數字0-9的可能性。(總和為1)。
為了能夠訓練模型,我們還需要做以下三步:
- 新增
損失函式
(loss function):評估模型在訓練集上訓練的好壞程度,為模型修正提供了正確方向。 優化器
(optimizer):模型優化自身引數的方法- 訓練和測試之間的度量標準。
network.compile(optimizer='rmsprop',
loss='categorical_crossentropy',
metrics=['accuracy'])
訓練模型並評估
在構建好的模型上,開始訓練:
>>>network.fit(train_images, train_labels, epochs=5, batch_size=128)
Epoch 1/5
60000/60000 [==============================] - 2s - loss: 0.2577 - acc: 0.9245
Epoch 2/5
60000/60000 [==============================] - 1s - loss: 0.1042 - acc: 0.9690
Epoch 3/5
60000/60000 [==============================] - 1s - loss: 0.0687 - acc: 0.9793
Epoch 4/5
60000/60000 [==============================] - 1s - loss: 0.0508 - acc: 0.9848
Epoch 5/5
60000/60000 [==============================] - 1s - loss: 0.0382 - acc: 0.9890
可以看到,這裡列印的log裡主要有2個指標,’loss’表示network和訓練集之間的loss,’acc’即表示network和訓練集之間accuracy。可以看到,在訓練集上acc很快達到了98.9%, 下面看看模型在測試集上的表現:
>>>test_loss, test_acc = network.evaluate(test_images, test_labels)
9536/10000 [===========================>..] - ETA: 0s
>>>print('test_acc:', test_acc)
test_acc: 0.9777
可以看到在測試集上達到了97.7%,也還算不錯。到此為止,我們搭建了一個簡易的神經網路模型用於手寫數字的識別,後面還將詳細的講解本小節用到的函式。
參考資料
Keras中文文件 SCP-173
《Deep Learning with Python》 Francois Chollet