ValueError: ожидаемый dense_22 должен иметь форму (None, 37), но получил массив с формой (1000, 2)

#keras #lstm #question-answering

#keras #lstm #nlp-вопрос-ответ

Вопрос:

В настоящее время я работаю над системой ответов на вопросы. Я создаю синтетический набор данных, который содержит несколько слов в ответах. Но ответы не являются частью данного контекста.

Первоначально я планирую протестировать его с использованием модели, основанной на глубоком обучении. Но у меня есть некоторые проблемы с построением модели. Вот как я векторизовал данные.

 def vectorize(data, word2idx, story_maxlen, question_maxlen, answer_maxlen):
    """ Create the story and question vectors and the label """
    Xs, Xq, Y = [], [], []
    for story, question, answer in data:
        xs = [word2idx[word] for word in story]
        xq = [word2idx[word] for word in question]
        y = [word2idx[word] for word in answer]
        #y = np.zeros(len(word2idx)   1)
        #y[word2idx[answer]] = 1
        Xs.append(xs)
        Xq.append(xq)
        Y.append(y)
    return (pad_sequences(Xs, maxlen=story_maxlen), 
            pad_sequences(Xq, maxlen=question_maxlen),
            pad_sequences(Y, maxlen=answer_maxlen))
            #np.array(Y))
 

ниже показано, как я создаю модель.

     # story encoder. Output dim: (None, story_maxlen, EMBED_HIDDEN_SIZE)
story_encoder = Sequential()
story_encoder.add(Embedding(input_dim=vocab_size, 
                              output_dim=EMBED_HIDDEN_SIZE,
                              input_length=story_maxlen))
story_encoder.add(Dropout(0.3))

# question encoder. Output dim: (None, question_maxlen, EMBED_HIDDEN_SIZE)
question_encoder = Sequential()
question_encoder.add(Embedding(input_dim=vocab_size,
                               output_dim=EMBED_HIDDEN_SIZE,
                               input_length=question_maxlen))
question_encoder.add(Dropout(0.3))

# episodic memory (facts): story * question
# Output dim: (None, question_maxlen, story_maxlen)
facts_encoder = Sequential()

facts_encoder.add(Merge([story_encoder, question_encoder], 
                        mode="dot", dot_axes=[2, 2]))
facts_encoder.add(Permute((2, 1)))                        

## combine response and question vectors and do logistic regression
answer = Sequential()
answer.add(Merge([facts_encoder, question_encoder], 
                 mode="concat", concat_axis=-1))
answer.add(LSTM(LSTM_OUTPUT_SIZE, return_sequences=True))
answer.add(Dropout(0.3))
answer.add(Flatten())
answer.add(Dense(vocab_size,activation= "softmax"))


answer.compile(optimizer="rmsprop", loss="categorical_crossentropy",
               metrics=["accuracy"])

answer.fit([Xs_train, Xq_train], Y_train, 
           batch_size=BATCH_SIZE, nb_epoch=NBR_EPOCHS,
           validation_data=([Xs_test, Xq_test], Y_test))
 

и это краткое изложение модели

    _________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
merge_46 (Merge)             (None, 5, 616)            0         
_________________________________________________________________
lstm_23 (LSTM)               (None, 5, 32)             83072     
_________________________________________________________________
dropout_69 (Dropout)         (None, 5, 32)             0         
_________________________________________________________________
flatten_9 (Flatten)          (None, 160)               0         
_________________________________________________________________
dense_22 (Dense)             (None, 37)                5957      
=================================================================
Total params: 93,765.0
Trainable params: 93,765.0
Non-trainable params: 0.0
_________________________________________________________________
 

Это выдает следующую ошибку.

 ValueError: Error when checking model target: expected dense_22 to have shape (None, 37) but got array with shape (1000, 2)
 

Я думаю, что ошибка связана с Y_train, Y_test . Я должен закодировать их в категориальные значения, и ответы будут не фрагментами текста, а последовательными. Я не знаю, что / как это сделать.
как я могу это исправить? есть идеи?

Редактировать:

Когда я использую sparse_categorical_crossentropy в потере и изменяю форму (2,-1); answer.summary()

 _________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
merge_94 (Merge)             (None, 5, 616)            0         
_________________________________________________________________
lstm_65 (LSTM)               (None, 5, 32)             83072     
_________________________________________________________________
dropout_139 (Dropout)        (None, 5, 32)             0         
_________________________________________________________________
reshape_22 (Reshape)         (None, 2, 80)             0         
_________________________________________________________________
dense_44 (Dense)             (None, 2, 37)             2997      
=================================================================
Total params: 90,805.0
Trainable params: 90,805.0
Non-trainable params: 0.0
_________________________________________________________________
 

ПРАВКА2:
Модель после изменений

 # story encoder. Output dim: (None, story_maxlen, EMBED_HIDDEN_SIZE)
story_encoder = Sequential()
story_encoder.add(Embedding(input_dim=vocab_size, 
                              output_dim=EMBED_HIDDEN_SIZE,
                              input_length=story_maxlen))
story_encoder.add(Dropout(0.3))

# question encoder. Output dim: (None, question_maxlen, EMBED_HIDDEN_SIZE)
question_encoder = Sequential()
question_encoder.add(Embedding(input_dim=vocab_size,
                               output_dim=EMBED_HIDDEN_SIZE,
                               input_length=question_maxlen))
question_encoder.add(Dropout(0.3))

# episodic memory (facts): story * question
# Output dim: (None, question_maxlen, story_maxlen)
facts_encoder = Sequential()

facts_encoder.add(Merge([story_encoder, question_encoder], 
                        mode="dot", dot_axes=[2, 2]))
facts_encoder.add(Permute((2, 1)))                        

## combine response and question vectors and do logistic regression
## combine response and question vectors and do logistic regression
answer = Sequential()
answer.add(Merge([facts_encoder, question_encoder], 
                 mode="concat", concat_axis=-1))
answer.add(LSTM(LSTM_OUTPUT_SIZE, return_sequences=True))
answer.add(Dropout(0.3))
#answer.add(Flatten())
answer.add(keras.layers.Reshape((2, -1)))    
answer.add(Dense(vocab_size,activation= "softmax"))

answer.compile(optimizer="rmsprop", loss="sparse_categorical_crossentropy",
               metrics=["accuracy"])

answer.fit([Xs_train, Xq_train], Y_train, 
           batch_size=BATCH_SIZE, nb_epoch=NBR_EPOCHS,
           validation_data=([Xs_test, Xq_test], Y_test))
 

Он по-прежнему выдает

 ValueError: Error when checking model target: expected dense_46 to have 3 dimensions, but got array with shape (1000, 2)
 

Ответ №1:

Насколько я понимаю — Y_train, Y_test состоят из индексов (а не однонаправленных векторов). Если это так — измените потерю на sparse_categorical_entropy:

 answer.compile(optimizer="rmsprop", loss="sparse_categorical_crossentropy",
               metrics=["accuracy"])
 

Насколько я понимаю — Y_train, Y_test имеют размер последовательности. И длина вопросов (5) не равна длине ответов (2). Это измерение удаляется с помощью Flatten() . Попробуйте заменить Flatten() на Reshape() :

 # answer.add(Flatten())
answer.add(tf.keras.layers.Reshape((2, -1)))    
 

Комментарии:

1. когда я меняю функцию потерь, я получаю ValueError: Ошибка при проверке цели модели: ожидаемый dense_22 должен иметь форму (None, 1), но получил массив с формой (1000, 2). В тесте 1000 выборок, и каждый ответ содержит не более 2 слов. @Andrey

2. Спасибо @Andrey. Как только я удалю слой Flatten(), добавьте Reshape(2,-1); это выдает ошибку ValueError: Ошибка при проверке цели модели: ожидаемая плотность dense_33 будет иметь 3 измерения, но есть массив с формой (1000, 2). vocab_size= 37 story_maxlen= 552 вопрос_макслен= 5 ответ_макслен = 2 история—> (1000, 552) вопрос -> (1000, 5) форма ответа -> (1000, 2)

3. Я обновил вопрос и добавил answer.summary() после этих изменений. @Андрей

4. @programming123 вы изменили loss на sparse_categorical_entropy ?