我有一个训练有素的自定义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模型转换中缺少任何内容?
任何信息都是有帮助的。
谢谢
答案 0 :(得分:0)
部分解决。 或准确地说,这是另一个问题。
通过从本地捆绑包提供模型,可以按预期工作。
我发现,即使我替换了云中的模型,该应用程序仍使用以前的模型。
我上面没有提到,但是在获得上述结果之前我尝试了不同的tflite模型。而且我对它的第一个结果没有给予太多关注,因为我知道该模型是不完整的。如果我更加注意它,我会更早发现结果根本没有改变。
无论如何,现在我必须弄清楚为什么从云中检索无法按预期进行,但我希望此信息对其他人有所帮助。