深度學習-圖片識別(上)

深度學習-圖片識別(上)

本文主要針對優達學城深度學習課程中的練習題,整理練習內容,有興趣者可結合本文內容然後按練習題實踐,幫助理解。

任務一:下載並整理數據

任務主要完成圖片下載、圖片內容數字化、選取三個數據集、打亂順序、持久化數據等,步驟如下:

  • 下載包含10個字母的兩份圖片數據,large與small

large與small不止數量大小區別,還在於large中的圖片有沒經過人工篩選,有噪點以及損壞圖片,從中選取數據作爲訓練集與驗證集,small中的圖片經過人工篩選,數據相對乾淨,從中選取數據作爲測試集

  • 處理每個字母文件夾

每張圖片可以用一個28 x 28的二維數組表示,一個目錄下的n張圖片放到一個n x 28 x 28的三維數組中,然後通過pickle序列化到文件中

  • 選取訓練集、驗證集、測試集

從處理好的數據中選取訓練集、驗證集、測試集,選取過程中每個類別打亂順序併合並不同類別,同時使用數組記錄每個數據項對應的類別(label)

  • 再次打亂順序,並序列化到文件

針對每個數據集與label,再次打亂順序,然後把所有數據集以及相應label包裝成dict序列化到磁盤

任務作業

使用sklearn.linear_model中的LogisticRegression模型訓練一個模型,主要代碼:

import numpy as np
import pickle
from sklearn.linear_model import LogisticRegression

image_size = 28
train_size = 1000

data = pickle.load(open('notMNIST.pickle','rb'))

train_features = data['train_dataset'][:train_size]
train_labels = data['train_labels'][:train_size]

test_features = data['test_dataset']
test_labels = data['test_labels']

train_features = train_features.reshape(len(train_features), image_size * image_size)

test_features = test_features.reshape(len(test_features), image_size * image_size)

print 'start train!'
classifier = LogisticRegression()
classifier.fit(train_features, train_labels)

print 'start predict!'
score = classifier.score(test_features,test_labels)

print 'The accuray score is %.3f' % score

結果:

start train!
start predict!
The accuray score is 0.828

任務二:TF邏輯迴歸訓練模型

任務主要構造TF計算圖、訓練模型,最後驗證隨機梯度下降算法帶來的速度優化,這部分內容比上一個任務難度增加,開始涉及TF編程,分爲以下幾步:

  • 重新格式化特徵與標籤

將特徵數組由n x 28 x 28的變形爲n x 784,label的值使用One-Hot編碼

  • 構造計算圖

選取了部分訓練數據作爲輸入,使用tf.truncated_normal生成權重矩陣,計算輸入矩陣與權重矩陣的乘積再加上偏差,然後計算softmax和交叉熵,並使用所有樣本的交叉熵平均值作爲模型針對樣本的損失值,最後使用梯度下降算法優化器優化模型

  • 訓練

訓練801步,每訓練100步,輸出模型針對訓練集與驗證集的損失值、準確度

  • 使用隨機梯度下降算法訓練模型

重新構造計算圖,然後使用隨機梯度下降算法訓練3001步,訓練速度比普通梯度下降算法更快

任務作業

任務二下面有留下一個需要解答的問題:“添加一層通過ReLU函數激活的隱藏層”,主要代碼如下:

batch_size = 128
hidden_layer_node_num = 1024

graph = tf.Graph()
with graph.as_default():
    tf_train_dataset = tf.placeholder(tf.float32, shape=(batch_size, image_size * image_size))
    tf_train_labels = tf.placeholder(tf.float32, shape=(batch_size, num_labels))
    tf_valid_dataset = tf.constant(valid_dataset)
    tf_test_dataset = tf.constant(test_dataset)

    hidden_weights = tf.Variable(tf.truncated_normal([image_size * image_size, hidden_layer_node_num]))
    hidden_biases = tf.Variable(tf.zeros([hidden_layer_node_num]))

    weights = tf.Variable(tf.truncated_normal([hidden_layer_node_num, num_labels]))
    biases = tf.Variable(tf.zeros([num_labels]))

    logits = tf.matmul(tf.nn.relu(tf.matmul(tf_train_dataset, hidden_weights) + hidden_biases), weights) + biases
    loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=tf_train_labels, logits=logits))

    optimizer = tf.train.GradientDescentOptimizer(0.5).minimize(loss)

    train_prediction = tf.nn.softmax(logits)
    valid_prediction = tf.nn.softmax(tf.matmul(tf.nn.relu(tf.matmul(tf_valid_dataset, hidden_weights) + hidden_biases), weights) + biases)
    test_prediction = tf.nn.softmax(tf.matmul(tf.nn.relu(tf.matmul(tf_test_dataset, hidden_weights) + hidden_biases), weights) + biases)

任務三:優化模型

任務三本身沒有多少現成代碼,主要靠自己動手。

L2正則化

接任務二ReLU的代碼,只要爲損失函數loss添加L2正則化的結果即可,選0.001438作爲超參λ的值,課程沒有講如何選擇超參的值,這個值是從他人文章中借用的。

在之前的損失函數賦值後面添加:

loss = loss + 0.001438 * (tf.nn.l2_loss(hidden_weights) + tf.nn.l2_loss(hidden_biases) + tf.nn.l2_loss(weights) + tf.nn.l2_loss(biases))

過度擬合

將訓練數據減少爲幾個批次的量,演示過度擬合。

從訓練數據中取出一個較小的子集作爲訓練集:

batch_size = 128
train_dataset = train_dataset[:batch_size * 5, :]
train_labels = train_labels[:batch_size * 5, :]

過度擬合,會導致模型在訓練集上的表現很好,但針對驗證集或測試集,表現大打折扣。

丟棄法

dropout會隨機將輸入值丟棄或縮放,可達到訓練模型冗餘性,防止過度擬合。

核心代碼:

tmp = tf.nn.relu(tf.matmul(tf_train_dataset, hidden_weights) + hidden_biases)
tmp = tf.nn.dropout(tmp, 0.5)
logits = tf.matmul(tmp, weights) + biases

dropout第二個參數0.5,說明dropout的行爲是隨機將部分值置爲0,另外一部分x2,這樣,整體樣本的平均值不會變化。

多層神經網絡

該習題的目的是使用多層神經網絡,使最終測試集的準確率達到97.1%。

核心代碼:

hlnn1 = 4096
hlnn2 = 2048
hlnn3 = 128

hw1 = tf.Variable(tf.truncated_normal([image_size * image_size, hlnn1], stddev=np.sqrt(2.0 / (image_size * image_size))))
    hb1 = tf.Variable(tf.zeros([hlnn1]))

    hw2 = tf.Variable(tf.truncated_normal([hlnn1, hlnn2], stddev=np.sqrt(2.0 / hlnn1)))
    hb2 = tf.Variable(tf.zeros([hlnn2]))

    hw3 = tf.Variable(tf.truncated_normal([hlnn2, hlnn3], stddev=np.sqrt(2.0 / hlnn2)))
    hb3 = tf.Variable(tf.zeros([hlnn3]))

    weights = tf.Variable(tf.truncated_normal([hlnn3, num_labels], stddev=np.sqrt(2.0 / hlnn3)))
    biases = tf.Variable(tf.zeros([num_labels]))

    tmp = tf.nn.relu(tf.matmul(tf_train_dataset, hw1) + hb1)
    tmp = tf.nn.relu(tf.matmul(tmp, hw2) + hb2)
    tmp = tf.nn.relu(tf.matmul(tmp, hw3) + hb3)

    logits = tf.matmul(tmp, weights) + biases

    loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=tf_train_labels, logits=logits))
    loss = loss + tf_beta * (tf.nn.l2_loss(hw1) + tf.nn.l2_loss(hb1) + tf.nn.l2_loss(hw2) + tf.nn.l2_loss(hb2) +
                             tf.nn.l2_loss(hw3) + tf.nn.l2_loss(hb3) + tf.nn.l2_loss(weights) + tf.nn.l2_loss(biases))

    learning_rate = tf.train.exponential_decay(0.5, global_step, 1000, 0.7, staircase=True)
    optimizer = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss, global_step=global_step)

添加多個隱藏層,然後使用學習速率衰減方式,讓損失降低,準確率進一步提升,到這一步我的Mac電腦已經開始喫不消,訓練5000步,模型在測試集上的準確率95.1%,繼續訓練,模型的表現應該會更好。

博客原文

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章