TensorFlow-1: 如何識別數字

karspb發表於2021-09-09

識別數字在機器學習任務中的地位和 Hello World 在程式設計中是一樣的。

主要步驟:

  1. 獲得資料:from Yann LeCun's website

  2. 建立模型:softmax

  3. 定義 tensor,variable:X,W,b

  4. 定義損失函式,最佳化器:cross-entropy,gradient descent

  5. 訓練模型:loop,batch

  6. 評價:準確率


1. 獲得資料

  • 來自 Yann LeCun's website:http://yann.lecun.com/exdb/mnist/

  • 分為 train,test,validate,每個 X 代表一個圖片,y 是它的 label

  • 其中圖片由 28*28 畫素組成,轉化成 array 的形式,變成 1*784

  • y 變為 one-hot 的形式,即屬於哪個數字,就在哪個位置上為 1, 其餘為 0

圖片描述

目標:給了 X 後,預測它的 label 是屬於 0~9 類中的哪一類

圖片描述

如果想要看資料屬於多類中的哪一類,首先可以想到用 softmax 來做。


2. 建立模型

softmax regression 有兩步:

  1. 把 input 轉化為某類的 evidence

  2. 把 evidence 轉化為 probabilities

1. 把 input 轉化為某類的 evidence

圖片描述

  • 某一類的 evidence 就是畫素強度的加權求和,再加上此類的 bias。

  • 如果某個 pixel 可以作為一個 evidence 證明圖片不屬於此類,則 weight 為負,否則的話 weight 為正。
    下圖中,紅色代表負值,藍色代表正值:

圖片描述

2. 把 evidence 轉化為 probabilities

圖片描述

簡單看,softmax 就是把 input 先做指數,再做一下歸一:

圖片描述

  • 歸一的作用:好理解,就是轉化成機率的性質

  • 為什麼要取指數:在 《常用啟用函式比較》寫過

    • 第一個原因是要模擬 max 的行為,所以要讓大的更大。

    • 第二個原因是需要一個可導的函式。

用圖形表示為:

圖片描述

圖片描述

上面兩步,寫成矩陣形式:

圖片描述

模型的程式碼只有一行:
y = tf.nn.softmax(tf.matmul(x, W) + b)


3. 定義 tensor 和 variable:

圖片描述


4. 定義損失函式,最佳化器:

用 cross-entropy 作為損失來衡量模型的誤差:

圖片描述

其中,y 是預測, y′ 是實際 .

按照表面的定義,程式碼只有一行:

cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(y), reduction_indices=[1]))

不過因為上面不穩定,所以實際用:

cross_entropy = tf.reduce_mean(
      tf.nn.softmax_cross_entropy_with_logits(labels=y_, logits=y))

然後用 backpropagation, 且 gradient descent 作為最佳化器,來訓練模型,使得 loss 達到最小:

train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)


5. 訓練模型

for _ in range(1000):
  batch_xs, batch_ys = mnist.train.next_batch(100)
  sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys})

6. 評價

看 y 和  y′ 有多少相等的,轉化為準確率。
再測試一下 test 資料集上的準確率,結果可以達到 92%。

correct_prediction = tf.equal(tf.argmax(y,1), tf.argmax(y_,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))print(sess.run(accuracy, feed_dict={x: mnist.test.images, y_: mnist.test.labels}))

這只是最簡單的模型,下次看如何提高精度。

完整程式碼和註釋:
溫馨提示,用web開啟,程式碼格式比較好看

"""A very simple MNIST classifier.
See extensive documentation at

"""from __future__ import absolute_importfrom __future__ import divisionfrom __future__ import print_functionimport argparseimport sysfrom tensorflow.examples.tutorials.mnist import input_dataimport tensorflow as tf

FLAGS = Nonedef main(_):
  # Import data
  mnist = input_data.read_data_sets(FLAGS.data_dir, one_hot=True)  # Create the model
  x = tf.placeholder(tf.float32, [None, 784])   
        # a 2-D tensor of floating-point numbers
        # None means that a dimension can be of any length
  W = tf.Variable(tf.zeros([784, 10]))
  b = tf.Variable(tf.zeros([10]))
  y = tf.matmul(x, W) + b        # It only takes one line to define it

  # Define loss and optimizer
  y_ = tf.placeholder(tf.float32, [None, 10])  # The raw formulation of cross-entropy,
  #
  #   tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(tf.nn.softmax(y)),
  #                                 reduction_indices=[1]))
                # tf.reduce_sum adds the elements in the second dimension of y, 
                # due to the reduction_indices=[1] parameter.
                # tf.reduce_mean computes the mean over all the examples in the batch.
  #
  # can be numerically unstable.
  #
  # So here we use tf.nn.softmax_cross_entropy_with_logits on the raw
  # outputs of 'y', and then average across the batch.
  
  cross_entropy = tf.reduce_mean(
      tf.nn.softmax_cross_entropy_with_logits(labels=y_, logits=y))
  train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)        # apply your choice of optimization algorithm to modify the variables and reduce the loss.

  sess = tf.InteractiveSession()        # launch the model in an InteractiveSession
  tf.global_variables_initializer().run()        # create an operation to initialize the variables
        
  # Train~~stochastic training
  for _ in range(1000):
    batch_xs, batch_ys = mnist.train.next_batch(100)            # Each step of the loop, 
            # we get a "batch" of one hundred random data points from our training set.
    sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys})  # Test trained model
  correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))            # use tf.equal to check if our prediction matches the truth
            # tf.argmax(y,1) is the label our model thinks is most likely for each input, 
            # while tf.argmax(y_,1) is the correct label.
  accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))            # [True, False, True, True] would become [1,0,1,1] which would become 0.75.
  print(sess.run(accuracy, feed_dict={x: mnist.test.images,
                                      y_: mnist.test.labels}))            # ask for our accuracy on our test data,about 92%if __name__ == '__main__':
  parser = argparse.ArgumentParser()
  parser.add_argument('--data_dir', type=str, default='/tmp/tensorflow/mnist/input_data',
                      help='Directory for storing input data')
  FLAGS, unparsed = parser.parse_known_args()
  tf.app.run(main=main, argv=[sys.argv[0]] + unparsed)

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/2001/viewspace-2806018/,如需轉載,請註明出處,否則將追究法律責任。

相關文章