Вывод преобразованной модели CoreML, отличной от Keras - PullRequest
0 голосов
/ 09 апреля 2019

Я обучаю 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.";

Полагаю, это имеет смысл, поскольку выходная фигура имеет размерность None.

Если я не укажу аргумент class_labels, он отлично преобразует модель.Однако при запуске result = coreml_model.predict() теперь я получаю матрицу вывода (40,31) вместо одного списка из 31 символа вероятностей.

Ни одна из записей в результатах не соответствует значениям модели Keras.Единственная первая запись имеет уникальные значения для каждого символа - все последующие записи имеют одинаковые значения.

Выходной слой модели CoreML имеет следующие метаданные:

output {
  name: "characters"
  shortDescription: "Next predicted character"
  type {
    multiArrayType {
      shape: 31
      dataType: DOUBLE
    }
  }
}

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

1 Ответ

0 голосов
/ 10 апреля 2019

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