#python #tensorflow #keras
Вопрос:
Я пытаюсь построить модель САЙМОНА на основе этого примера(ссылка). Ниже показано, как я создаю 2 модели: (1) кодер предложений (кодер предложений), который поступает в (2) кодер документов (docModel).
Когда я пытаюсь соответствовать, я получаю следующую ошибку.
Входной тензор должен быть ранга 3, 4 или 5, но равен 2.
Мой ввод имеет форму (3003, 30, 28), т. Е. (образцы,отправленная максимальная длина, один горячий кодированный символ).
maxLength = 30
max_cells = 3003
charMap = {'a': 1,'b': 2, 'c': 3,'d': 4,'e': 5,'f': 6,
'g': 7,'h': 8, 'i': 9, 'j': 10, 'k': 11,
'l': 12,'m': 13, 'n': 14, 'o': 15, 'p': 16,
'q': 17,'r': 18, 's': 19, 't': 20, 'u': 21,
'v': 22,'w': 23, 'x': 24, 'y': 25, 'z': 26,
' ': 27}
maxChars = len(charMap) 1
x_train = np.zeros((max_cells, maxLength, maxChars), dtype='int32')
y_train = np.zeros((max_cells, 3), dtype='int32')
def buildSentModel(sentModelInput):
layer = Conv1D(10,
5,
padding='valid',
activation='relu',
strides=1)(sentModelInput)
layer = Bidirectional(LSTM(units=12, return_sequences=False))(layer)
return Model(input=sentModelInput, output=layer)
def buildDocModel(sentModel, docInput):
layer = TimeDistributed(sentModel)(docInput)
#layer = Flatten()(layer)
layer = Dense(3, activation='sigmoid')(layer)
return Model(input=docInput, output=layer)
sentModelInput = Input(shape=(30,28), dtype='float32')
sentModel = buildSentModel(sentModelInput);
docModel = buildDocModel(sentModel, sentModelInput);
docModel.compile(optimizer="adam", loss='categorical_crossentropy', metrics=['categorical_accuracy'])
docModel.fit(x_train, y_train, steps_per_epoch=20,epochs=100, shuffle=True)
Вот в чем вся ошибка:
Файл «C:tempSimonTempSimonNames.py», строка 107, в model = buildDocModel(sentModel, sentModelInput);
Файл «C:tempSimonTempSimonNames.py», строка 94, в слое buildDocModel = Распределенное по времени(отправленная модель)(ввод документа)
Файл «C:ProgramDataAnaconda3libsite-packageskerasbackendtensorflow_backend.py», строка 75, в функции возврата symbolic_fn_wrapper(*args, **kwargs)
Файл «C:ProgramDataAnaconda3libsite-packageskerasenginebase_layer.py», строка 489, в выводе вызова = самостоятельный вызов(входы, **квт)
Файл «C:ProgramDataAnaconda3libsite-packageskeraslayerswrappers.py», строка 250, в вызове y = self.layer.вызов(входы, **кварги)
Файл «C:ProgramDataAnaconda3libsite-packageskerasenginenetwork.py», строка 583, в вызове output_tensors, _, _ = self.run_internal_graph(входы, маски)
Файл «C:ProgramDataAnaconda3libsite-packageskerasenginenetwork.py», строка 740, в слое run_internal_graph.вызов(computed_tensor, **кварги))
Файл «C:ProgramDataAnaconda3libsite-packageskeraslayersconvolutional.py», строка 163, в вызове dilation_rate=self.dilation_rate[0])
Файл «C:ProgramDataAnaconda3libsite-packageskerasbackendtensorflow_backend.py», строка 3671, в 1d **кваргах)
Файл «C:ProgramDataAnaconda3libsite-packagestensorflow_corepythonopsnn_ops.py», строка 917, в свертке имя_в2=имя)
Файл «C:ProgramDataAnaconda3libsite-packagestensorflow_corepythonopsnn_ops.py», строка 969, в convolution_internal «Входной тензор должен иметь ранг 3, 4 или 5, но был {}.».формат(n 2))
Ошибка значения: Входной тензор должен иметь ранг 3, 4 или 5, но был равен 2.
Буду признателен за любую помощь. Спасибо!
Ответ №1:
Вы, кажется, перепутали некоторые из ваших переменных и форм.
Согласно вашему коду, sent_model-это модель, получающая предложение, состоящее до 30 символов, следовательно, форма ввода (30, 28) (хотя мне интересно, почему в ваших предложениях только до 30 символов, это, кажется, не так много).
Теперь ваша doc_model должна применять sent_model к каждому предложению документа. Таким образом, форма ввода вашего документа должна быть (num_sentences_per_doc, 30, 28).
Теперь к проблеме: вы передаете один и тот же входной слой обеим моделям. Это не имеет никакого смысла, так как две модели должны иметь разные входные слои. Форма sentModelInput (единственный определенный вами входной слой) соответствует форме ввода для вашей модели sent_model, но имеет слишком мало размеров для вашей модели doc_model, поскольку для этой модели требуется форма (num_sentences_per_doc, 30, 28), как описано ранее. Таким образом, решение всего этого будет заключаться в следующем:
- Используйте два разных входных слоя для обеих моделей.
- Убедитесь, что входные слои действительно имеют правильную форму.
Этот измененный код должен дать вам представление о том, что вам нужно сделать. Если вы хотите использовать подход сглаживания, который в настоящее время прокомментирован, в ваших документах должно быть фиксированное количество предложений, поэтому я буду называть это num_sents_per_doc. Если вы хотите построить модель, которая может обрабатывать документы переменной длины, то вам нужно установить форму ввода DocInput на (Нет, 30, 28) и использовать структуру нейронной сети, которая может обрабатывать этот ввод переменной длины.
def buildSentModel():
sentModelInput = Input(shape=(30,28), dtype='float32')
layer = Conv1D(10,
5,
padding='valid',
activation='relu',
strides=1)(sentModelInput)
layer = Bidirectional(LSTM(units=12, return_sequences=False))(layer)
return Model(input=sentModelInput, output=layer)
def buildDocModel():
docInput = Input(shape=(num_sents_per_doc, 30,28), dtype='float32')
layer = TimeDistributed(sentModel)(docInput)
#layer = Flatten()(layer)
layer = Dense(3, activation='sigmoid')(layer)
return Model(input=docInput, output=layer)
sentModel = buildSentModel();
docModel = buildDocModel(sentModel);
docModel.compile(optimizer="adam", loss='categorical_crossentropy', metrics=['categorical_accuracy'])
docModel.fit(x_train, y_train, steps_per_epoch=20,epochs=100, shuffle=True)
Комментарии:
1. Марк, я не могу отблагодарить тебя за то, что ты все это для меня разрушил! Ваш код сработал для меня, но мне пришлось внести небольшое изменение. Мне пришлось сгладить() перед плотным слоем в buildDocModel. Он жаловался: «Ожидалось, что dense_4 будет иметь 4 измерения, но получил массив с формой (3003, 3)». Не будет ли распределенный по времени слой разбивать ось 1 (предложения) и передавать только 2D в плотный? Почему он должен ожидать 4D?
2. Не за что! Поэтому я думаю, что распределенный по времени слой просто применяет модель отправки к каждому из 3003 предложений. Это означает, что, если входные данные для вашей модели builddoc имеют форму (3003, 30, 28), отправленная модель применяется к каждому из 3003 тензоров формы (30, 28). Вывод вашей модели отправки теперь имеет форму (12,), насколько я могу видеть, поэтому вывод вашего распределенного по времени слоя должен быть (3003, 12). Если вы теперь используете свой плотный слой на этом, он будет применен к каждому из 3003 12-мерных тензоров по отдельности. Это приводит к выходной форме (3003, 3) (поскольку слой
3. имеет 3 нейрона). Вероятно, это не то, что вы хотите, поэтому вместо этого вы используете слой выравнивания, который в основном просто превращает двумерный вывод распределенного по времени слоя формы (3003, 12) в 1-D тензор формы 3003*12 = (36036,), к которому затем можно применить плотный слой (в результате чего получается окончательная форма (3,). Помогает ли это вам ответить на ваш вопрос?
4. хорошо, это действительно полезно. Могу я, пожалуйста, задать еще один быстрый вопрос? При использовании двунаправленной оболочки вокруг LSTM это то же самое, что при использовании прямого LSTM обратного LSTM конкатенационного слоя?
5. Похоже на то, по крайней мере, это то, что я вижу, если посмотрю документацию: tensorflow.org/api_docs/python/tf/keras/layers/Bidirectional Могут быть различия, если вы зададите некоторые другие параметры, например, merge_mode или укажите другой backwards_layer, но если вы этого не сделаете, то это должно быть то же самое.