Я тренирую предиктор следующего символа/слова LSTM в Keras и хочу включить его в проект iOS. Когда я конвертирую его в CoreML, выходная форма и значения не соответствуют моей исходной модели Keras.
Подводя итог моего вопроса:
Модель, которую я тренирую, имеет следующую компоновку:
model = Sequential()
model.add(LSTM(128, input_shape=(SEQUENCE_LENGTH, len(chars))))
model.add(Dense(len(chars), activation = 'softmax'))
model.add(Activation('softmax'))
Где последовательность — это список символов длиной 40 (sequence_length
), а chars
— список возможных символов. В данном случае 31. Итак, выходная форма модели (None,31)
Если я попытаюсь преобразовать модель, используя
coreml_model = coremltools.converters.keras.convert(
'keras_model.h5',
input_names=['sentence'],
output_names=['chars'],
class_labels = chars)
Я получаю следующую ошибку:
NSLocalizedDescription = "The size of the output layer 'characters' in the neural network does not match the number of classes in the classifier.";
Я думаю, это имеет смысл, так как выходная форма не имеет размерности.
Если я не укажу аргумент class_labels
, он прекрасно преобразует модель. Однако при запуске result = coreml_model.predict()
я теперь получаю выходную матрицу (40,31)
вместо одного списка вероятностей из 31 символа.
Ни одна из записей в результатах не соответствует значениям из модели Keras. Только первая запись имеет уникальные значения для каждого символа - все последующие записи имеют точно такие же значения.
Выходной слой модели CoreML имеет следующие метаданные:
output {
name: "characters"
shortDescription: "Next predicted character"
type {
multiArrayType {
shape: 31
dataType: DOUBLE
}
}
}
Большое спасибо за помощь!
@MatthijsHollemans на самом деле добавляет метки классов, если я это делаю. Но, конечно, это не будет полезно для реального использования. Я подозреваю, что это как-то связано с обработкой CoreML многомерного ввода/вывода в моделях. Я постараюсь сгладить их в модели.
Ошибка заключалась в несовместимости CoreML с многомерными входными данными. Я нашел этот блог, который направил меня в правильном направлении.
Поэтому, чтобы исправить это, мне пришлось сгладить входные данные, добавив слой Reshape, и изменить размер входных обучающих данных до одного вектора. Новая модель выглядит так:
# Input is now a single vector of length 1240
input_shape = (SEQUENCE_LENGTH*len(chars))
model = Sequential()
# The reshape layer makes sure that I don't have to change anything inside the layers.
model.add(Reshape((SEQUENCE_LENGTH, len(chars)), input_shape=(input_shape,)))
model.add(LSTM(128, input_shape=(SEQUENCE_LENGTH, len(chars))))
model.add(Dense(len(chars)))
model.add(Activation('softmax'))
Все входные векторы должны быть изменены одинаково:
x = x.reshape(x.shape[0], input_shape)
Что, если вы установите
SEQUENCE_LENGTH
на 1 вinput_shape
при преобразовании модели?