深度學習(二)——案例,兩層DNN進行圖片識別

只有一層隱藏層,一般叫多層感知機
深度神經網絡(DNN)
除了輸出層,每層都包括bias,都是全連接到下一層
人工神經網絡(ANN)有兩個或兩個以上隱藏層

在這裏插入圖片描述
每根線上都有w

代碼:

import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
import numpy as np
# 全連接,通過它進行上下層之間的全連接
from tensorflow.contrib.layers import fully_connected


# 構建圖階段
n_inputs = 28*28  # 輸入層結點數,784像素
n_hidden1 = 300  # 第一個隱藏層結點數
n_hidden2 = 100  # 第二個隱藏層結點數
n_outputs = 10  # 輸出層十個,因爲有十個數字的圖片啊

X = tf.placeholder(tf.float32, shape=(None, n_inputs), name='X')
y = tf.placeholder(tf.int64, shape=(None), name='y')


# 構建神經網絡層,我們這裏兩個隱藏層,基本一樣,除了輸入inputs到每個神經元的連接不同
# 和神經元個數不同
# 輸出層也非常相似,只是激活函數從ReLU變成了Softmax而已
# activation=None 就是沒有激活
def neuron_layer(X, n_neurons, name, activation=None):
    # 包含所有計算節點對於這一層,name_scope可寫可不寫
    with tf.name_scope(name):
        # 取輸入矩陣的維度作爲層的輸入連接個數
        n_inputs = int(X.get_shape()[1])
        stddev = 2 / np.sqrt(n_inputs)  # 標準方差
        # 這層裏面的w可以看成是二維數組,每個神經元對於一組w參數
        # truncated normal distribution 比 regular normal distribution的值小
        # 不會出現任何大的權重值,確保慢慢的穩健的訓練
        # 使用這種標準方差會讓收斂快
        # w參數需要隨機,不能爲0,否則輸出爲0,最後調整都是一個幅度沒意義
        # w的初始化,服從正態分佈,正態分佈的寬度取決於上面算得的方差的大小
        init = tf.truncated_normal((n_inputs, n_neurons), stddev=stddev)
        w = tf.Variable(init, name='weights')
        b = tf.Variable(tf.zeros([n_neurons]), name='biases')
        # 向量表達的使用比一條一條加和要高效
        z = tf.matmul(X, w) + b
        if activation == "relu":
            return tf.nn.relu(z)
        else:
            return z


with tf.name_scope("dnn"):
    hidden1 = neuron_layer(X, n_hidden1, "hidden1", activation="relu")
    hidden2 = neuron_layer(hidden1, n_hidden2, "hidden2", activation="relu")
    # 進入到softmax之前的結果
    logits = neuron_layer(hidden2, n_outputs, "outputs")

# 用下面這4行可以代替上面22~49行全部
# with tf.name_scope("dnn"):
#     # tensorflow使用這個函數幫助我們使用合適的初始化w和b的策略,默認使用ReLU激活函數
#     hidden1 = fully_connected(X, n_hidden1, scope="hidden1")
#     hidden2 = fully_connected(hidden1, n_hidden2, scope="hidden2")
#     logits = fully_connected(hidden2, n_outputs, scope="outputs", activation_fn=None)

with tf.name_scope("loss"):
    # 定義交叉熵損失函數,並且求個樣本平均
    # 函數等價於先使用softmax損失函數,再接着計算交叉熵,並且更有效率
    # 類似的softmax_cross_entropy_with_logits只會給one-hot編碼,我們使用的會給0-9分類號
    xentropy = tf.nn.sparse_softmax_cross_entropy_with_logits(labels=y, logits=logits)
    loss = tf.reduce_mean(xentropy, name="loss")

learning_rate = 0.01

with tf.name_scope("train"):
    # 梯度下降的優化器
    optimizer = tf.train.GradientDescentOptimizer(learning_rate)
    training_op = optimizer.minimize(loss)

with tf.name_scope("eval"):
    # 獲取logits裏面最大的那1位和y比較類別好是否相同,返回True或者False一組值
    correct = tf.nn.in_top_k(logits, y, 1)
    accuracy = tf.reduce_mean(tf.cast(correct, tf.float32))

init = tf.global_variables_initializer()
saver = tf.train.Saver()

# 計算圖階段
mnist = input_data.read_data_sets("MNIST_data_bak/")
n_epochs = 400
batch_size = 50

with tf.Session() as sess:
    init.run()
    for epoch in range(n_epochs):
        for iteration in range(mnist.train.num_examples // batch_size):
            X_batch, y_batch = mnist.train.next_batch(batch_size)
            sess.run(training_op, feed_dict={X: X_batch, y: y_batch})
        acc_train = accuracy.eval(feed_dict={X: X_batch, y: y_batch})
        acc_test = accuracy.eval(feed_dict={X: mnist.test.images,
                                            y: mnist.test.labels})
        print(epoch, "Train accuracy:", acc_train, "Test accuracy:", acc_test)

    save_path = saver.save(sess, "./my_dnn_model_final.ckpt")


# 使用模型預測
# with tf.Session as sess:
#     saver.restore(sess, "./my_dnn_model_final.ckpt")
#     X_new_scaled = [...]
#     Z = logits.eval(feed_dict={X: X_new_scaled})
#     y_pred = np.argmax(Z, axis=1)  # 查看最大的類別是哪個

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