Ошибка BERT: невозможно сжать измерение, значение которого не равно 1 - PullRequest
0 голосов
/ 19 февраля 2020

У меня есть mlmodel, основанная на pytorch-pretrained-BERT, экспортированная через ONNX в CoreML. Этот процесс был довольно плавным, поэтому сейчас я пытаюсь провести некоторое (очень) базовое тестирование c, то есть просто сделать какой-то прогноз и получить общее представление о том, с какими проблемами производительности мы можем столкнуться.

Как бы то ни было, когда я пытаюсь запустить прогнозирование, я получаю следующую ошибку:

[espresso] [Espresso::handle_ex_plan] exception=Espresso exception: "Invalid state": Cannot squeeze a dimension whose  
value is not 1: shape[1]=128 stat2020-02-16   
11:36:05.959261-0800 Xxxxx[6725:2140794] [coreml] Error computing NN outputs -5  

Указывает ли эта ошибка на проблему с самой моделью (т. Е. Из преобразования модели) или что-то в Swift / CoreML, что я делаю не так? Моя функция прогнозирования выглядит следующим образом:

public func prediction(withInput input: String) -> MLMultiArray? {
        var predictions: MLMultiArray? = nil
        if let bert = bertMLModel {
            var ids = tokenizer.tokenizeToIds(text: input, includeWordpiece: true)
            print("ids: \(ids)")
            while ids.count < 256 {
                ids.append(0)
            }
            let inputMLArray = MLMultiArray.from(ids, dims: 2)
            let modelInput = bert_256_FP16Input(input_ids: inputMLArray)
            var modelOutput: bert_256_FP16Output? = nil
            do {
                modelOutput = try bert.prediction(input: modelInput)
            } catch {
                print("Error running prediction: \(error)")
            }
            if let modelOutput = modelOutput {
                predictions = modelOutput.output_weights
            }
        }
        return predictions
    }

На данном этапе я не пытаюсь сделать что-либо значимое, только чтобы запустить его.

Я использовал pytorch-pretrained-BERT репо, потому что я смог найти пример предварительной подготовки для этого. С тех пор я заметил, что HuggingFace выпустил вариант обучения «с нуля», но все еще есть некоторые проблемы с этим уроком, которые решаются. Поэтому я хотел бы по крайней мере понять, что может быть не так с моей текущей моделью / подходом. Однако, если проблема определенно заключается в преобразовании PyTorch-> ONNX-> CoreML, тогда я не хочу участвовать в этой битве и просто углублюсь в то, что предлагает HuggingFace.

Любые мысли приветствуются.

ОБНОВЛЕНИЕ: По совету Матти js, я пытаюсь предсказать из модели в python:

from coremltools.models import *
import numpy as np

# Just a "dummy" input, but it is a valid series of tokens for my data.
tokens = [3, 68, 45, 68, 45,  5, 45, 68, 45,  4]
tokens_tensor = np.zeros((1, 128))
for i in range(0, 10):
    tokens_tensor[0, i] = tokens[I]
# I'm doing masked token prediction, so one segment.
segments_tensor = np.zeros((1, 128))

mlmodel = 'bert_fp16.mlmodel'

model = MLModel(mlmodel)
spec = model.get_spec()
print("spec: ", spec.description)

predictions = model.predict({'input.1': np.asarray(tokens_tensor, dtype=np.int32), 'input.3': np.asarray(segments_tensor, dtype=np.int32)})

Я признаю, что я не запускал mlmodel из python раньше, но я думаю, что данные верны. Spe c указывает:

input {
  name: "input.1"
  type {
    multiArrayType {
      shape: 1
      shape: 128
      dataType: INT32
    }
  }
}
input {
  name: "input.3"
  type {
    multiArrayType {
      shape: 1
      shape: 128
      dataType: INT32
    }
  }
}
...

для моих входов.

В этом случае я не получаю сообщение cannot squeeze или код ошибки (-5), но это не с Error computing NN outputs. Так что что-то определенно не так. Я просто не совсем уверен, как go отладить его.

J.

ОБНОВЛЕНИЕ: Для сравнения я обучил / преобразовал модель BERT HuggingFace (на самом деле, DistilBert - Я обновил код выше соответственно) и имею ту же ошибку. Глядя на журнал из onnx, я вижу, что добавлен один Squeeze (также, конечно, из журнала onnx-coreml), но единственный squeeze в коде PyTorch находится в BertForQuestionAnswering, а не BertForMaskedLM. Возможно, onnx строит модель ответа на вопрос, а не MLM (или вопрос, отвечающий на вопрос, сохраняется в контрольной точке)?

Глядя на пример кода swift-coreml-transformers, я вижу, что на входахtilBert просто let input_ids = MLMultiArray.from(allTokens, dims: 2), и именно так я его и определил. Так что я в тупике, я думаю. Кому-нибудь удалось запустить MLM с Bert / DistilBert в CoreML (через onnx)? Если это так, пример был бы очень полезен.

Я тренируюсь, используя последние run_language_modeling.py от HuggingFace, кстати.

Глядя на mlmodel в Netron, я вижу оскорбительные squeeze. Признаюсь, я не знаю, для чего предназначена эта ветвь ввода, но я предполагаю, что это маска (и еще одно предположение может быть связано с ответом на вопрос). Могу ли я просто удалить это как-нибудь?

enter image description here

...