淺談Tensorflow加載Vgg預(yù)訓(xùn)練模型的幾個(gè)注意事項(xiàng)
寫這個(gè)博客的關(guān)鍵Bug: Value passed to parameter 'input' has DataType uint8 not in list of allowed values: float16, bfloat16, float32, float64。本博客將圍繞 加載圖片 和 保存圖片到本地 來詳細(xì)解釋和解決上述的Bug及其引出來的一系列Bug。
加載圖片
首先,造成上述Bug的代碼如下所示
image_path = "data/test.jpg" # 本地的測試圖片 image_raw = tf.gfile.GFile(image_path, 'rb').read() # 一定要tf.float(),否則會(huì)報(bào)錯(cuò) image_decoded = tf.image.decode_jpeg(image_raw) # 擴(kuò)展圖片的維度,從三維變成四維,符合Vgg19的輸入接口 image_expand_dim = tf.expand_dims(image_decoded, 0) # 定義Vgg19模型 vgg19 = VGG19(data_path) net = vgg19.feed_forward(image_expand_dim, 'vgg19') print(net)
上述代碼是加載Vgg19預(yù)訓(xùn)練模型,并傳入圖片得到所有層的特征圖,具體的代碼實(shí)現(xiàn)和原理講解可參考我的另一篇博客:Tensorflow加載Vgg預(yù)訓(xùn)練模型。那么,為什么代碼會(huì)出現(xiàn): Value passed to parameter 'input' has DataType uint8 not in list of allowed values: float16, bfloat16, float32, float64,這個(gè)Bug呢?
這句英文翻譯過來是指:傳遞的值類型是uint8,但是接受的參數(shù)類型必須是float的那幾種。故原因就是傳入值的數(shù)據(jù)類型錯(cuò)了,那么如何解決這個(gè)Bug呢,很簡單
image_path = "data/test.jpg" # 本地的測試圖片 image_raw = tf.gfile.GFile(image_path, 'rb').read() # 一定要tf.float(),否則會(huì)報(bào)錯(cuò) image_decoded = tf.to_float(tf.image.decode_jpeg(image_raw)) # 擴(kuò)展圖片的維度,從三維變成四維,符合Vgg19的輸入接口 image_expand_dim = tf.expand_dims(image_decoded, 0) # 定義Vgg19模型 vgg19 = VGG19(data_path) net = vgg19.feed_forward(image_expand_dim, 'vgg19') print(net)
這兩個(gè)代碼塊唯一的變動(dòng)就是:image_decoded結(jié)果在輸出前加了一個(gè)tf.float(),將其轉(zhuǎn)換為float類型。
在tensorflow API中,tf.image.decode_jpeg()默認(rèn)讀取的圖片數(shù)據(jù)格式為unit8,而不是float。uint8數(shù)據(jù)的范圍在(0, 255)中,正好符合圖片的像素范圍(0, 255)。但是,保存在本地的Vgg19預(yù)訓(xùn)練模型的數(shù)據(jù)接口為float,所以才造成了本文開頭的Bug。
這里還要提一點(diǎn),若是使用PIL的方法來加載圖片,則不會(huì)出現(xiàn)上述的Bug,因?yàn)橥ㄟ^PIL得到的圖片格式是float,而不是uint8,故不需要轉(zhuǎn)換。
很多同學(xué)可能會(huì)疑惑,若是強(qiáng)行改變了原圖片的數(shù)據(jù)格式,從uint8類型轉(zhuǎn)變成float,會(huì)不會(huì)導(dǎo)致數(shù)據(jù)改變或者出錯(cuò)?故我做了下面這個(gè)實(shí)驗(yàn):
image_path = "data/3.jpg" image_raw = tf.gfile.GFile(image_path, 'rb').read() image_unit8 = tf.image.decode_jpeg(image_raw) image_float = tf.to_float(image_unit8) with tf.Session() as sess: image_unit8_, image_float_ = sess.run([image_unit8, image_float]) print("image_unit8_", image_unit8_) print("image_float_ ", image_float_ )
代碼結(jié)果如下:
image_unit8_ [180, 192, 204], [183, 195, 207], [186, 198, 210], ..., [191, 205, 218], [191, 205, 218], [190, 204, 217]], image_float_ [180., 192., 204.], [183., 195., 207.], [186., 198., 210.], ..., [191., 205., 218.], [191., 205., 218.], [190., 204., 217.]],
可以看到,數(shù)據(jù)根本沒有變化,只是后面多加了個(gè)小數(shù)點(diǎn),變得只有類型,而沒有強(qiáng)制改變值,故同學(xué)們不需要過度擔(dān)心。
保存圖片到本地
在加載圖片的時(shí)候,為了使用保存在本地的預(yù)訓(xùn)練Vgg19模型,我們需要將讀取的圖片由uint8格式轉(zhuǎn)換成float格式。那若是我們想將已經(jīng)轉(zhuǎn)換為float格式的圖片再保存到本地,該怎么做呢?
首先,我們根據(jù)上述的文字的意思讀取圖片,并且將其轉(zhuǎn)換為float格式,在將讀取的圖片再次保存到本地之前,我們首先可視化一下轉(zhuǎn)換格式后的圖片,代碼如下:
import tensorflow as tf from matplotlib import pyplot as plt image_path = "data/boat.jpg" image_raw = tf.gfile.GFile(image_path, 'rb').read() image_decoded = tf.image.decode_jpeg(image_raw) image_decoded = tf.to_float(image_decoded) with tf.Session() as sess: image_decoded_ = sess.run(image_decoded) plt.imshow(image_decoded_) plt.show()
生成的圖片如下圖所示:
左邊是原圖,右邊是轉(zhuǎn)換為float格式的圖片,可見將圖片轉(zhuǎn)換為float格式,雖然數(shù)值沒有造成太大影響,但是若想將圖片保存到本地就會(huì)出現(xiàn)問題。
說了這么多,只為了說一點(diǎn),在保存圖片到本地之前,需要將其格式從float轉(zhuǎn)回uint8,否則會(huì)造成一系列錯(cuò)誤:圖片顯示異常,API報(bào)錯(cuò)等。正確的保存代碼如下:
save_path = "data/boat_copy.jpg" image_uint = tf.cast(image_decoded, tf.uint8) with tf.Session() as sess: with open(save_path, 'wb') as img: image_saved = sess.run(tf.image.encode_jpeg(image_uint)) img.write(image_saved)
其中只有一句話最關(guān)鍵,即 tf.cast(image_decoded, tf.uint8)。
以上這篇淺談Tensorflow加載Vgg預(yù)訓(xùn)練模型的幾個(gè)注意事項(xiàng)就是小編分享給大家的全部內(nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
利用python實(shí)現(xiàn)命令行有道詞典的方法示例
平常都是用終端敲, 有時(shí)候不會(huì)的詞語也懶得打開詞典了,干脆搞了個(gè)簡單的查詞命令。下面這篇文章主要給大家介紹了利用python實(shí)現(xiàn)命令行有道詞典的方法示例,需要的朋友可以參考借鑒,一起來看看吧。2017-01-01python實(shí)現(xiàn)音樂播放和下載小程序功能
這篇文章主要介紹了python實(shí)現(xiàn)音樂播放和下載小程序功能,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-04-04python編程PyQt5創(chuàng)建按鈕及觸發(fā)點(diǎn)擊事件示例解析
這篇文章主要為大家介紹了python編程使用PyQt5如何創(chuàng)建按鈕及觸發(fā)點(diǎn)擊事件的示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步2021-10-10Python Request類源碼實(shí)現(xiàn)方法及原理解析
這篇文章主要介紹了Python Request類源碼實(shí)現(xiàn)方法及原理解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-08-08Python利用matplotlib實(shí)現(xiàn)餅圖繪制
Pyplot作為Matplotlib的子庫,提供了和MATLAB差不多的繪圖API。因此Pyplot作為常用的繪圖模塊,能很方便讓用戶繪制2D圖表。本文將為大家介紹如何利用Matplotlib繪制餅圖,感興趣的小伙伴可以了解一下2021-12-12python3.6 如何將list存入txt后再讀出list的方法
這篇文章主要介紹了python3.6 如何將list存入txt后再讀出list的方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-07-07