Вывод преобразованной модели CoreML, отличной от Keras

Я тренирую предиктор следующего символа/слова 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
    }
  }
}

Большое спасибо за помощь!

Что, если вы установите SEQUENCE_LENGTH на 1 в input_shape при преобразовании модели?

Matthijs Hollemans 09.04.2019 15:16

@MatthijsHollemans на самом деле добавляет метки классов, если я это делаю. Но, конечно, это не будет полезно для реального использования. Я подозреваю, что это как-то связано с обработкой CoreML многомерного ввода/вывода в моделях. Я постараюсь сгладить их в модели.

Elias Pedersen 09.04.2019 20:39
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
2
354
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Ошибка заключалась в несовместимости 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)

Другие вопросы по теме