日常填坑之keras.backend.ctc_batch_cost參數問題

InvalidArgumentError sequence_length(0) <=30錯誤

下面的代碼是在網上絕大多數文章給出的關於k.ctc_batch_cost()函數的使用代碼

def ctc_lambda_func(args):
    y_pred, labels, input_length, label_length = args
    # the 2 is critical here since the first couple outputs of the RNN
    # tend to be garbage:    
    y_pred = y_pred[:, 2:, :]
    return K.ctc_batch_cost(labels, y_pred, input_length, label_length)

可以注意到有一句:y_pred = y_pred[:, 2:, :],這裏把y_pred 的第二維數據去掉了兩列,說人話:把送進lstm序列的step減了2步。後來偶然在一篇文章中有提到說這裏之所以減2是因爲在將feature送入keras的lstm時自動少了2維,所以這裏就寫成這樣了。估計是之前老版本的bug,現在的新版本已經修復了。如果依然按照上面的寫法,會得到如下錯誤:

InvalidArgumentError sequence_length(0) <=30

'<='後面的數值 = 你cnn最後的輸出維度 - 2。這個錯誤我找了很久,一直不明白30哪裏來的,後來一行行的檢查代碼是發現了這裏很可疑,於是改成如下形式錯誤解決。

def ctc_lambda_func(args):
    y_pred, labels, input_length, label_length = args    
    return K.ctc_batch_cost(labels, y_pred, input_length, label_length)

訓練時出現ctc_loss_calculator.cc:144] No valid path found或loss: inf錯誤

  • 熟悉CTC算法的話,這個提示應該是ctc沒找到有效路徑。既然是沒找到有效路徑,那肯定是label和input之間哪個地方又出問題了!和input相關的錯誤已經解決了,那麼肯定就是label的問題了。再看ctc_batch_cost的四個參數,labels和label_length這兩個地方有可疑。對於ctc_batch_cost()的參數,labels需要one-hot編碼,形狀:[batch, max_labelLength],其中max_labelLength指預測的最大字符長度;label_length就是每個label中的字符長度了,受之前tf.ctc_loss的影響把這裏都設置成了最大長度,所以報錯。
  • 對於參數labels而言,max_labelLength是能預測的最大字符長度。這個值與送lstm的featue的第二維,即特徵序列的max_step有關,表面上看只要max_labelLength<max_step即可,但是如果小的不多依然會出現上述錯誤。至於到底要小多少,還得從ctc算法裏找,由於ctc算法在標籤中的每個字符後都加了一個空格,所以應該把這個長度考慮進去,所以有 max_labelLength < max_step//2。沒仔細研究keras裏ctc_batch_cost()函數的實現細節,上面是我的猜測。如果有很明確的答案,還請麻煩告訴我一聲,謝了先!
    錯誤代碼:
batch_label_length = np.ones(batch_size) * max_labelLength

正確打開方式:

batch_x, batch_y = [], []
batch_input_length = np.ones(batch_size) * (max_img_weigth//8)
batch_label_length = []
for j in range(i, i + batch_size):
    x, y = self.get_img_data(index_all[j])
    batch_x.append(x)
    batch_y.append(y)
    batch_label_length.append(self.label_length[j])

最後附一張我的crnn的模型圖:
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章