InvalidArgumentError (see above for traceback): You must feed a value for placeholder tensor '...

1.bug背景

InvalidArgumentError (see above for traceback): You must feed a value for placeholder tensor ‘input_1’ with dtype float and shape
[?,256,1,1]

在訓練model的過程中,我使用Input(shape=(channel,H,W))輸入了一個tensor後,想要將其轉換爲np.array格式以便我能使用一些numpy特有的函數,在查閱了網上的資料後決定採用eval函數實現我的夢想。但是實現過程卻報了上面的bug,具體原因是什麼呢?原因是我沒有爲placeholder tensor實例化,也就是說這個placeholder,他是個戰力五的渣渣,想用它需要我們feed(投喂)它,具體怎麼個投喂法,且聽我慢慢道來。

2.解決之路

首先,我們需要大體上去了解一下我們的tensor都有些什麼貨色,爲什麼別人用eval函數能做到的我們卻做不到。

tensor的種類:(constant、placeholder、Variable)

(1)constant:(常量)
通過constant方法創建,其是計算圖(Computational Graph)中的起始節點,是傳入數據。 創建過程

   import tensorflow as tf
   cons1 = tf.constant([1, 2, 3], shape=[2, 3])

別人用eval函數時候怎麼用的,人家是拿這種constant類型的tensor給你演示的,你比如說對上面的cons1,我們可以執行下面的操作:

   sess=tf.Session()
   cons1 = cons1.eval(session=sess)
   #然後輸出type(cons1)果然成功變成<class 'numpy.ndarray'>

但是我咋一試就報了標題的bug呢??因爲我用的不是這個常量,我用的是在模型中的placeholder,也就是下面我要說的這個。

(2) placeholder:(佔位符)
說白了就是佔着坑兒,和我們平時去佔座似的,我一個個都佔好座位了,但是上面沒有人就只有個你口頭上的話(“這座兒是我的哈”),專業一些講的話更類似是形參,它不能像constant一樣直接使用,需要用戶傳遞常數值,也就是feed。具體怎麼feed,我最後講,我們先有始有終的把tensor類型全部記錄下來。

(3)Variable(變量)
  Vatiable是tensorflow的變量節點,通過Variable(注:V大寫)方法創建,並且需要傳遞初始值。在使用前需要通過tensorflow的初始化方法進行初始化。

3.placeholder咋整?

我們用Input函數(也就是keras.layers.Input)輸入進來的tensor,它就是個佔位符,和我們用X = tf.placeholder(dtype=tf.float32, shape=[144, 10], name=‘X’)創建的東西一樣,都是佔着坑沒東西的傢伙,你對這種傢伙用eval函數操作想讓它變成numpy的nd.array,它不現實,就好比你一個人對着一堆空桌子沒人坐在上面,讓他們彼此換座位似的,你得先整點兒人上去。

於是乎,我經過一番思考,我覺着反正佔位符它就是爲了佔位置,它本身是沒有值的,只是爲了撐起來模型的整體形狀而存在,那我們不妨直接給他賦值全0或別的什麼的,這樣它不就有值了,而且我的值並不影響它撐起模型的作用。說幹就幹:

    zero_array = np.zeros(x.shape)#這兒是爲了feed x讓它能轉爲numpy
    sess=tf.Session()
    x = x.eval(session=sess,feed_dict={x:zero_array})  

通過上面這段代碼,我們就可以成功把一個tensor轉換成numpy的nd.array了,如果想要轉換回tensor,可以用:

    x =tf.convert_to_tensor(x)

寫到這兒,tensor和numpy的互相轉化結束了,但是我還想說一句忠告,如果你是從我這篇關於moveaxis的文章移步到這裏的話,我想先問您一下是否在和我走同樣的路

我用的是keras訓練模型,但是我想將channel_last轉換爲channel_first,轉換後我在拼接Concatenate和調整大小keras.backend.resize_images遇到了維度對接不上的問題。因爲keras.backend.resize_images這個函數只能用於channel_last的tensor,所以我的想法是先把它轉換爲channel_last後調整完大小再轉回去。

調了一整天的我發現,這樣的確可以把維度調順,但是有一個問題就是,我們在使用tf的函數過程中,返回值是tf.tensor,而我們若用keras訓練模型的話,我們應該輸入keras.tensor,這個問題在我查的最多的方法中告訴我可以用Lambda層包住tf的函數,但是但是但是!!!我這個過程中有一步的函數tf.convert_to_tensor(x)這個函數是爲了把numpy轉換成tensor的,如果用Lambda層包住,而Lambda層又需要我們輸入進入一個tensor,就成了那個程序員找工作的故事了(“我想要找工作!”、“那你得有工作經驗”,“我不工作哪兒來的工作經驗?”,“但是你得先有工作經驗才能找到這份工作!!“)。

所以說了這半天,我想說的是如果你用的是tensorflow搭建模型,上面這種轉換應該不會有啥影響,但是如果你用keras搭建,你最後輸入模型的時候必然還會出現這種bug(keras.tensor and tf.tensor)。如果你是因爲*keras.backend.resize_images只能一種格式而鬱悶,我這兒有一個藥方(tensor調整大小篇),但是如果是別的,我建議你別這樣換來換去的,最後維度對上了格式不對的吐血感受,誰看誰知道。。

發佈了15 篇原創文章 · 獲贊 1 · 訪問量 6769
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章