1. 神經(jīng)網(wǎng)絡
神經(jīng)網(wǎng)絡是學者通過對生物神經(jīng)元的研究,提出了模擬生物神經(jīng)元機制的人工神經(jīng)網(wǎng)絡的數(shù)學模型,生物神經(jīng)元的模型抽象為如圖所示的數(shù)學結構。
神經(jīng)元輸入向量?? = [??1, ????2, ??3, … , ????]T,經(jīng)過函數(shù)映射:??: ?? → ??后得到輸出??。
考慮一種簡化的情況,即線性變換:??(??) = ??1??1 + ??2??2 + ??3??3 + ? + ???????? + b。
參數(shù)?? = {??1, ??2, ??3, . . . , ????, ??}確定了神經(jīng)元的狀態(tài),通過固定??參數(shù)即可確定此神經(jīng)元的處理邏輯。當神經(jīng)元輸入節(jié)點數(shù)?? = 1(單輸入)時,神經(jīng)元數(shù)學模型可進一步簡化為:?? = ???? + ??。
2. 線性回歸
在這里,我們通過一個線性回歸的例子了解神經(jīng)網(wǎng)絡的基本思想。
線性回歸問題簡單來說就是找到一條曲線使得該曲線到圖中各點的距離之和最短,即求出當前模型的所有采樣點上的預測值????(??) + ??與真實值??(??)之間的差的平方和作為總誤差?的值最小的??和??。
而每次尋找最優(yōu)值??和??的過程就是訓練的過程,其中尋找最優(yōu)值的方法叫做優(yōu)化方法,常用優(yōu)化方法是梯度下降法。也就是在每次訓練時讓參數(shù)??和??按照下列式子進行更新,直到找到最優(yōu)解,最終結果如下圖。
其中η是學習率。
3. 激活函數(shù)
以上的例子是線性的,但是實際中有很多問題是非線性的。針對于非線性問題,可以在線性模型的基礎上嵌套非線性函數(shù),就是激活函數(shù)。
這里的??代表了某個具體的非線性激活函數(shù)。
3.1 Sigmoid函數(shù)
它的一個優(yōu)良特性就是能夠把?? ∈ ??的輸入“壓縮”到?? ∈ (0,1)區(qū)間,這個區(qū)間的數(shù)值在深度學習常用來表示以下意義:
(1) 概率分布 (0,1)區(qū)間的輸出和概率的分布范圍[0,1]契合,可以通過 Sigmoid 函數(shù)將輸出轉譯為概率輸出。
(2) 信號強度 一般可以將 0~1 理解為某種信號的強度,如像素的顏色強度,1 代表當前通道顏色最強,0 代表當前通道無顏色;抑或代表門控值(Gate)的強度,1 代表當前門控全部開放,0 代表門控關閉。
3.2 Relu函數(shù)
在 ReLU激活函數(shù)提出之前,Sigmoid 函數(shù)通常是神經(jīng)網(wǎng)絡的激活函數(shù)首選。但是 Sigmoid 函數(shù)在輸入值較大或較小時容易出現(xiàn)梯度值接近于 0 的現(xiàn)象,稱為梯度彌散現(xiàn)象。出現(xiàn)梯度彌散現(xiàn)象時,網(wǎng)絡參數(shù)長時間得不到更新,導致訓練不收斂或停滯不動的現(xiàn)象發(fā)生,較深層次的網(wǎng)絡模型中更容易出現(xiàn)梯度彌散現(xiàn)象。因此為了解決梯度彌散問題,提出了Relu激活函數(shù)。
可以看到,ReLU 對小于 0 的值全部抑制為 0;對于正數(shù)則直接輸出。
3.3 Softmax函數(shù)
Softmax 函數(shù)不僅可以將輸出值映射到[0,1]區(qū)間,還滿足所有的輸出值之和為 1 的特性。
如圖的例子,輸出層的輸出為[2.0,1.0,0.1],經(jīng)過 Softmax 函數(shù)計算后,得到輸出為[0.7,0.2,0.1],每個值代表了當前樣本屬于每個類別的概率,概率值之和為 1。通過 Softmax函數(shù)可以將輸出層的輸出轉譯為類別概率,在分類問題中使用的非常頻繁。
4. ANN(全連接網(wǎng)絡)模型結構
由每個輸出節(jié)點與全部的輸入節(jié)點相連接,這種網(wǎng)絡層稱為全連接層。
通過層層堆疊上圖中的全連接層,保證前一層的輸出節(jié)點數(shù)與當前層的輸入節(jié)點數(shù)匹配,即可堆疊出任意層數(shù)的網(wǎng)絡。我們把這種由神經(jīng)元相互連接而成的網(wǎng)絡叫做神經(jīng)網(wǎng)絡。如下圖所示,通過堆疊 4 個全連接層,可以獲得層數(shù)為 4 的神經(jīng)網(wǎng)絡,由于每層均為全連接層,稱為全連接網(wǎng)絡。其中第 1~3 個全連接層在網(wǎng)絡中間,稱之為隱藏層 1、2、3,最后一個全連接層的輸出作為網(wǎng)絡的輸出,稱為輸出層。隱藏層 1、2、3 的輸出節(jié)點數(shù)分別為[256,128,64],輸出層的輸出節(jié)點數(shù)為 10。
在設計全連接網(wǎng)絡時,網(wǎng)絡的結構配置等超參數(shù)可以按著經(jīng)驗法則自由設置。
5. 誤差函數(shù)
在搭建完模型結構后,下一步就是選擇合適的誤差函數(shù)來計算誤差。常見的誤差函數(shù)有均方差、交叉熵、KL 散度、Hinge Loss 函數(shù)等,其中均方差函數(shù)和交叉熵函數(shù)在深度學習中比較常見,均方差函數(shù)主要用于回歸問題,交叉熵函數(shù)主要用于分類問題。
5.1 均方差誤差函數(shù)
均方差(Mean Squared Error,簡稱 MSE)誤差函數(shù)通過計算這兩個點之間的歐式距離的平方來衡量兩個向量之間的差距。
MSE 誤差函數(shù)的值總是大于等于 0,當 MSE 函數(shù)達到最小值 0 時,輸出等于真實標簽,此時神經(jīng)網(wǎng)絡的參數(shù)達到最優(yōu)狀態(tài)。均方差誤差函數(shù)廣泛應用在回歸問題中,實際上,分類問題中也可以應用均方差誤差函數(shù)。
5.2 交叉熵誤差函數(shù)
交叉熵誤差函數(shù)常用于分類問題中。
6. 手寫數(shù)字識別實戰(zhàn)
6.1 工具說明
該代碼是基于TensorFlow框架書寫,需要下載相關庫。
6.2 導入相關庫
以下第三方庫是python專門用于深度學習的庫
# 導入tensorflow
import tensorflow as tf
# 導入keras
from tensorflow import keras
# 引入內置手寫體數(shù)據(jù)集mnist
from keras.datasets import mnist
# 引入繪制acc和loss曲線的庫
import matplotlib.pyplot as plt
# 引入ANN的必要的類
from keras.layers import Dense
from keras.models import Sequential
from keras import optimizers, losses
6.3 加載數(shù)據(jù)
把MNIST數(shù)據(jù)集進行加載
"1.加載數(shù)據(jù)"
"""
x_train是mnist訓練集圖片,大小的28*28的,y_train是對應的標簽是數(shù)字
x_test是mnist測試集圖片,大小的28*28的,y_test是對應的標簽是數(shù)字
"""
(x_train, y_train), (x_test, y_test) = mnist.load_data() # 加載mnist數(shù)據(jù)集
print('mnist_data:', x_train.shape, y_train.shape, x_test.shape, y_test.shape) # 打印訓練數(shù)據(jù)和測試數(shù)據(jù)的形狀
6.4 數(shù)據(jù)預處理
(1) 將輸入的圖片進行歸一化,從0-255變換到0-1;
(2) 將輸入圖片的形狀(60000,28,28)轉換成(60000,28*28),相當于將圖片拉直,便于輸入給神經(jīng)網(wǎng)絡;
(3) 將標簽y進行獨熱編碼,因為神經(jīng)網(wǎng)絡的輸出是10個概率值,而y是1個數(shù), 計算loss時無法對應計算,因此將y進行獨立編碼成為10個數(shù)的行向量,然后進行l(wèi)oss的計算 獨熱編碼:例如數(shù)值1的10分類的獨熱編碼是[0 1 0 0 0 0 0 0 0 0,即1的位置為1,其余位置為0。
"2.數(shù)據(jù)預處理"
def preprocess(x, y): # 數(shù)據(jù)預處理函數(shù)
x = tf.cast(x, dtype=tf.float32) / 255. # 將輸入的圖片進行歸一化,從0-255變換到0-1
x = tf.reshape(x, [28 * 28])
"""
# 將輸入圖片的形狀(60000,28,28)轉換成(60000,28*28),
相當于將圖片拉直,便于輸入給神經(jīng)網(wǎng)絡
"""
y = tf.cast(y, dtype=tf.int32) # 將輸入圖片的標簽轉換為int32類型
y = tf.one_hot(y, depth=10)
"""
# 將標簽y進行獨熱編碼,因為神經(jīng)網(wǎng)絡的輸出是10個概率值,而y是1個數(shù),
計算loss時無法對應計算,因此將y進行獨立編碼成為10個數(shù)的行向量,然后進行l(wèi)oss的計算
獨熱編碼:例如數(shù)值1的10分類的獨熱編碼是[0 1 0 0 0 0 0 0 0 0,即1的位置為1,其余位置為0
"""
return x, y
6.5 數(shù)據(jù)處理
數(shù)據(jù)加載進入內存后,需要轉換成 Dataset 對象,才能利用 TensorFlow 提供的各種便捷功能。
通過 Dataset.from_tensor_slices 可以將訓練部分的數(shù)據(jù)圖片 x 和標簽 y 都轉換成Dataset 對象
batchsz = 128 # 每次輸入給神經(jīng)網(wǎng)絡的圖片數(shù)
"""
數(shù)據(jù)加載進入內存后,需要轉換成 Dataset 對象,才能利用 TensorFlow 提供的各種便捷功能。
通過 Dataset.from_tensor_slices 可以將訓練部分的數(shù)據(jù)圖片 x 和標簽 y 都轉換成Dataset 對象
"""
db = tf.data.Dataset.from_tensor_slices((x_train, y_train)) # 構建訓練集對象
db = db.map(preprocess).shuffle(60000).batch(batchsz) # 將數(shù)據(jù)進行預處理,隨機打散和批量處理
ds_val = tf.data.Dataset.from_tensor_slices((x_test, y_test)) # 構建測試集對象
ds_val = ds_val.map(preprocess).batch(batchsz) # 將數(shù)據(jù)進行預處理,隨機打散和批量處理
6.6 構建網(wǎng)絡模型
構建了5層ANN網(wǎng)絡,每層的神經(jīng)元個數(shù)分別是256,128,64,32,10,隱藏層的激活函數(shù)是relu,輸出層的激活函數(shù)是sortmax
"3.構建網(wǎng)絡模型"
model = Sequential([Dense(256, activation='relu'),
Dense(128, activation='relu'),
Dense(64, activation='relu'),
Dense(32, activation='relu'),
Dense(10,activation='softmax')])
"""
構建了5層ANN網(wǎng)絡,每層的神經(jīng)元個數(shù)分別是256,128,64,32,10,
隱藏層的激活函數(shù)是relu,輸出層的激活函數(shù)是sortmax
"""
model.build(input_shape=(None, 28 * 28)) # 模型的輸入大小
model.summary() # 打印網(wǎng)絡結構
6.7 模型編譯
模型的優(yōu)化器是Adam,學習率是0.01,
損失函數(shù)是losses.CategoricalCrossentropy,
性能指標是正確率accuracy
"4.模型編譯"
model.compile(optimizer=optimizers.Adam(lr=0.01),
loss=tf.losses.CategoricalCrossentropy(from_logits=False),
metrics=['accuracy']
)
"""
模型的優(yōu)化器是Adam,一種優(yōu)化方法,學習率是0.01,
損失函數(shù)是losses.CategoricalCrossentropy,多分類交叉熵損失函數(shù)
性能指標是正確率accuracy
"""
6.8 模型訓練
模型訓練的次數(shù)是5,每1次循環(huán)進行測試
"5.模型訓練"
history = model.fit(db, epochs=5, validation_data=ds_val, validation_freq=1)
"""
模型訓練的次數(shù)是5,每1次循環(huán)進行測試
"""
6.9 模型保存
以.h5文件格式保存模型
"6.模型保存"
model.save('ann_mnist.h5') # 以.h5文件格式保存模型
6.10 模型評價
得到測試集的正確率
"7.模型評價"
model.evaluate(ds_val) # 得到測試集的正確率
6.11 模型測試
對模型進行測試
"8.模型測試"
sample = next(iter(ds_val)) # 取一個batchsz的測試集數(shù)據(jù)
x = sample[0] # 測試集數(shù)據(jù)
y = sample[1] # 測試集的標簽
pred = model.predict(x) # 將一個batchsz的測試集數(shù)據(jù)輸入神經(jīng)網(wǎng)絡的結果
pred = tf.argmax(pred, axis=1) # 每個預測的結果的概率最大值的下標,也就是預測的數(shù)字
y = tf.argmax(y, axis=1) # 每個標簽的最大值對應的下標,也就是標簽對應的數(shù)字
print(pred) # 打印預測結果
print(y) # 打印標簽數(shù)字
6.12 模型訓練結果的可視化
對模型的訓練結果進行可視化文章來源:http://www.zghlxwxcb.cn/news/detail-578579.html
"9.模型訓練時的可視化"
# 顯示訓練集和驗證集的acc和loss曲線
acc = history.history['accuracy'] # 獲取模型訓練中的accuracy
val_acc = history.history['val_accuracy'] # 獲取模型訓練中的val_accuracy
loss = history.history['loss'] # 獲取模型訓練中的loss
val_loss = history.history['val_loss'] # 獲取模型訓練中的val_loss
# 繪值acc曲線
plt.figure(1)
plt.plot(acc, label='Training Accuracy')
plt.plot(val_acc, label='Validation Accuracy')
plt.title('Training and Validation Accuracy')
plt.legend()
# 繪制loss曲線
plt.figure(2)
plt.plot(loss, label='Training Loss')
plt.plot(val_loss, label='Validation Loss')
plt.title('Training and Validation Loss')
plt.legend()
plt.show() # 將結果顯示出來
7. 手寫數(shù)字識別的ANN模型可視化結果圖
Epoch 1/5
469/469 [==============================] - 5s 6ms/step - loss: 0.2726 - accuracy: 0.9186 - val_loss: 0.1712 - val_accuracy: 0.9542
Epoch 2/5
469/469 [==============================] - 3s 5ms/step - loss: 0.1341 - accuracy: 0.9632 - val_loss: 0.1232 - val_accuracy: 0.9654
Epoch 3/5
469/469 [==============================] - 3s 5ms/step - loss: 0.1126 - accuracy: 0.9691 - val_loss: 0.1032 - val_accuracy: 0.9702
Epoch 4/5
469/469 [==============================] - 3s 5ms/step - loss: 0.0926 - accuracy: 0.9750 - val_loss: 0.1217 - val_accuracy: 0.9690
Epoch 5/5
469/469 [==============================] - 3s 5ms/step - loss: 0.0900 - accuracy: 0.9759 - val_loss: 0.1246 - val_accuracy: 0.9676
從以上結果可知,模型的準確率達到了96%。文章來源地址http://www.zghlxwxcb.cn/news/detail-578579.html
8. 完整代碼
# 導入tensorflow
import tensorflow as tf
# 導入keras
from tensorflow import keras
# 引入內置手寫體數(shù)據(jù)集mnist
from keras.datasets import mnist
# 引入繪制acc和loss曲線的庫
import matplotlib.pyplot as plt
# 引入ANN的必要的類
from keras.layers import Dense
from keras.models import Sequential
from keras import optimizers, losses
"1.加載數(shù)據(jù)"
"""
x_train是mnist訓練集圖片,大小的28*28的,y_train是對應的標簽是數(shù)字
x_test是mnist測試集圖片,大小的28*28的,y_test是對應的標簽是數(shù)字
"""
(x_train, y_train), (x_test, y_test) = mnist.load_data() # 加載mnist數(shù)據(jù)集
print('mnist_data:', x_train.shape, y_train.shape, x_test.shape, y_test.shape) # 打印訓練數(shù)據(jù)和測試數(shù)據(jù)的形狀
"2.數(shù)據(jù)預處理"
def preprocess(x, y): # 數(shù)據(jù)預處理函數(shù)
x = tf.cast(x, dtype=tf.float32) / 255. # 將輸入的圖片進行歸一化,從0-255變換到0-1
x = tf.reshape(x, [28 * 28])
"""
# 將輸入圖片的形狀(60000,28,28)轉換成(60000,28*28),
相當于將圖片拉直,便于輸入給神經(jīng)網(wǎng)絡
"""
y = tf.cast(y, dtype=tf.int32) # 將輸入圖片的標簽轉換為int32類型
y = tf.one_hot(y, depth=10)
"""
# 將標簽y進行獨熱編碼,因為神經(jīng)網(wǎng)絡的輸出是10個概率值,而y是1個數(shù),
計算loss時無法對應計算,因此將y進行獨立編碼成為10個數(shù)的行向量,然后進行l(wèi)oss的計算
獨熱編碼:例如數(shù)值1的10分類的獨熱編碼是[0 1 0 0 0 0 0 0 0 0,即1的位置為1,其余位置為0
"""
return x, y
batchsz = 128 # 每次輸入給神經(jīng)網(wǎng)絡的圖片數(shù)
"""
數(shù)據(jù)加載進入內存后,需要轉換成 Dataset 對象,才能利用 TensorFlow 提供的各種便捷功能。
通過 Dataset.from_tensor_slices 可以將訓練部分的數(shù)據(jù)圖片 x 和標簽 y 都轉換成Dataset 對象
"""
db = tf.data.Dataset.from_tensor_slices((x_train, y_train)) # 構建訓練集對象
db = db.map(preprocess).shuffle(60000).batch(batchsz) # 將數(shù)據(jù)進行預處理,隨機打散和批量處理
ds_val = tf.data.Dataset.from_tensor_slices((x_test, y_test)) # 構建測試集對象
ds_val = ds_val.map(preprocess).batch(batchsz) # 將數(shù)據(jù)進行預處理,隨機打散和批量處理
"3.構建網(wǎng)絡模型"
model = Sequential([Dense(256, activation='relu'),
Dense(128, activation='relu'),
Dense(64, activation='relu'),
Dense(32, activation='relu'),
Dense(10,activation='softmax')])
"""
構建了5層ANN網(wǎng)絡,每層的神經(jīng)元個數(shù)分別是256,128,64,32,10,
隱藏層的激活函數(shù)是relu,輸出層的激活函數(shù)是sortmax
"""
model.build(input_shape=(None, 28 * 28)) # 模型的輸入大小
model.summary() # 打印網(wǎng)絡結構
"4.模型編譯"
model.compile(optimizer=optimizers.Adam(lr=0.01),
loss=tf.losses.CategoricalCrossentropy(from_logits=False),
metrics=['accuracy']
)
"""
模型的優(yōu)化器是Adam,學習率是0.01,
損失函數(shù)是losses.CategoricalCrossentropy,
性能指標是正確率accuracy
"""
"5.模型訓練"
history = model.fit(db, epochs=5, validation_data=ds_val, validation_freq=1)
"""
模型訓練的次數(shù)是5,每1次循環(huán)進行測試
"""
"6.模型保存"
model.save('ann_mnist.h5') # 以.h5文件格式保存模型
"7.模型評價"
model.evaluate(ds_val) # 得到測試集的正確率
"8.模型測試"
sample = next(iter(ds_val)) # 取一個batchsz的測試集數(shù)據(jù)
x = sample[0] # 測試集數(shù)據(jù)
y = sample[1] # 測試集的標簽
pred = model.predict(x) # 將一個batchsz的測試集數(shù)據(jù)輸入神經(jīng)網(wǎng)絡的結果
pred = tf.argmax(pred, axis=1) # 每個預測的結果的概率最大值的下標,也就是預測的數(shù)字
y = tf.argmax(y, axis=1) # 每個標簽的最大值對應的下標,也就是標簽對應的數(shù)字
print(pred) # 打印預測結果
print(y) # 打印標簽數(shù)字
"9.模型訓練時的可視化"
# 顯示訓練集和驗證集的acc和loss曲線
acc = history.history['accuracy'] # 獲取模型訓練中的accuracy
val_acc = history.history['val_accuracy'] # 獲取模型訓練中的val_accuracy
loss = history.history['loss'] # 獲取模型訓練中的loss
val_loss = history.history['val_loss'] # 獲取模型訓練中的val_loss
# 繪值acc曲線
plt.figure(1)
plt.plot(acc, label='Training Accuracy')
plt.plot(val_acc, label='Validation Accuracy')
plt.title('Training and Validation Accuracy')
plt.legend()
# 繪制loss曲線
plt.figure(2)
plt.plot(loss, label='Training Loss')
plt.plot(val_loss, label='Validation Loss')
plt.title('Training and Validation Loss')
plt.legend()
plt.show() # 將結果顯示出來
到了這里,關于python與深度學習(一):ANN和手寫數(shù)字識別的文章就介紹完了。如果您還想了解更多內容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!