1. 程式人生 > >【TensorFlow/簡單網絡】MNIST數據集-softmax、全連接神經網絡,卷積神經網絡模型

【TensorFlow/簡單網絡】MNIST數據集-softmax、全連接神經網絡,卷積神經網絡模型

idt form data labels pac amp sil ber 內置函數

初學tensorflow,參考了以下幾篇博客:

soft模型

tensorflow構建全連接神經網絡

tensorflow構建卷積神經網絡

tensorflow構建卷積神經網絡

tensorflow構建CNN[待學習]

全連接+各種優化[待學習]

BN層[待學習]


先解釋以下MNIST數據集,訓練數據集有55,000 條,即X為55,000 * 784的矩陣,那麽Y為55,000 * 10的矩陣,每個圖片是28像素*28像素,帶有標簽,Y為該圖片的真實數字,即標簽,每個圖片10個數字,1所在位置代表圖片類別。

Softmax模型

準確率92.3,讀入時候將圖片拉成一個向量。使用Adam梯度下降求答案。

  1. import tensorflow as tf
  2. import numpy as np
  3. from tensorflow.examples.tutorials.mnist import input_data
  4. #訓練數據集有55,000 條,即X為55,000 * 784的矩陣,那麽Y為55,000 * 10的矩陣
  5. #讀數據,one_hot表示將矩陣處理為行向量,即28*28 => 1*784
  6. mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)
  7. learning_rate = 0.01
  8. batch_size = 128
  9. n_epochs = 1000
  10. x = tf.placeholder(tf.float32, [None
    , 784]) #因為訓練時跟測試時樣本數量不一樣,所以直接None
  11. #只是一個softmax分類器,初始化0就好了,默認訓練variable.trainable=True的參數
  12. W = tf.Variable(tf.zeros([784, 10]))
  13. b = tf.Variable(tf.zeros([10]))
  14. #softmax 輸出一個10*1的矩陣,代表每個值的概率分布
  15. y_hat = tf.nn.softmax(tf.matmul(x, W) + b)
  16. y = tf.placeholder(tf.float32, [None, 10])
  17. #交叉熵損失函數
  18. loss = tf.reduce_mean(-tf.reduce_sum(y * tf.log(y_hat)))
  19. #也可以調用內置函數
  20. #entropy = tf.nn.softmax_cross_entropy_with_logits(logits, Y) #第一個是測試輸出的函數,第二個是樣本類別真實值
  21. #loss = tf.reduce_mean(entropy) # computes the mean over examples in the batch
  22. #學習率為0.01 使用Adam梯度下降
  23. train = tf.train.AdamOptimizer(learning_rate).minimize(loss)
  24. correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_hat, 1)) # 測試樣本只有一個1,看這個1的位置和預測的概率最大值是否一樣
  25. accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32)) # 通過cast將布爾類型轉化成float類型,每個值要麽0要麽1,求他的均值就是準確率
  26. with tf.Session() as sess:
  27. sess.run(tf.global_variables_initializer())
  28. for i in range(n_epochs):
  29. batch_x, batch_y = mnist.train.next_batch(batch_size) #獲取批量樣本
  30. sess.run(train, feed_dict={x: batch_x, y: batch_y}) #運行計算圖
  31. print(sess.run(accuracy, feed_dict={x: mnist.test.images, y: mnist.test.labels}))

全連接神經網絡模型

2層隱藏層,激活函數為relu函數,分類函數為softmax函數,學習率采用指數下降法,基本初始學習率0.01,如果太大會只有9.8%的準確率,學習率衰減速度如果太快也會準確率下降(過擬合),dropout正則化不是很管用,會讓準確率下降,只有keep_prob = 0.99才勉強準確率高點。如果一個隱藏層,準確率為93.45%,無論是學習率大了,過度正則化都會導致9.8%。學習率太低則90左右的準確率

  1. import tensorflow as tf
  2. import numpy as np
  3. from tensorflow.examples.tutorials.mnist import input_data
  4. # 訓練數據集有55,000 條,即X為55,000 * 784的矩陣,那麽Y為55,000 * 10的矩陣
  5. # 讀數據,one_hot表示將矩陣處理為行向量,即28*28 => 1*784
  6. mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)
  7. base_learning_rate = 0.01
  8. batch_size = 128
  9. n_epochs = 1000
  10. keep_prob = 1
  11. decay_steps = 2
  12. decay_rate = 0.99
  13. def add_layer(inputs, input_size, output_size, activation_function=None):
  14. W = tf.Variable(tf.random_normal([input_size, output_size]) * np.sqrt(1/input_size))
  15. b = tf.Variable(tf.zeros([1, output_size]) + 0.1)
  16. y_hat = tf.matmul(inputs, W) + b
  17. y_hat = tf.nn.dropout(y_hat, keep_prob=keep_prob) #dropout 自動除以了keep_prob
  18. if activation_function is None:
  19. outputs = y_hats
  20. else:
  21. outputs = activation_function(y_hat)
  22. return outputs
  23. x = tf.placeholder(tf.float32, [None, 784])
  24. y = tf.placeholder(tf.float32, [None, 10])
  25. layer1 = add_layer(x, 784, 100, activation_function=tf.nn.relu)
  26. layer2 = add_layer(layer1, 100, 10, activation_function=tf.nn.relu)
  27. y_hat = add_layer(layer2, 10, 10, tf.nn.softmax)
  28. #定義存儲訓練輪數的變量,這個變量不需要被訓練
  29. global_step = tf.Variable(0, trainable=False)
  30. learning_rate = tf.train.exponential_decay(base_learning_rate, global_step, decay_steps, decay_rate)
  31. #base_learning_rate為基礎學習率,global_step為當前叠代的次數
  32. #decay_steps為幾步一下降
  33. #decay_rate為學習率衰減速度
  34. loss = tf.reduce_mean(-tf.reduce_sum(y*tf.log(y_hat)))
  35. train = tf.train.AdamOptimizer(learning_rate).minimize(loss, global_step=global_step) #會自增
  36. correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_hat, 1)) # 測試樣本只有一個1,看這個1的位置和預測的概率最大值是否一樣
  37. accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32)) # 通過cast將布爾類型轉化成float類型,每個值要麽0要麽1,求他的均值就是準確率
  38. with tf.Session() as sess:
  39. sess.run(tf.global_variables_initializer())
  40. for i in range(n_epochs):
  41. batch_x, batch_y = mnist.train.next_batch(batch_size)
  42. sess.run(train, feed_dict={x: batch_x, y: batch_y})
  43. print(sess.run(accuracy, feed_dict={x: mnist.test.images, y: mnist.test.labels}))


卷積網絡模型(LENET)

思路

使用一個簡單的CNN網絡結構如下,括號裏邊表示tensor經過本層後的輸出shape:

  • 輸入層(28 * 28 * 1)
  • 卷積層1(28 * 28 * 32)
  • pooling層1(14 * 14 * 32)
  • 卷積層2(14 * 14 * 64)
  • pooling層2(7 * 7 * 64)
  • 全連接層(1 * 1024)
  • softmax層(10)

主要的函數說明:

卷積層:
tf.nn.conv2d(input, filter, strides, padding, use_cudnn_on_gpu=None, data_format=None, name=None)

參數說明:
  • data_format:表示輸入的格式,有兩種分別為:“NHWC”和“NCHW”,默認為“NHWC”

  • input:輸入是一個4維格式的(圖像)數據,數據的 shape 由 data_format 決定:當 data_format 為“NHWC”輸入數據的shape表示為[batch, in_height, in_width, in_channels],分別表示訓練時一個batch的圖片數量、圖片高度、 圖片寬度、 圖像通道數。當 data_format 為“NHWC”輸入數據的shape表示為[batch, in_channels, in_height, in_width]

  • filter:卷積核是一個4維格式的數據:shape表示為:[height,width,in_channels, out_channels],分別表示卷積核的高、寬、深度(與輸入的in_channels應相同)、輸出 feature map的個數(即卷積核的個數)。

  • strides:表示步長:一個長度為4的一維列表,每個元素跟data_format互相對應,表示在data_format每一維上的移動步長。當輸入的默認格式為:“NHWC”,則 strides = [batch , in_height , in_width, in_channels]。其中 batch 和 in_channels 要求一定為1,即只能在一個樣本的一個通道上的特征圖上進行移動,in_height , in_width表示卷積核在特征圖的高度和寬度上移動的布長,即 和 。

  • padding:表示填充方式:“SAME”表示采用填充的方式,簡單地理解為以0填充邊緣,當stride為1時,輸入和輸出的維度相同;“VALID”表示采用不填充的方式,多余地進行丟棄。具體公式:

    “SAME”:

    “VALID”:

池化層:
tf.nn.max_pool( value, ksize,strides,padding,data_format=’NHWC’,name=None)
或者
tf.nn.avg_pool(…)

參數說明:
  • value:表示池化的輸入:一個4維格式的數據,數據的 shape 由 data_format 決定,默認情況下shape 為[batch, height, width, channels]

  • 其他參數與 tf.nn.cov2d 類型

  • ksize:表示池化窗口的大小:一個長度為4的一維列表,一般為[1, height, width, 1],因不想在batch和channels上做池化,則將其值設為1。

Batch Nomalization層:
batch_normalization( x,mean,variance,offset,scale, variance_epsilon,name=None)

  • mean 和 variance 通過 tf.nn.moments 來進行計算:
    batch_mean, batch_var = tf.nn.moments(x, axes = [0, 1, 2], keep_dims=True),註意axes的輸入。對於以feature map 為維度的全局歸一化,若feature map 的shape 為[batch, height, width, depth],則將axes賦值為[0, 1, 2]

  • x 為輸入的feature map 四維數據,offset、scale為一維Tensor數據,shape 等於 feature map 的深度depth。

註意,計算準確率的時候,一定讓keep_prob等於1

  1. import tensorflow as tf
  2. import numpy as np
  3. #導入input_data用於自動下載和安裝MNIST數據集
  4. from tensorflow.examples.tutorials.mnist import input_data
  5. mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)
  6. #創建兩個占位符,x為輸入網絡的圖像,y_為輸入網絡的圖像類別
  7. x = tf.placeholder("float", shape=[None, 784])
  8. y = tf.placeholder("float", shape=[None, 10])
  9. #權重初始化函數
  10. def weight_variable(shape):
  11. #輸出服從截尾正態分布的隨機值
  12. initial = tf.truncated_normal(shape, stddev=0.1)
  13. return tf.Variable(initial)
  14. #偏置初始化函數
  15. def bias_variable(shape):
  16. initial = tf.constant(0.1, shape=shape)
  17. return tf.Variable(initial)
  18. #創建卷積op
  19. #x 是一個4維張量,shape為[batch,height,width,channels]
  20. #卷積核移動步長為1。填充類型為SAME,可以不丟棄任何像素點
  21. def conv2d(x, W):
  22. return tf.nn.conv2d(x, W, strides=[1,1,1,1], padding="SAME")
  23. #創建池化op
  24. #采用最大池化,也就是取窗口中的最大值作為結果
  25. #x 是一個4維張量,shape為[batch,height,width,channels]
  26. #ksize表示pool窗口大小為2x2,也就是高2,寬2
  27. #strides,表示在height和width維度上的步長都為2
  28. def max_pool_2x2(x):
  29. return tf.nn.max_pool(x, ksize=[1,2,2,1],
  30. strides=[1,2,2,1], padding="SAME")
  31. #第1層,卷積層
  32. #初始化W為[5,5,1,32]的張量,表示卷積核大小為5*5,第一層網絡的輸入和輸出神經元個數分別為1和32
  33. W_conv1 = weight_variable([5,5,1,32])
  34. #初始化b為[32],即輸出大小
  35. b_conv1 = bias_variable([32])
  36. #把輸入x(二維張量,shape為[batch, 784])變成4d的x_image,x_image的shape應該是[batch,28,28,1]
  37. #-1表示自動推測這個維度的size
  38. x_image = tf.reshape(x, [-1,28,28,1])
  39. #把x_image和權重進行卷積,加上偏置項,然後應用ReLU激活函數,最後進行max_pooling
  40. #h_pool1的輸出即為第一層網絡輸出,shape為[batch,14,14,1]
  41. h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1)
  42. h_pool1 = max_pool_2x2(h_conv1)
  43. #第2層,卷積層
  44. #卷積核大小依然是5*5,這層的輸入和輸出神經元個數為32和64
  45. W_conv2 = weight_variable([5,5,32,64])
  46. b_conv2 = weight_variable([64])
  47. #h_pool2即為第二層網絡輸出,shape為[batch,7,7,1]
  48. h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2)
  49. h_pool2 = max_pool_2x2(h_conv2)
  50. #第3層, 全連接層
  51. #這層是擁有1024個神經元的全連接層
  52. #W的第1維size為7*7*64,7*7是h_pool2輸出的size,64是第2層輸出神經元個數
  53. W_fc1 = weight_variable([7*7*64, 1024])
  54. b_fc1 = bias_variable([1024])
  55. #計算前需要把第2層的輸出reshape成[batch, 7*7*64]的張量
  56. h_pool2_flat = tf.reshape(h_pool2, [-1, 7*7*64])
  57. h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1)
  58. #Dropout層
  59. #為了減少過擬合,在輸出層前加入dropout
  60. keep_prob = tf.placeholder("float")
  61. h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)
  62. #輸出層
  63. #最後,添加一個softmax層
  64. #可以理解為另一個全連接層,只不過輸出時使用softmax將網絡輸出值轉換成了概率
  65. W_fc2 = weight_variable([1024, 10])
  66. b_fc2 = bias_variable([10])
  67. y_conv = tf.nn.softmax(tf.matmul(h_fc1_drop, W_fc2) + b_fc2)
  68. #預測值和真實值之間的交叉墑
  69. cross_entropy = -tf.reduce_sum(y * tf.log(y_conv))
  70. #train op, 使用ADAM優化器來做梯度下降。學習率為0.0001
  71. train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)
  72. #評估模型,tf.argmax能給出某個tensor對象在某一維上數據最大值的索引。
  73. #因為標簽是由0,1組成了one-hot vector,返回的索引就是數值為1的位置
  74. correct_predict = tf.equal(tf.argmax(y_conv, 1), tf.argmax(y, 1))
  75. #計算正確預測項的比例,因為tf.equal返回的是布爾值,
  76. #使用tf.cast把布爾值轉換成浮點數,然後用tf.reduce_mean求平均值
  77. accuracy = tf.reduce_mean(tf.cast(correct_predict, "float"))
  78. with tf.Session() as sess:
  79. # 初始化變量
  80. sess.run(tf.global_variables_initializer())
  81. # 開始訓練模型,循環20000次,每次隨機從訓練集中抓取50幅圖像
  82. for i in range(1000):
  83. batch = mnist.train.next_batch(50)
  84. if i % 100 == 0:
  85. # 每100次輸出一次日誌
  86. train_accuracy = accuracy.eval(feed_dict={
  87. x: batch[0], y: batch[1], keep_prob: 1.0}) #計算準確率時候一定讓keep_prob等於1
  88. print("step %d, training accuracy %g" % (i, train_accuracy))
  89. train_step.run(feed_dict={x: batch[0], y: batch[1], keep_prob: 0.5})
  90. print(sess.run(accuracy, feed_dict={x: mnist.test.images, y: mnist.test.labels}))








【TensorFlow/簡單網絡】MNIST數據集-softmax、全連接神經網絡,卷積神經網絡模型