只有一層隱藏層,一般叫多層感知機
深度神經網絡(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) # 查看最大的類別是哪個