人工智能深度學習入門練習之(26)TensorFlow – 例子:人工神經網絡(ANN)


人工神經網絡(ANN)介紹

生物神經元

人腦有數十億個神經元。神經元是人腦中相互連接的神經細胞,參與處理和傳遞化學信號和電信號。

生物神經元

以下是生物神經元的重要組成部分:

  • 樹突 – 從其他神經元接收信息的分支
  • 細胞核 – 處理從樹突接收到的信息
  • 軸突 – 一種被神經元用來傳遞信息的生物電纜
  • 突觸 – 軸突和其他神經元樹突之間的連接

人腦神經元處理信息的過程:多個信號到達樹突,然后整合到細胞體中,如果積累的信號超過某個閾值,就會產生一個輸出信號,由軸突傳遞。

人工神經元

人工神經元是一個基於生物神經元的數學模型,神經元接受多個輸入信息,對它們進行加權求和,再經過一個激活函數處理,然后將這個結果輸出。

人工神經元

生物神經元對照人工神經元

生物神經元

人工神經元

細胞核

節點 (加權求和 + 激活函數)

樹突

輸入

軸突

帶權重的連接

突觸

輸出

人工神經網絡

人工神經網絡,模仿哺乳動物大腦皮層的神經系統,但規模要小得多。它由許多簡單的處理單元(神經元)互聯組成,這些處理單元(神經元)的作用類似於生物神經元,接受信息輸入,處理后向下一層輸出信息。

人工神經網絡由多層神經元組成。層與層之間的神經元有連接,而層內之間的神經元沒有連接。最左邊的層叫做輸入層,這層負責接收輸入數據;最右邊的層叫輸出層,我們可以從這層獲取神經網絡輸出數據。輸入層和輸出層之間的層叫做隱藏層。

人工神經網絡2

人工神經網絡的訓練

給神經網絡輸入一批樣本數據,神經網絡會產生輸出。比較神經網絡的輸出與樣本中的正確結果,根據兩者的差值,對神經網絡的權重進行調整,使差值變小。重復這個過程,直到神經網絡產生正確輸出,從而確定神經網絡的權重值完成訓練。

訓練好的神經網絡就可以用來處理數據,給神經網絡輸入數據,給出正確的輸出。

所以,所謂神經網絡的訓練過程,實際上就是確定神經元之間輸入權重的過程。

圖

如上圖所示,具體訓練過程如下:

  1. 給神經網絡輸入一批樣本數據,經過神經網絡傳輸到輸出層,這一步被稱為前向傳播。
  2. 計算損失函數的值,損失函數的值表示預測結果(Prediction Y)和已知結果(True label Y)之間的差值。
  3. 使用優化器(Optimizer,通常使用梯度下降算法與反向傳播算法),調整權重值,使差值變小。

重復以上3個步驟訓練權重,直到損失函數的值(差值)最小,確定最終的權重值,完成訓練。

注意: 關於人工神經網絡的詳細內容,可參考我們的深度學習教程

TensorFlow 人工神經網絡例子

TensorFlow中,Estimator是一種可極大地簡化機器學習編程的高階API。Estimator 會封裝下列操作:

  • 訓練
  • 評估
  • 預測
  • 導出以供使用

開發人員可以使用TensorFlow預創建的 Estimator,也可以編寫自定義 Estimator。所有 Estimator(無論是預創建的還是自定義)都是基於 tf.estimator.Estimator 類的類。

這一部分,我們將學習使用TensorFlow的高階APIEstimator中的DNNClassifier訓練神經網絡,DNNClassifier是一個神經網絡分類器的實現。訓練數據集我們將采用MNIST數據集。

MNIST(Modified National Institute of Standards and Technology database)是一個手寫數字的大型數據庫,通常作為各種圖像識別系統的訓練數據集,該數據集包含了從0到9的手寫數字的28×28像素圖像的集合,現在已經成為英語數字訓練的標准數據集。

MNIST手寫數字

該神經網絡訓練好后,功能是能夠識別手寫數字。

用TensorFlow訓練神經網絡並不復雜,我們將按以下步驟進行:

  1. 導入數據
  2. 轉換數據
  3. 構造張量
  4. 構建模型
  5. 訓練和評估模型
  6. 改進模型

1. 導入數據

首先需要導入必要的庫,除了TensorFlow,我們將使用:

  • numpy 計算、處理多維數組的python包
  • sklearn 機器學習相關的包,包含許多有用的函數

sklearn可用於導入MNIST數據集,預處理數據等。

import numpy as np
import tensorflow as tf

openml.org是一個分享機器學習數據和實驗的公共存儲庫,每個人都可在上面分享、下載數據集。sklearn.datasets包中的fetch_openml函數可以從openml存儲庫下載數據集。我們將使用該函數從openml.org下載MNIST數據集,下載會花幾分鍾時間。

MNIST數據集中包含了樣本特征集mnist.data及樣本標簽mnist.target

# 導入sklearn庫中fetch_openml函數,下載MNIST數據集
from sklearn.datasets import fetch_openml
mnist = fetch_openml('mnist_784')
print(mnist.keys())
print(mnist.data.shape)
print(mnist.target.shape)

使用train_test_split函數將數據集隨機划分為訓練子集和測試子集,並返回划分好的訓練集測試集樣本和訓練集測試集標簽。

from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(mnist.data, mnist.target, test_size=0.2, random_state=42)
y_train  = y_train.astype(int)
y_test  = y_test.astype(int)
batch_size = len(X_train)

# 查看訓練樣本子集、訓練樣本標簽子集、測試樣本子集、測試樣本標簽子集的形狀
print(X_train.shape, y_train.shape, X_test.shape, y_test.shape)

train_test_split函數的參數解釋:

  • train_data:被划分的樣本特征集
  • train_target:被划分的樣本標簽
  • test_size:如果是浮點數,在0-1之間,表示測試子集占比;如果是整數的話就是測試子集的樣本數量
  • random_state:是隨機數的種子

隨機數種子

隨機數的產生取決於種子,隨機數和種子之間的關系遵從以下兩個規則:
種子不同,產生不同的隨機數;種子相同,即使實例不同也產生相同的隨機數。

隨機數種子,其實就是該組隨機數的編號,在需要重復試驗的時候,種子相同可以保證得到一組一樣的隨機數。比如你每次都填1,其他參數一樣的情況下,得到的隨機數組是一樣的,但填0或不填,則每次都會不一樣。

2. 數據預處理

在進行訓練之前,需要對數據集作歸一化處理,可以提高模型收斂速度和模型精度。我們將使用最小最大值標准化方法,該方法的公式是:

(X-min_x)/(max_x - min_x)

sklearn庫中已經為此提供了一個函數: MinMaxScaler()

## 導入MinMaxScaler
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
# 訓練樣本子集
X_train_scaled = scaler.fit_transform(X_train.astype(np.float64))
# 測試樣本子集
X_test_scaled = scaler.fit_transform(X_test.astype(np.float64))

3. 構造張量

構造輸入特征列張量。TensorFlow中的特征列可以視為原始數據和 Estimator 之間的媒介。特征列功能強大,可以將各種原始數據轉換為 Estimator 可以使用的格式。

feature_columns = [tf.feature_column.numeric_column('x', shape = X_train_scaled.shape[1:])]

4. 構建模型

該神經網絡結構包含兩個隱藏層,第一層為300個神經元,第二層為100個神經元。這些值都是經驗值,你可以嘗試調整這些值,看看它如何影響網絡的准確性。

要構建模型,可以使用estimator.DNNClassifier

estimator = tf.estimator.DNNClassifier(
    feature_columns=feature_columns,
    hidden_units=[300, 100], 
    n_classes=10, 
    model_dir = './train/DNN')

參數

  • feature_columns: 定義要在網絡中使用的特征列
  • hidden_units: 定義隱藏層的神經元數量
  • n_classes: 定義要預測的分類數量,這里是0~9,是10個類
  • model_dir: 定義TensorBoard的路徑

5. 訓練和評估模型

可以使用numpy方法來訓練和評估模型。

# 訓練模型
train_input = tf.estimator.inputs.numpy_input_fn(
    x={"x": X_train_scaled},
    y=y_train,
    batch_size=50,
    shuffle=False,
    num_epochs=None)

estimator.train(input_fn = train_input,steps=1000) 

# 評估模型
eval_input = tf.estimator.inputs.numpy_input_fn(
    x={"x": X_test_scaled},
    y=y_test, 
    shuffle=False,
    batch_size=X_test_scaled.shape[0],
    num_epochs=1)

result = estimator.evaluate(eval_input, steps=None) 
print(result)

輸出

{'accuracy': 0.9720714, 'average_loss': 0.09608318, 'loss': 1345.1646, 'global_step': 4000}

可以看到,現在模型的准確率為97%。

6. 改進模型

為減少過擬合,添加正則化參數來改進模型。我們設置dropout率為0.3,使用Adam Grad優化器:tf.train.ProximalAdagradOptimizer, 設置以下參數:

  • 學習速率: learning_rate
  • L1正則化: l1_regularization_strength
  • L2正則化: l2_regularization_strength
estimator_imp = tf.estimator.DNNClassifier(
    feature_columns = feature_columns,
    hidden_units = [300, 100],
    dropout = 0.3, 
    n_classes = 10,
    optimizer=tf.train.ProximalAdagradOptimizer(
      learning_rate=0.01,
      l1_regularization_strength=0.01, 
      l2_regularization_strength=0.01
    ),
    model_dir = './train/DNN1')

estimator_imp.train(input_fn = train_input, steps=1000) 

result = estimator_imp.evaluate(eval_input, steps=None) 
print(result)

輸出

{'accuracy': 0.94292855, 'average_loss': 0.2078176, 'loss': 2909.4463, 'global_step': 1000}

完整代碼:

import tensorflow.compat.v1 as tf
import numpy as np
tf.compat.v1.disable_eager_execution()
# 導入sklearn庫中fetch_openml函數,下載MNIST數據集
from sklearn.datasets import fetch_openml
mnist = fetch_openml('mnist_784')
print(mnist.keys())
print(mnist.data.shape)
print(mnist.target.shape)
from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(mnist.data, mnist.target, test_size=0.2, random_state=42)
y_train  = y_train.astype(int)
y_test  = y_test.astype(int)
batch_size = len(X_train)

# 查看訓練樣本子集、訓練樣本標簽子集、測試樣本子集、測試樣本標簽子集的形狀
print(X_train.shape, y_train.shape, X_test.shape, y_test.shape)
from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(mnist.data, mnist.target, test_size=0.2, random_state=42)
y_train  = y_train.astype(int)
y_test  = y_test.astype(int)
batch_size = len(X_train)

# 查看訓練樣本子集、訓練樣本標簽子集、測試樣本子集、測試樣本標簽子集的形狀
print(X_train.shape, y_train.shape, X_test.shape, y_test.shape)
## 導入MinMaxScaler
from sklearn.preprocessing import MinMaxScaler
scaler = MinMaxScaler()
# 訓練樣本子集
X_train_scaled = scaler.fit_transform(X_train.astype(np.float64))
# 測試樣本子集
X_test_scaled = scaler.fit_transform(X_test.astype(np.float64))
feature_columns = [tf.feature_column.numeric_column('x', shape = X_train_scaled.shape[1:])]
estimator = tf.estimator.DNNClassifier(
    feature_columns=feature_columns,
    hidden_units=[300, 100],
    n_classes=10,
    model_dir = './train/DNN')
# 訓練模型
train_input = tf.estimator.inputs.numpy_input_fn(
    x={"x": X_train_scaled},
    y=y_train,
    batch_size=50,
    shuffle=False,
    num_epochs=None)

estimator.train(input_fn = train_input,steps=1000)

# 評估模型
eval_input = tf.estimator.inputs.numpy_input_fn(
    x={"x": X_test_scaled},
    y=y_test,
    shuffle=False,
    batch_size=X_test_scaled.shape[0],
    num_epochs=1)

result = estimator.evaluate(eval_input, steps=None)
print(result)
estimator_imp = tf.estimator.DNNClassifier(
    feature_columns = feature_columns,
    hidden_units = [300, 100],
    dropout = 0.3,
    n_classes = 10,
    optimizer=tf.train.ProximalAdagradOptimizer(
      learning_rate=0.01,
      l1_regularization_strength=0.01,
      l2_regularization_strength=0.01
    ),
    model_dir = './train/DNN1')

estimator_imp.train(input_fn = train_input, steps=1000)

result = estimator_imp.evaluate(eval_input, steps=None)
print(result)

執行結果:

{'accuracy': 0.94292855, 'average_loss': 0.2078176, 'loss': 2909.4463, 'global_step': 1000}

減少過擬合的參數設置,並沒有提高模型的精度,第一個模型的准確率為97%,而L2正則化模型的准確率為94%。你可以嘗試使用不同的值,看看它如何影響准確度。

小結

本篇教程中,我們學習了如何構建一個神經網絡。神經網絡需要:

  • 隱藏層的數量
  • 每個隱藏層內神經元的數量
  • 激活函數
  • 優化器
  • 輸出的分類數量

在TensorFlow中,你可以使用tf.estimator.DNNClassifier訓練一個神經網絡來解決分類問題,需要設置的參數如下:

  • feature_columns=feature_columns,
  • hidden_units=[300, 100]
  • n_classes=10
  • model_dir

可以使用不同的優化器來改進模型。我們學習了如何使用Adam Grad優化器和學習率,並設置了防止過度擬合的控制參數。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM