Tensorflow编程基础之Mnist手写识别实验+关于cross_entropy的理解
好久沒有靜下心來寫點(diǎn)東西了,最近好像又回到了高中時候的狀態(tài),休息不好,無法全心學(xué)習(xí),惡性循環(huán),現(xiàn)在終于調(diào)整的好一點(diǎn)了,聽著純音樂突然非常傷感,那些曾經(jīng)快樂的大學(xué)時光啊,突然又慢慢的一下子出現(xiàn)在了眼前,不知道我大學(xué)的那些小伙伴們現(xiàn)在都怎么樣了,考研的剛剛希望他考上,實(shí)習(xí)的菜頭希望他早日脫離苦海,小瑞哥希望他早日出成果,范爺熊健研究生一定要過的開心啊!天哥也哥早日結(jié)婚領(lǐng)證!那些回不去的曾經(jīng)的快樂的時光,你們都還好嗎!
?
最近開始接觸Tensorflow,可能是論文里用的是這個框架吧,其實(shí)我還是覺得pytorch更方便好用一些,仔細(xì)讀了最簡單的Mnist手寫識別程序,覺得大同小異,關(guān)鍵要理解Tensorflow的思想,文末就寫一下自己看交叉熵的感悟,絮叨了這么多開始寫點(diǎn)代碼吧!?
2 # -*- coding: utf-8 -*-""" 3 Created on Sun Nov 11 16:14:38 2018 4 5 @author: Yang 6 """ 7 8 import tensorflow as tf 9 from tensorflow.examples.tutorials.mnist import input_data 10 11 mnist = input_data.read_data_sets("/MNIST_data",one_hot=True) #從input_data中讀取數(shù)據(jù)集,使用one_hot編碼 12 13 import pylab #畫圖模塊 14 15 tf.reset_default_graph()#重置一下圖 圖代表了一個運(yùn)算過程,包含了許多Variable和op,如果不重置一下圖的話,可能會因為某些工具重復(fù)調(diào)用變量而報錯 16 17 x = tf.placeholder(tf.float32,[None,784])#占位符,方便用feed_dict進(jìn)行注入操作 18 y = tf.placeholder(tf.float32,[None,10])#占位符,方便用feed_dict進(jìn)行注入操作
20 21 W = tf.Variable(tf.random_normal([784,10]))#要學(xué)習(xí)的參數(shù)統(tǒng)一用Variable來定義,這樣方便進(jìn)行調(diào)整更新 22 b = tf.Variable(tf.zeros([10])) 23 24 25 #construct the model 26 pred = tf.nn.softmax(tf.matmul(x,W) + b) #前向的計算過程 就這一句沒錯,就這一句,一個簡單的函數(shù)來實(shí)現(xiàn)分類! 27 28 cost = tf.reduce_mean(-tf.reduce_sum(y*tf.log(pred),reduction_indices=1))#計算損失的過程,cost reduction_indices=1代表了按照行進(jìn)行求和,這其實(shí)是人為實(shí)現(xiàn)的cross_entropy 29 30 learning_rate = 0.01#定義學(xué)習(xí)率 31 32 optimizer = tf.train.GradientDescentOptimizer(learning_rate).minimize(cost) #定義優(yōu)化函數(shù),利用GradienDescent來讓cost最小化 33 34 #set parameters about thee model 35 training_epoch = 25 #訓(xùn)練迭代次數(shù) epoch 36 batch_size = 100 #每次訓(xùn)練用多少的batch_size數(shù)據(jù) 37 display_step = 1 38 saver = tf.train.Saver() #創(chuàng)建一個用于保存模型的saver 39 model_path = "log/kerwinsmodel.ckpt" #模型保存的路徑 40 41 #start the session start a session 開始一個會話,所有的變量只有在會話里才能流動起來,也就是定義的計算都是僅僅定義而已,只有session啟動了才真正的開始分配給GPU進(jìn)行計算 42 43 with tf.Session() as sess : 44 sess.run(tf.global_variables_initializer()) #先將所有的變量進(jìn)行初始化一下,個人認(rèn)為這就相當(dāng)于在圖里給各個變量上戶口! 45 46 for epoch in range(training_epoch): #大的epoch迭代 47 avg_cost = 0 48 total_batch = int(mnist.train.num_examples/batch_size)#計算總共有多少個epoch 49 print(total_batch) 50 for i in range(total_batch): #一個batch 一個batch的開始迭代! 51 batch_xs,batch_ys = mnist.train.next_batch(batch_size)#取一個batch出來 52 53 _,c = sess.run([optimizer,cost],feed_dict={x:batch_xs,y:batch_ys})#開始計算optimizer和cost,真正的計算正是從這里開始的!因為優(yōu)化得到的結(jié)果我們無所謂所以用_表示,c代表cost 54 55 avg_cost += c/ total_batch#這里我一開始沒想明白,為什么一開始就用total_epoch進(jìn)行相除?可能中間變量不準(zhǔn)也沒關(guān)系吧! 56 if (epoch +1 ) % display_step ==0: 57 print("Epoch:",'%04d' %(epoch+1),"cost=","{:.9f}".format(avg_cost)) #將每個epoch的loss和avg_cost輸出來 58 59 print("Finish!")#這樣訓(xùn)練就算結(jié)束了 60 61 correct_prediction = tf.equal(tf.argmax(pred,1),tf.argmax(y,1)) #利用當(dāng)前學(xué)得的參數(shù)進(jìn)行一個預(yù)測,判斷和label是否相同 62 accuracy = tf.reduce_mean(tf.cast(correct_prediction,tf.float32))#進(jìn)行精確度的判斷,tf.cast就指的是類型轉(zhuǎn)換函數(shù),reduce_mean就是求出這一個batch的平均 63 print("Accuracy:",accuracy.eval({x:mnist.test.images,y:mnist.test.labels}))#驗證精確度 #這里果然有一個feed_dict進(jìn)行注入!因為要不然沒有辦法進(jìn)行測試啊!數(shù)據(jù)從哪里來呢?mnist.test 64 65 save_path = saver.save(sess,model_path) #模型的保存路徑,將整個session保存下來,可以理解為將整個桌布包起來,菜肯定都在里面了 66 print("Model saved in file: %s" % save_path)#輸出模型保存的路徑 67 # 68 69 70 #讀取模型程序 71 72 print("Starting 2nd session...")#讀取模型 73 with tf.Session() as sess: 74 sess.run(tf.global_variables_initializer())#將所有的變量都初始化一遍 75 saver.restore(sess,model_path)#重載模型 76 77 #測試model 78 correct_prediction = tf.equal(tf.arg_max(pred,1),tf.argmax(y,1))#直接進(jìn)行計算 79 #計算準(zhǔn)確率 80 accuracy = tf.reduce_mean(tf.cast(correct_prediction,tf.float32)) 81 print("Accuracy:",accuracy.eval({x:mnist.test.images,y:mnist.test.labels}))#和剛才同樣的方法,都是在測試數(shù)據(jù)集上進(jìn)行計算精確度結(jié)果! 82 83 output = tf.argmax(pred,1) 將輸出的labels得到 84 batch_xs,batch_ys = mnist.train.next_batch(2)從batch_size里面取兩個 85 outputval,predv = sess.run([output,pred],feed_dict={x:batch_xs})計算輸出和預(yù)測! 86 print(outputval,predv,batch_ys) #將輸出的labels,整個預(yù)測的結(jié)果,和真實(shí)的labels全都輸出來 87 88 im = batch_xs[0] 89 im = im.reshape(-1,28) 90 pylab.imshow(im) 91 pylab.show() #測試一下 92 93 im = batch_xs[1] 94 im = im.reshape(-1,28) 95 pylab.imshow(im) 96 pylab.show() 97 98 99 100
?到這里,整個Mnist識別的實(shí)驗就做完了,可以看出其實(shí)不管是pytorch框架還是Tensorflow的框架,感覺在基礎(chǔ)的實(shí)現(xiàn)上都是大同小異的,Tensorflow果然在編程上更復(fù)雜一些,好像pytorch就是沒有那么多復(fù)雜繁瑣的工作,就好像是兩個畫家在作畫,比拼誰的實(shí)力更強(qiáng),但是確實(shí)兩個完全不同的繪畫順序,Tensorflow就像是畫家畫龍,整個龍都畫完了也沒有用,必須得點(diǎn)睛!而session就是龍的眼睛!但是pytorch就像是畫家將龍的每一部分都畫的生龍活虎,栩栩如生,畫完爪子它就已經(jīng)可以撓傷你了,哈哈哈,太形象了!
?
最后用一個小小的實(shí)驗解釋一下tensorflow里面該如何正確的用好Softmax和cross_entropy:
?
# -*- coding: utf-8 -*- """ Created on Mon Nov 12 20:04:10 2018@author: Yang """ import tensorflow as tflabels = [[0,0,1],[0,1,0]] logits = [[2,0.5,6],[0.1,0,3]]logits_scaled = tf.nn.softmax(logits) logits_scaled2 = tf.nn.softmax(logits_scaled)result1 = tf.nn.softmax_cross_entropy_with_logits(labels=labels,logits = logits)#直接用softmax_cross_entropy results2 = tf.nn.softmax_cross_entropy_with_logits(labels=labels,logits=logits_scaled)#softmax之后再用softmax_cross_entropy results3 = -tf.reduce_sum(labels*tf.log(logits_scaled),1)with tf.Session() as sess:print("softmax之后的結(jié)果scaled=" ,sess.run(logits_scaled))print("兩次softmax之后的結(jié)果:",sess.run(logits_scaled2))print("##############")print("直接用logits進(jìn)行softmax_cross_entropy:",sess.run(result1),"\n")print("softmax之后再用softmax_cross_entropy:",sess.run(results2),"\n")print("自己實(shí)現(xiàn)的cross_entropy用softmax之后的結(jié)果",sess.run(results3))結(jié)果是這樣的:
softmax之后的結(jié)果scaled= [[0.01791432 0.00399722 0.97808844]
??[0.04980332 0.04506391 0.90513283]]
兩次softmax之后的結(jié)果:
[[0.21747023 0.21446465 0.56806517]
[0.2300214 0.22893383 0.5410447 ]]
#####################################################
直接用logits進(jìn)行softmax_cross_entropy: [0.02215516 3.0996735 ]
softmax之后再用softmax_cross_entropy: [0.56551915 1.4743223 ]
自己實(shí)現(xiàn)的cross_entropy用softmax之后的結(jié)果 [0.02215518 3.0996735 ]
下面來解釋下為什么會有這樣的結(jié)果,softmax之前三個變量的求和明顯是大于1的,經(jīng)過了softmax之后求和的結(jié)果等于1了,變成了相對概率的形式,如果再進(jìn)行一次softmax你會發(fā)現(xiàn)概率明顯發(fā)生了較大的偏移,概率代表的label其實(shí)已經(jīng)不那么明顯了!所以兩次softmax很明顯是錯誤的結(jié)果!
再看下面cross_entropy的調(diào)用:
直接用logits進(jìn)行softmax_cross_entropy的計算第一個結(jié)果較小,因為它的數(shù)據(jù)和它的labels差異較小,數(shù)據(jù):[2,0.5,6]?而label:[0,0,1] 所以交叉熵較小,但是第二個數(shù)據(jù)和label的差異明顯就比較大,所以對應(yīng)它的交叉熵就比較大,所以直接用logtis數(shù)據(jù)帶入到softmax_crossentropy里面其實(shí)是正確的結(jié)果!
而下面就是將softmax的結(jié)果再帶入到softmax_cross_entropy里面去,很明顯后面的結(jié)果不如第一次的直觀,因為差異變小了很多,為什么會這樣,因為兩次softmax之后概率發(fā)生了偏移,差異化變小所以cross_entropy得結(jié)果就相應(yīng)的改變了!
可能會有讀者有疑問,那我如果已經(jīng)進(jìn)行了softmax,豈不是到了沒有損失函數(shù)可以用的尷尬地步了?錯,第三個結(jié)果告訴了我們答案,我們完全可以用自己實(shí)現(xiàn)的cross_entropy函數(shù)啊,不必非得調(diào)用現(xiàn)成的,就是一個-tf.reduce_sum(labels*tf.log(logits))就可以實(shí)現(xiàn)相同的結(jié)果了,可以發(fā)現(xiàn)第三個和第一個數(shù)據(jù)的結(jié)果都是相同的,不過一個調(diào)用了封裝,一個是自己實(shí)現(xiàn)的,完全一樣!
?
好啦,簡單的Tensorflow的介紹就結(jié)束了,如果您是Tensorflow框架的大牛,恰好看到了也不要笑話我寫的稚嫩,純粹是記錄,增強(qiáng)記憶,博你一笑!哈哈哈,這下女朋友知道我在干嘛了吧!
?
轉(zhuǎn)載于:https://www.cnblogs.com/kerwins-AC/p/9948841.html
總結(jié)
以上是生活随笔為你收集整理的Tensorflow编程基础之Mnist手写识别实验+关于cross_entropy的理解的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: UDS tester之Tdrm
- 下一篇: Tweak工程