看了幾天的Deep Learnning的書,全是高數(shù)公式,看得一臉懵逼, 所以找了個tensorflow的例子看看這個些矩陣變化的意義。機(jī)器學(xué)習(xí)交流可訪問
http://www.jokls.com
這里是tensorflow 書上的一個列子MNIST,數(shù)據(jù)來源 http://yann.lecun.com/exdb/mnist/
就是一個手寫體阿拉伯?dāng)?shù)字的圖像識別的程序。
訓(xùn)練集有55000張圖片, 檢驗集中有5000張圖片,處理后的每張圖片都是784像素的一維數(shù)組,數(shù)組中的數(shù)字對應(yīng)了 (28*28=784) 像素矩陣中的每一個數(shù)字
我安裝的tensorflow版本是 1.2 whl.
書上的例子在tensorflow1.2上運行不了, 會報錯, 看了tensorflow的這個sparse_softmax_cross_entropy_with_logits函數(shù)的源碼,發(fā)現(xiàn)調(diào)用方式有變化,改成這樣即可:
tf.nn.sparse_softmax_cross_entropy_with_logits(logits=y, labels=tf.argmax(y_, 1))
程序代碼如下:
from tensorflow.examples.tutorials.mnist import input_data
import tensorflow as tf
INPUT_NODE= 784 #輸入層的節(jié)點數(shù),即為圖片的像素
OUTPUT_NODE = 10 #輸出的節(jié)點數(shù),在MINST中需要區(qū)分的是0-9,所以輸出節(jié)點數(shù)是10
LAYER1_NODE= 500 #隱藏層的節(jié)點數(shù)
BATCH_SIZE= 100 #一個訓(xùn)練batch中的訓(xùn)練數(shù)據(jù)個數(shù), 值越少越接近隨機(jī)梯度,值越大越接近梯度下降
LEARNING_RATE_BASE= 0.8 #基礎(chǔ)學(xué)習(xí)率
LEARNING_RATE_DECAY= 0.99 #學(xué)習(xí)率的衰減率
REGULARIZATION_RATE= 0.0001 #描述模型復(fù)雜度正則化項在損失函數(shù)中的系數(shù)
TRAINING_STEPS= 30000 #訓(xùn)練輪數(shù)
MOVING_AVERAGE_DECAY= 0.99 #滑動平均衰減率
#計算神經(jīng)網(wǎng)絡(luò)的前向傳播結(jié)果
# 在這里定義了一個使用ReLU激活函數(shù)的三層全連接神經(jīng)網(wǎng)絡(luò),通過加入隱藏層實現(xiàn)了多層網(wǎng)絡(luò)結(jié)構(gòu)
#通過ReLu激活函數(shù)實現(xiàn)了去線性化,這個函數(shù)也支持滑動平均計算mean(股票的MACD就是用這個滑動平均算的)
def inference(input_tensor, avg_class, weight1,biases1, weight2, biases2):
#如果沒有提供滑動平均函數(shù),則直接使用參數(shù)當(dāng)前值
if avg_class == None:
#計算隱藏層的前向傳播結(jié)果,這里使用ReLU作為激活函數(shù)
layer1 = tf.nn.relu(tf.matmul(input_tensor,weight1) + biases1)
#計算輸出層前向傳播的結(jié)果,因為在計算損失函數(shù)時會一并計算softmax 函數(shù)
#所以這里不需要加入激活函數(shù),而且不加入softmax函數(shù)也不會影響結(jié)果,因為預(yù)測時使用的是
#不同類別對應(yīng)節(jié)點輸出值的大小,有沒有softmax層對最后分類結(jié)果的計算沒有影響,于是在計算整個神經(jīng)
#網(wǎng)絡(luò)的前向傳播時可以不加入最后的softmax層
return tf.matmul(layer1, weight2) + biases2
else:
#先使用avg_class計算變量的滑動平均值,然后再計算神經(jīng)網(wǎng)絡(luò)前向傳播結(jié)果
layer1 = tf.nn.relu(tf.matmul(input_tensor, avg_class.average(weight1)) + avg_class.average(biases1))
return tf.matmul(layer1, avg_class.average(weight2)) + avg_class.average(biases2)
#神經(jīng)網(wǎng)絡(luò)訓(xùn)練函數(shù)
def train(minst):
x = tf.placeholder(tf.float32, [None, INPUT_NODE], name="x_input")
y_ = tf.placeholder(tf.float32, [None, OUTPUT_NODE], name="y_input")
#生成隱藏層的參數(shù)
weight1= tf.Variable(tf.truncated_normal([INPUT_NODE, LAYER1_NODE], stddev= 0.1))
biases1= tf.Variable(tf.constant(0.1, shape=[LAYER1_NODE]))
#生成輸出層的參數(shù)
weight2= tf.Variable(tf.truncated_normal([LAYER1_NODE, OUTPUT_NODE], stddev= 0.1))
biases2= tf.Variable(tf.constant(0.1, shape=[OUTPUT_NODE]))
#計算當(dāng)前參數(shù)下神經(jīng)網(wǎng)絡(luò)前向傳播的結(jié)果
y = inference(x, None, weight1, biases1, weight2, biases2)
#定義存儲訓(xùn)練輪數(shù)的變量,這個變量不需要計算滑動平均值,所以這里指定這個變量為不可訓(xùn)練的變量(trainable=False)
#在使用Tensorflow訓(xùn)練神經(jīng)網(wǎng)絡(luò)時,一般將代表訓(xùn)練輪數(shù)的變量指定為不可訓(xùn)練的參數(shù)
global_step= tf.Variable(0, trainable=False)
#給定滑動平均衰減率和訓(xùn)練輪數(shù)的變量,初始化滑動平均類
variable_avg= tf.train.ExponentialMovingAverage(MOVING_AVERAGE_DECAY, global_step)
variable_avg_op= variable_avg.apply(tf.trainable_variables())
avg_y= inference(x, variable_avg, weight1, biases1, weight2, biases2)
#計算交叉熵作為刻畫預(yù)測值與真實值之間差距的損失函數(shù),這里使用了Tensorflow的sparse_softmax_cross_entropy_with_logits函數(shù)來計算交叉熵
#當(dāng)分類問題只有一個正確答案是,這個函數(shù)可以加速交叉熵的計算。MNIS
#cross_entopy= tf.nn.sparse_softmax_cross_entropy_with_logits(y, tf.argmax(y_, 1))
cross_entopy= tf.nn.sparse_softmax_cross_entropy_with_logits(logits=y, labels=tf.argmax(y_, 1))
print("cross_entopy = ",cross_entopy)
#這里是計算使用reduce_mean求向量的均值,也就是Loss函數(shù)的值,如果要求代價函數(shù)H的值,則需要使用tf.reduce_sum
cross_entopy_mean= tf.reduce_mean(cross_entopy)
#計算L2的正則化損失函數(shù)
regularizer= tf.contrib.layers.l2_regularizer(REGULARIZATION_RATE)
#計算模型的正則化損失,一般只計算神經(jīng)網(wǎng)絡(luò)邊上權(quán)重的正則化損失,而不使用偏置項
regularization= regularizer(weight1) + regularizer(weight2)
#總得損失函數(shù)的值等于交叉熵的值和正則化損失之和
loss= cross_entopy_mean + regularization
#設(shè)置指數(shù)衰減的學(xué)習(xí)率
learning_rate= tf.train.exponential_decay(LEARNING_RATE_BASE, global_step, minst.train.num_examples, LEARNING_RATE_DECAY)
#使用梯度下降優(yōu)化算法來優(yōu)化損失函數(shù), 這里的損失函數(shù)包含了交叉熵和L2正則化損失
train_step= tf.train.GradientDescentOptimizer(learning_rate).minimize(loss,global_step= global_step)
#在神經(jīng)網(wǎng)絡(luò)中,每循環(huán)一遍,就需要更新通過反向傳播來更新參數(shù)的值,并且更新參數(shù)的滑動平均值
#為了一次完成這兩個操作,Tensorflow提供了 control_dependencies 和group兩種機(jī)制,結(jié)果是等價的
with tf.control_dependencies([train_step,variable_avg_op]):
train_op= tf.no_op(name='train')
#檢查使用了滑動平均模型的神經(jīng)網(wǎng)絡(luò)前向傳播結(jié)果是否正確
#tf.argmax()用來獲取每一個樣例的預(yù)測結(jié)果, argmax 的第二個參數(shù)"1"表示選取最大值得操作僅在第一個維度中進(jìn)行,也就是只在第一行選取最大值得下標(biāo)
#于是就得到一個長度為batch的一維數(shù)組,這個一維數(shù)組中的值就表示了每一個樣例對應(yīng)數(shù)字的識別結(jié)果, tf.equal用來判斷兩個張量的每一維是否相等
correct_prediction = tf.equal(tf.argmax(avg_y,1),tf.argmax(y_,1))
#這里是將一個布爾類型的值轉(zhuǎn)換成實數(shù)類型的值,然后計算平均值,這個平均值就是模型在這一組數(shù)據(jù)上的正確率
accuracy = tf.reduce_mean(tf.cast(correct_prediction,tf.float32))
with tf.Session() as sess:
tf.global_variables_initializer().run()
#準(zhǔn)備驗證數(shù)據(jù).一般在神經(jīng)網(wǎng)絡(luò)的訓(xùn)練過程中會通過驗證數(shù)據(jù)來大致判斷停止的條件和評判訓(xùn)練的效果
validate_feed = {x: minst.validation.images, y_: minst.validation.labels}
#準(zhǔn)備測試數(shù)據(jù),在真是的應(yīng)用中,這部分?jǐn)?shù)據(jù)在訓(xùn)練時是不可見的,這個數(shù)據(jù)是模型的優(yōu)劣的最后評價標(biāo)準(zhǔn)
test_feed= {x:minst.test.images, y_:minst.test.labels}
for i in range(TRAINING_STEPS):
if i % 1000 == 0:
#計算滑動平均模型在驗證數(shù)據(jù)上的結(jié)果
validate_acc = sess.run(accuracy, feed_dict=validate_feed)
print("After %d traing step(s), validation accuracy use average model is %g" % (i, validate_acc))
xs, ys = minst.train.next_batch(BATCH_SIZE)
sess.run(train_op,feed_dict={x:xs, y_:ys})
#訓(xùn)練結(jié)束后 在測試數(shù)據(jù)上檢測神經(jīng)網(wǎng)絡(luò)模型的最終正確率
test_acc=sess.run(accuracy,feed_dict=test_feed)
print("After %d traing step(s), validation accuracy use average model is %g" % (TRAINING_STEPS, test_acc))
def main(argv=None):
minst = input_data.read_data_sets("/path/to/Minst_Data", one_hot=True)
print("trainning dataset ", minst.train.num_examples)
print("trainning data label ", minst.train.labels[0])
train(minst)
if __name__ == '__main__':
tf.app.run()
識別的準(zhǔn)確率能達(dá)到 98.5%

Paste_Image.png