首先利用tensorflow寫了一個簡單的線性回歸,自己捏造數據來回歸:
import tensorflow as tf import numpy as np x_data = np.float32(np.random.rand(2,100)) y_data = np.dot([0.1,0.2],x_data) + 3 b = tf.Variable(tf.zeros([1])) w = tf.Variable(tf.random_uniform([1,2],-1,1)) y = tf.matmul(w,x_data)+b loss = tf.reduce_mean(tf.square(y - y_data)) optimzier = tf.train.GradientDescentOptimizer(learning_rate=0.2) train = optimzier.minimize(loss) init = tf.initialize_all_variables() sess = tf.Session() sess.run(init) for step in range(401): sess.run(train) if step % 20 == 0: print(step,sess.run(w),sess.run(b),sess.run(loss))
得到如下結果,誤差顯然很小:
不需要多解釋,都是簡單的操作。
下面再利用tensorflow的開源的數據集mnist來訓練softmax回歸:
每一個MNIST數據單元有兩部分組成:一張包含手寫數字的圖片和一個對應的標簽。我們把這些圖片設為“xs”,把這些標簽設為“ys”。訓練數據集和測試數據集都包含xs和ys,比如訓練數據集的圖片是 mnist.train.images
,訓練數據集的標簽是 mnist.train.labels
。
每一張圖片包含28像素X28像素。我們可以用一個數字數組來表示這張圖片:

我們把這個數組展開成一個向量,長度是 28x28 = 784。如何展開這個數組(數字間的順序)不重要,只要保持各個圖片采用相同的方式展開。從這個角度來看,MNIST數據集的圖片就是在784維向量空間里面的點, 並且擁有比較復雜的結構 (提醒: 此類數據的可視化是計算密集型的)。
展平圖片的數字數組會丟失圖片的二維結構信息。這顯然是不理想的,最優秀的計算機視覺方法會挖掘並利用這些結構信息,我們會在后續教程中介紹。但是在這個教程中我們忽略這些結構,所介紹的簡單數學模型,softmax回歸(softmax regression),不會利用這些結構信息。
因此,在MNIST訓練數據集中,mnist.train.images
是一個形狀為 [60000, 784]
的張量,第一個維度數字用來索引圖片,第二個維度數字用來索引每張圖片中的像素點。在此張量里的每一個元素,都表示某張圖片里的某個像素的強度值,值介於0和1之間。

相對應的MNIST數據集的標簽是介於0到9的數字,用來描述給定圖片里表示的數字。為了用於這個教程,我們使標簽數據是"one-hot vectors"。 一個one-hot向量除了某一位的數字是1以外其余各維度數字都是0。所以在此教程中,數字n將表示成一個只有在第n維度(從0開始)數字為1的10維向量。比如,標簽0將表示成([1,0,0,0,0,0,0,0,0,0,0])。因此, mnist.train.labels
是一個 [60000, 10]
的數字矩陣
Softmax回歸
我們知道MNIST的每一張圖片都表示一個數字,從0到9。我們希望得到給定圖片代表每個數字的概率。比如說,我們的模型可能推測一張包含9的圖片代表數字9的概率是80%但是判斷它是8的概率是5%(因為8和9都有上半部分的小圓),然后給予它代表其他數字的概率更小的值。
這是一個使用softmax回歸(softmax regression)模型的經典案例。softmax模型可以用來給不同的對象分配概率。即使在之后,我們訓練更加精細的模型時,最后一步也需要用softmax來分配概率。
softmax回歸(softmax regression)分兩步:第一步
為了得到一張給定圖片屬於某個特定數字類的證據(evidence),我們對圖片像素值進行加權求和。如果這個像素具有很強的證據說明這張圖片不屬於該類,那么相應的權值為負數,相反如果這個像素擁有有利的證據支持這張圖片屬於這個類,那么權值是正數。
下面的圖片顯示了一個模型學習到的圖片上每個像素對於特定數字類的權值。紅色代表負數權值,藍色代表正數權值。

我們也需要加入一個額外的偏置量(bias),因為輸入往往會帶有一些無關的干擾量。因此對於給定的輸入圖片 x 它代表的是數字 i 的證據可以表示為
其中 代表權重,
代表數字 i 類的偏置量,j 代表給定圖片 x 的像素索引用於像素求和。然后用softmax函數可以把這些證據轉換成概率 y:
這里的softmax可以看成是一個激勵(activation)函數或者鏈接(link)函數,把我們定義的線性函數的輸出轉換成我們想要的格式,也就是關於10個數字類的概率分布。因此,給定一張圖片,它對於每一個數字的吻合度可以被softmax函數轉換成為一個概率值。softmax函數可以定義為:
展開等式右邊的子式,可以得到:
但是更多的時候把softmax模型函數定義為前一種形式:把輸入值當成冪指數求值,再正則化這些結果值。這個冪運算表示,更大的證據對應更大的假設模型(hypothesis)里面的乘數權重值。反之,擁有更少的證據意味着在假設模型里面擁有更小的乘數系數。假設模型里的權值不可以是0值或者負值。Softmax然后會正則化這些權重值,使它們的總和等於1,以此構造一個有效的概率分布。
下面是代碼:
from tensorflow.examples.tutorials.mnist import input_data import tensorflow as tf #加載數據 path = 'C:\\test_mnist_tf' mnist = input_data.read_data_sets(path, one_hot=True) #x為占位符號,可以輸入任意數量的圖片信息 x = tf.placeholder('float',[None,784]) #權值 和 偏重量定義 w = tf.Variable(tf.zeros([784,10])) b = tf.Variable(tf.zeros([10])) #目標值 y = tf.nn.softmax(tf.matmul(x,w) + b) #交叉熵 y_ = tf.placeholder('float',[None,10]) cross_entropy = -tf.reduce_sum(y_ * tf.log(y)) #梯度下降法 train_step = tf.train.GradientDescentOptimizer(learning_rate=0.01).minimize(cross_entropy) #初始化圖 init = tf.global_variables_initializer() sess = tf.Session() sess.run(init) #開始訓練 for i in range(5000): bach_xs, bach_ys = mnist.train.next_batch(100) sess.run(train_step,feed_dict={x:bach_xs,y_:bach_ys}) #評價模型 correct_prediction = tf.equal(tf.argmax(y,1),tf.argmax(y_,1)) accuracy = tf.reduce_mean(tf.cast(correct_prediction,'float')) print(sess.run(accuracy,feed_dict={x:mnist.test.images, y_:mnist.test.labels}))
最后得到的的精度為0.9218,雖然效果不是太好,是因為這是一個非常簡單的模型。
為了提高准確率,采用卷積神經網絡對其進行改進:
import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data #加載數據 path = 'C:\\test_mnist_tf' mnist = input_data.read_data_sets(path, one_hot=True) sess = tf.InteractiveSession() x = tf.placeholder("float", shape=[None, 784]) y_ = tf.placeholder("float", shape=[None, 10]) def weight_variable(shape): initial = tf.truncated_normal(shape,stddev=0.1) return tf.Variable(initial) def bias_variable(shape): initial = tf.constant(0.1,shape = shape) return tf.Variable(initial) def conv2d(x,W): return tf.nn.conv2d(x,W,strides=[1,1,1,1],padding='SAME') def max_pool_2x2(x): return tf.nn.max_pool(x,ksize=[1,2,2,1],strides=[1,2,2,1],padding='SAME') #第一層卷積 W_conv1 = weight_variable([5,5,1,32]) b_conv1 = bias_variable([32]) x_image = tf.reshape(x,[-1,28,28,1]) h_conv1 = tf.nn.relu(conv2d(x_image,W_conv1) + b_conv1) h_pool1 = max_pool_2x2(h_conv1) #第二層卷積 w_conv2 = weight_variable([5,5,32,64]) b_conv2 = bias_variable([64]) h_conv2 = tf.nn.relu(conv2d(h_pool1,w_conv2) + b_conv2) h_pool2 = max_pool_2x2(h_conv2) #全連接 w_fc1 = weight_variable([7*7*64,1024]) b_fc1 = bias_variable([1024]) h_pool_flat = tf.reshape(h_pool2,[-1,7*7*64]) h_fc1 = tf.nn.relu(tf.matmul(h_pool_flat,w_fc1) + b_fc1) #dropout keep_prob = tf.placeholder('float') h_fc1_drop = tf.nn.dropout(h_fc1,keep_prob) w_fc2 = weight_variable([1024,10]) b_fc2 = bias_variable([10]) y_conv = tf.nn.softmax(tf.matmul(h_fc1_drop,w_fc2) + b_fc2) #訓練 cross_entropy = -tf.reduce_mean(y_*tf.log(y_conv)) train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy) correct_prediction = tf.equal(tf.argmax(y_conv,1),tf.argmax(y_,1)) accuracy = tf.reduce_mean(tf.cast(correct_prediction,'float')) sess.run(tf.global_variables_initializer()) for i in range(5000): batch = mnist.train.next_batch(50) if i % 100 == 0: train_accuracy = accuracy.eval(feed_dict={x:batch[0],y_:batch[1],keep_prob:1.0}) print('step %d,train accuracy %g'%(i,train_accuracy)) train_step.run(feed_dict={x:batch[0],y_:batch[1],keep_prob:0.5}) print('test accuracy %g'%accuracy.eval(feed_dict = {x:mnist.test.images,y_:mnist.test.labels,keep_prob:1})) #print(sess.run(accuracy,feed_dict={x:mnist.test.images,y_:mnist.test.labels,keep_prob:1}))
准確率達到了98.75%,有了很大的提高。
另外,本次學習並沒有加入可視化,后續的實踐當中會加入此類的東
********************
神經網絡訓練需要一個有好的gpu機器,gpu版本下訓練速度飛快,本人的電腦因為顯卡不行換成cpu版本訓練的特別慢。。。。。
---恢復內容結束---
---恢復內容結束---