导出的tflite模型预测错误的输出

时间:2019-01-31 03:29:41

标签: ios firebase-mlkit

我有一个训练有素的自定义Tensorflow模型,并希望通过Firebase MLKit在我的iOS应用中使用它。 该模型是一个简单的4进4出神经网络,具有一个隐藏层,就像这样。

num_data_input = 4
num_units = 12
num_display = 4

xd = tf.placeholder(tf.float32, [None, num_data_input])

w1 = tf.Variable(tf.truncated_normal([num_data_input, num_units],dtype=tf.float32))
b1 = tf.Variable(tf.zeros([num_units],dtype=tf.float32))
hidden1 = tf.nn.sigmoid(tf.matmul(xd, w1) + b1)

w0 = tf.Variable(tf.zeros([num_units, num_display],dtype=tf.float32))
b0 = tf.Variable(tf.zeros([num_display],dtype=tf.float32))
p = tf.nn.softmax(tf.matmul(hidden1, w0) + b0)

ref = tf.placeholder(tf.float32, [None,num_display])
loss = -tf.reduce_sum(ref * tf.log(p))

train_step = tf.train.AdamOptimizer().minimize(loss)
correct_prediction = tf.equal(tf.argmax(p, 1), tf.argmax(ref, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

该模型的目的是通过使用分别放置在房间中的4个源信号来预测您在房间中设置的4个锚点中最接近的一个。因此,输出应显示每个锚点的概率。 (源信号位置和锚点之间的关系不是直接的,这就是为什么我考虑使用机器学习的原因。)

经过约10000次迭代训练,loss已降至约0.3。 (这还不够好,但这不是问题)。

培训结束后,我得到了这样的价值观。

print("input", dataarray[0][0])
print("output", sess.run(p, {xd: np.array(dataarray[0][0], dtype=np.float32).reshape(1,4)}))
# Results in:
# input [-87.43277416700528, -81.06589379945419, -71.74611110703701, -71.10851819430701]
# output [[1.5792685e-14 1.7755997e-01 7.4530774e-01 7.7132232e-02]]

print("input", dataarray[10][0])
print("output", sess.run(p, {xd: np.array(dataarray[10][0], dtype=np.float32).reshape(1,4)}))
# Results in:
# input [-86.87348060585144, -79.92684778533435, -71.24158331694396, -71.81342917898614]
# output [[1.30361505e-14 1.73598051e-01 7.51829445e-01 7.45724738e-02]]

除了正确与否之外,您至少可以看到它针对不同的输入报告了不同的值。

有了这个结果,我用python代码中的saved_model创建了一个tflite模型

tf.saved_model.simple_save(sess, "model", inputs={"input": xd}, outputs={"output": p})

和从命令行tflite_convert

tflite_convert --output_file=tmp/model.tflite --saved_model_dir=model

然后通过云在我斯威夫特项目导入:

    let conditions = ModelDownloadConditions(isWiFiRequired: true, canDownloadInBackground: true)
    let cloudModelSource = CloudModelSource(
        modelName: "my-model",
        enableModelUpdates: false,
        initialConditions: conditions,
        updateConditions: conditions
    )
    let registrationSuccessful = ModelManager.modelManager().register(cloudModelSource)

    let options = ModelOptions(
        cloudModelName: "my-model",
        localModelName: nil)
    interpreter = ModelInterpreter.modelInterpreter(options: options)

    ioOptions = ModelInputOutputOptions()
    do {
        try ioOptions.setInputFormat(index: 0, type: .float32, dimensions: [1, 4])
        try ioOptions.setOutputFormat(index: 0, type: .float32, dimensions: [1, 4])
    } catch let error as NSError {
        print("Failed to set input or output format with error: \(error.localizedDescription)")
    }

并执行预测:

    // 1st value
    let inputValues: [Double] = [-78.07635984967995, -76.68000728404165, -73.98016027165527, -74.77428875130332] 
    // 2nd value
    // let inputValues: [Double] = [-86.87348060585144, -79.92684778533435, -71.24158331694396, -71.81342917898614]

    let inputs = ModelInputs()
    let converted: [Float32] = inputValues.map { Float32($0) }
    do {
        try inputs.addInput([converted])
    } catch let error {
        print("Failed to add input: \(error)")
    }

    interpreter.run(inputs: inputs, options: ioOptions) { (outputs, error) in
        guard error == nil, let outputs = outputs else { return }
        do {
            if let ov = try outputs.output(index: 0) as? [[NSNumber]] {
                print("output = \(ov)") 
                // output = [[0.089901, 0.2951571, 0.2564065, 0.3585353]]
                // ^ Different from above result in python!
                //   And gives me the same value even when the input value is switched to "2nd value" above
            }
        } catch let error {
            print("output retrieval error: \(error)")
        }
    }
}

首先,从银行代码的输出值是从所述一个在Python不同。 最重要的是,我尝试了一些不同的价值观,他们都给了我相同的价值观。我还尝试了真实世界的信号值,但几乎在所有情况下它都给了我相同的值。 只有当我给它一些超出预期范围的极限值时,它才会显示不同的值。

您在我的Python代码或Swift代码中看到任何问题吗? 还是我的tflite模型转换中缺少任何内容?

任何信息都是有帮助的。

谢谢

1 个答案:

答案 0 :(得分:0)

部分解决。 或准确地说,这是另一个问题。

通过从本地捆绑包提供模型,可以按预期工作。

我发现,即使我替换了云中的模型,该应用程序仍使用以前的模型。

我上面没有提到,但是在获得上述结果之前我尝试了不同的tflite模型。而且我对它的第一个结果没有给予太多关注,因为我知道该模型是不完整的。如果我更加注意它,我会更早发现结果根本没有改变。

无论如何,现在我必须弄清楚为什么从云中检索无法按预期进行,但我希望此信息对其他人有所帮助。