我有一个基于 pytorch-pretrained-BERT 的 mlmodel,通过 ONNX 导出到 CoreML。这个过程非常顺利,所以现在我正在尝试做一些(非常)基本的测试——即,只是为了做出某种预测,并大致了解我们可能遇到的性能问题。
但是,当我尝试运行预测时,出现以下错误:
[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 提供的东西。
任何想法表示赞赏。
更新:根据 Matthijs 的建议,我试图从 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)})
我承认我之前没有从 python 运行过 mlmodel,但我认为输入是正确的。规范表明:
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
. 所以肯定有问题。我只是完全不确定如何调试它。
J。
更新:为了比较,我已经训练/转换了 HuggingFace BERT 模型(实际上是 DistilBert——我已经相应地更新了上面的代码)并且有同样的错误。查看来自 onnx 的日志,我看到Squeeze
添加了一个(当然,从 onnx-coreml 日志中也很清楚),但squeeze
PyTorch 代码中唯一的一个是 in BertForQuestionAnswering
,而不是BertForMaskedLM
. 也许 onnx 正在构建问答模型,而不是 mlm 模型(或者问答模型被保存在检查点中)?
查看 swift-coreml-transformers 示例代码,我可以看到 distilBert 的输入只是let input_ids = MLMultiArray.from(allTokens, dims: 2)
,这正是我定义它的方式。所以我想,我处于死胡同。有没有人设法在 CoreML 中使用 Bert/DistilBert 运行 MLM(通过 onnx)?如果是这样,一个例子将非常有帮助。
顺便说一句,我正在使用run_language_modeling.py
HuggingFace 的最新版本进行训练。
查看 Netron 中的 mlmodel,我可以看到有问题的squeeze
. 我承认我不知道输入的那个分支是做什么用的,但我猜它是一个掩码(进一步的猜测可能是它与问答有关)。我可以以某种方式删除它吗?