1. 程式人生 > >Keras入門(一)搭建深度神經網絡(DNN)解決多分類問題

Keras入門(一)搭建深度神經網絡(DNN)解決多分類問題

-s pil return 進行 stat var das 部分 sof

Keras介紹

??Keras是一個開源的高層神經網絡API,由純Python編寫而成,其後端可以基於Tensorflow、Theano、MXNet以及CNTK。Keras 為支持快速實驗而生,能夠把你的idea迅速轉換為結果。Keras適用的Python版本是:Python 2.7-3.6。
??Keras,在希臘語中意為“角”(horn),於2015年3月份第一次發行,它可以在Windows, Linux, Mac等系統中運行。那麽,既然有了TensorFlow(或Theano、MXNet、CNTK),為什麽還需要Keras呢?這是因為,盡管我們可以用TensorFlow等來創建深度神經網絡系統,但Tensorflow等使用相對低級的抽象,直接編寫TensorFlow代碼具有一定的挑戰性,而Keras在TensorFlow的基礎上,增加了較易使用的抽象層,使用起來更加簡單、高效。
??什麽樣的場合適合用Keras呢?如果你有如下需求,請選擇Keras:

  • 簡易和快速的原型設計(keras具有高度模塊化,極簡,和可擴充特性)
  • 支持CNN和RNN,或二者的結合
  • 無縫CPU和GPU切換

??如果想用在你的電腦上使用Keras,需要以下工具:

  • Python
  • TensorFlow
  • Keras

在這裏,我們選擇TensorFlow作為Keras的後端工具。使用以下Python代碼,可以輸出Python、TensorFlow以及Keras的版本號:

import sys
import keras as K
import tensorflow as tf

py_ver = sys.version
k_ver = K.__version__
tf_ver = tf.__version__

print("Using Python version " + str(py_ver))
print("Using Keras version " + str(k_ver))
print("Using TensorFlow version " + str(tf_ver))

在筆者的電腦上,輸出的結果如下:

Using TensorFlow backend.
Using Python version 3.5.1 (v3.5.1:37a07cee5969, Dec  6 2015, 01:54:25) [MSC v.1900 64 bit (AMD64)]
Using Keras version 2.1.5
Using TensorFlow version 1.6.0

??下面,筆者將使用IRIS數據集(鳶尾花數據集,一個經典的機器學習數據集,適合作為多分類問題的測試數據),使用Keras搭建一個深度神經網絡(DNN),來解決IRIS數據集的多分類問題,作為Keras入門的第一個例子。

IRIS數據集介紹

??IRIS數據集(鳶尾花數據集),是一個經典的機器學習數據集,適合作為多分類問題的測試數據,它的下載地址為:http://archive.ics.uci.edu/ml/machine-learning-databases/iris/。
??IRIS數據集是用來給鳶尾花做分類的數據集,一共150個樣本,每個樣本包含了花萼長度(sepal length in cm)、花萼寬度(sepal width in cm)、花瓣長度(petal length in cm)、花瓣寬度(petal width in cm)四個特征,將鳶尾花分為三類,分別為Iris Setosa,Iris Versicolour,Iris Virginica,每一類都有50個樣本。
??IRIS數據集具體如下(只展示部分數據,順序已打亂):
技術分享圖片

讀取數據集

??筆者的IRIS數據集以csv格式儲存,筆者將使用Pandas來讀取IRIS數據集,並對目標變量進行0-1編碼(One-hot Encoding),最後將該數據集分為訓練集和測試集,比例為7:3。完整的Python代碼如下:

import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelBinarizer

# 讀取CSV數據集,並拆分為訓練集和測試集
# 該函數的傳入參數為CSV_FILE_PATH: csv文件路徑
def load_data(CSV_FILE_PATH):
    IRIS = pd.read_csv(CSV_FILE_PATH)
    target_var = ‘class‘  # 目標變量
    # 數據集的特征
    features = list(IRIS.columns)
    features.remove(target_var)
    # 目標變量的類別
    Class = IRIS[target_var].unique()
    # 目標變量的類別字典
    Class_dict = dict(zip(Class, range(len(Class))))
    # 增加一列target, 將目標變量進行編碼
    IRIS[‘target‘] = IRIS[target_var].apply(lambda x: Class_dict[x])
    # 對目標變量進行0-1編碼(One-hot Encoding)
    lb = LabelBinarizer()
    lb.fit(list(Class_dict.values()))
    transformed_labels = lb.transform(IRIS[‘target‘])
    y_bin_labels = []  # 對多分類進行0-1編碼的變量
    for i in range(transformed_labels.shape[1]):
        y_bin_labels.append(‘y‘ + str(i))
        IRIS[‘y‘ + str(i)] = transformed_labels[:, i]
    # 將數據集分為訓練集和測試集
    train_x, test_x, train_y, test_y = train_test_split(IRIS[features], IRIS[y_bin_labels],                                                         train_size=0.7, test_size=0.3, random_state=0)
    return train_x, test_x, train_y, test_y, Class_dict

搭建DNN

??接下來,筆者將展示如何利用Keras來搭建一個簡單的深度神經網絡(DNN)來解決這個多分類問題。我們要搭建的DNN的結構如下圖所示:

技術分享圖片

我們搭建的DNN由輸入層、隱藏層、輸出層和softmax層組成,其中輸入層由4個神經元組成,對應IRIS數據集中的4個特征,作為輸入向量,隱藏層有兩層,每層分別有5和6個神經元,之後就是輸出層,由3個神經元組成,對應IRIS數據集的目標變量的類別個數,最後,就是一個softmax層,用於解決多分類問題而創建。
??對應以上的DNN結構,用Keras來搭建的話,其Python代碼如下:

   import keras as K
    # 2. 定義模型
    init = K.initializers.glorot_uniform(seed=1)
    simple_adam = K.optimizers.Adam()
    model = K.models.Sequential()
    model.add(K.layers.Dense(units=5, input_dim=4, kernel_initializer=init, activation=‘relu‘))
    model.add(K.layers.Dense(units=6, kernel_initializer=init, activation=‘relu‘))
    model.add(K.layers.Dense(units=3, kernel_initializer=init, activation=‘softmax‘))
    model.compile(loss=‘categorical_crossentropy‘, optimizer=simple_adam, metrics=[‘accuracy‘])

在這個模型中,我們選擇的神經元激活函數為ReLU函數,損失函數為交叉熵(cross entropy),叠代的優化器(optimizer)選擇Adam,最初各個層的連接權重(weights)和偏重(biases)是隨機生成的。這樣我們就講這個DNN的模型定義完畢了。這麽簡單?Yes, that‘s it!

訓練及預測

??OK,定義完模型後,我們需要對模型進行訓練、評估及預測。對於模型訓練,我們每次訓練的批數為1,共叠代100次,代碼如下(接以上代碼):

    # 3. 訓練模型
    b_size = 1
    max_epochs = 100
    print("Starting training ")
    h = model.fit(train_x, train_y, batch_size=b_size, epochs=max_epochs, shuffle=True, verbose=1)
    print("Training finished \n")

??為了對模型有個評估,感知模型的表現,需要輸出該DNN模型的損失函數的值以及在測試集上的準確率,其Python代碼如下(接以上代碼):

    # 4. 評估模型
    eval = model.evaluate(test_x, test_y, verbose=0)
    print("Evaluation on test data: loss = %0.6f accuracy = %0.2f%% \n"           % (eval[0], eval[1] * 100) )

訓練100次,輸出的結果如下(中間部分的訓練展示已忽略):

Starting training 
Epoch 1/100

  1/105 [..............................] - ETA: 17s - loss: 0.3679 - acc: 1.0000
 42/105 [===========>..................] - ETA: 0s - loss: 1.8081 - acc: 0.3095 
 89/105 [========================>.....] - ETA: 0s - loss: 1.5068 - acc: 0.4270
105/105 [==============================] - 0s 3ms/step - loss: 1.4164 - acc: 0.4667
Epoch 2/100

  1/105 [..............................] - ETA: 0s - loss: 0.4766 - acc: 1.0000
 45/105 [===========>..................] - ETA: 0s - loss: 1.0813 - acc: 0.4889
 93/105 [=========================>....] - ETA: 0s - loss: 1.0335 - acc: 0.4839
105/105 [==============================] - 0s 1ms/step - loss: 1.0144 - acc: 0.4857

......

Epoch 99/100

  1/105 [..............................] - ETA: 0s - loss: 0.0013 - acc: 1.0000
 43/105 [===========>..................] - ETA: 0s - loss: 0.0447 - acc: 0.9767
 84/105 [=======================>......] - ETA: 0s - loss: 0.0824 - acc: 0.9524
105/105 [==============================] - 0s 1ms/step - loss: 0.0711 - acc: 0.9619
Epoch 100/100

  1/105 [..............................] - ETA: 0s - loss: 2.3032 - acc: 0.0000e+00
 51/105 [=============>................] - ETA: 0s - loss: 0.1122 - acc: 0.9608    
 99/105 [===========================>..] - ETA: 0s - loss: 0.0755 - acc: 0.9798
105/105 [==============================] - 0s 1ms/step - loss: 0.0756 - acc: 0.9810
Training finished 

Evaluation on test data: loss = 0.094882 accuracy = 97.78% 

可以看到,訓練完100次後,在測試集上的準確率已達到97.78%,效果相當好。
??最後是對新數據集進行預測,我們假設一朵鳶尾花的4個特征為6.1,3.1,5.1,1.1,我們想知道這個DNN模型會把它預測到哪一類,其Python代碼如下:

   import numpy as np
    # 5. 使用模型進行預測
    np.set_printoptions(precision=4)
    unknown = np.array([[6.1, 3.1, 5.1, 1.1]], dtype=np.float32)
    predicted = model.predict(unknown)
    print("Using model to predict species for features: ")
    print(unknown)
    print("\nPredicted softmax vector is: ")
    print(predicted)
    species_dict = {v:k for k,v in Class_dict.items()}
    print("\nPredicted species is: ")
    print(species_dict[np.argmax(predicted)])

輸出的結果如下:

Using model to predict species for features: 
[[ 6.1  3.1  5.1  1.1]]

Predicted softmax vector is: 
[[  2.0687e-07   9.7901e-01   2.0993e-02]]

Predicted species is: 
versicolor

如果我們仔細地比對IRIS數據集,就會發現,這個預測結果令人相當滿意,這個鳶尾花樣本的預測結果,以人類的眼光來看,也應當是versicolor。

總結

??到此為止,筆者就把這個演示例子給講完了,作為入門Keras的第一步,這個例子還是可以的。回顧該模型,首先我們利用Pandas讀取IRIS數據集,並分為訓練集和測試集,然後用Keras搭建了一個簡單的DNN模型,並對該模型進行訓練及評估,最後看一下該模型在新數據集上的預測能力。從中,讀者不難體會到Keras的優越性,因為,相比TensorFlow,搭建同樣的DNN模型及模型訓練、評估、預測,其Python代碼無疑會比Keras來得長。
??最後,附上該DNN模型的完整Python代碼:

# iris_keras_dnn.py
# Python 3.5.1, TensorFlow 1.6.0, Keras 2.1.5
# ========================================================
# 導入模塊
import os
import numpy as np
import keras as K
import tensorflow as tf
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelBinarizer
os.environ[‘TF_CPP_MIN_LOG_LEVEL‘]=‘2‘

# 讀取CSV數據集,並拆分為訓練集和測試集
# 該函數的傳入參數為CSV_FILE_PATH: csv文件路徑
def load_data(CSV_FILE_PATH):
    IRIS = pd.read_csv(CSV_FILE_PATH)
    target_var = ‘class‘  # 目標變量
    # 數據集的特征
    features = list(IRIS.columns)
    features.remove(target_var)
    # 目標變量的類別
    Class = IRIS[target_var].unique()
    # 目標變量的類別字典
    Class_dict = dict(zip(Class, range(len(Class))))
    # 增加一列target, 將目標變量進行編碼
    IRIS[‘target‘] = IRIS[target_var].apply(lambda x: Class_dict[x])
    # 對目標變量進行0-1編碼(One-hot Encoding)
    lb = LabelBinarizer()
    lb.fit(list(Class_dict.values()))
    transformed_labels = lb.transform(IRIS[‘target‘])
    y_bin_labels = []  # 對多分類進行0-1編碼的變量
    for i in range(transformed_labels.shape[1]):
        y_bin_labels.append(‘y‘ + str(i))
        IRIS[‘y‘ + str(i)] = transformed_labels[:, i]
    # 將數據集分為訓練集和測試集
    train_x, test_x, train_y, test_y = train_test_split(IRIS[features], IRIS[y_bin_labels],                                                         train_size=0.7, test_size=0.3, random_state=0)
    return train_x, test_x, train_y, test_y, Class_dict

def main():

    # 0. 開始
    print("\nIris dataset using Keras/TensorFlow ")
    np.random.seed(4)
    tf.set_random_seed(13)

    # 1. 讀取CSV數據集
    print("Loading Iris data into memory")
    CSV_FILE_PATH = ‘E://iris.csv‘
    train_x, test_x, train_y, test_y, Class_dict = load_data(CSV_FILE_PATH)

    # 2. 定義模型
    init = K.initializers.glorot_uniform(seed=1)
    simple_adam = K.optimizers.Adam()
    model = K.models.Sequential()
    model.add(K.layers.Dense(units=5, input_dim=4, kernel_initializer=init, activation=‘relu‘))
    model.add(K.layers.Dense(units=6, kernel_initializer=init, activation=‘relu‘))
    model.add(K.layers.Dense(units=3, kernel_initializer=init, activation=‘softmax‘))
    model.compile(loss=‘categorical_crossentropy‘, optimizer=simple_adam, metrics=[‘accuracy‘])

    # 3. 訓練模型
    b_size = 1
    max_epochs = 100
    print("Starting training ")
    h = model.fit(train_x, train_y, batch_size=b_size, epochs=max_epochs, shuffle=True, verbose=1)
    print("Training finished \n")

    # 4. 評估模型
    eval = model.evaluate(test_x, test_y, verbose=0)
    print("Evaluation on test data: loss = %0.6f accuracy = %0.2f%% \n"           % (eval[0], eval[1] * 100) )

    # 5. 使用模型進行預測
    np.set_printoptions(precision=4)
    unknown = np.array([[6.1, 3.1, 5.1, 1.1]], dtype=np.float32)
    predicted = model.predict(unknown)
    print("Using model to predict species for features: ")
    print(unknown)
    print("\nPredicted softmax vector is: ")
    print(predicted)
    species_dict = {v:k for k,v in Class_dict.items()}
    print("\nPredicted species is: ")
    print(species_dict[np.argmax(predicted)])

main()

參考文獻

  1. Keras中文文檔: https://keras-cn.readthedocs.io/en/latest/
  2. Keras Succinctly: http://ebooks.syncfusion.com/downloads/keras-succinctly/keras-succinctly.pdf?AWSAccessKeyId=AKIAJ5W3G2Z6F2ZHAREQ&Expires=1539315050&Signature=r6qJ%2BP7KUEU442WMObSLd2%2Flkqw%3D
  3. IRIS數據集: http://archive.ics.uci.edu/ml/machine-learning-databases/iris/

Keras入門(一)搭建深度神經網絡(DNN)解決多分類問題