我正在尝试在我的Android应用程序上运行Tensorflow模型,但与在桌面上运行Python时相比,相同的训练模型会产生不同的结果(错误的推断)。
该模型是一个简单的连续CNN,用于识别字符,与this number plate recognition network非常相似,减去窗口,因为我的模型已将字符裁剪到位。
我有:
我使用this code将Keras模型保存为.pb文件。
Python代码,这可以按预期工作:
test_image = [ndimage.imread("test_image.png", mode="RGB").astype(float)/255]
imTensor = np.asarray(test_image)
def load_graph(model_file):
graph = tf.Graph()
graph_def = tf.GraphDef()
with open(model_file, "rb") as f:
graph_def.ParseFromString(f.read())
with graph.as_default():
tf.import_graph_def(graph_def)
return graph
graph=load_graph("model.pb")
with tf.Session(graph=graph) as sess:
input_operation = graph.get_operation_by_name("import/conv2d_1_input")
output_operation = graph.get_operation_by_name("import/output_node0")
results = sess.run(output_operation.outputs[0],
{input_operation.outputs[0]: imTensor})
Android代码,基于this example;这给出了看似随机的结果:
Bitmap bitmap;
try {
InputStream stream = getAssets().open("test_image.png");
bitmap = BitmapFactory.decodeStream(stream);
} catch (IOException e) {
e.printStackTrace();
}
inferenceInterface = new TensorFlowInferenceInterface(context.getAssets(), "model.pb");
int[] intValues = new int[129*45];
float[] floatValues = new float[129*45*3];
String outputName = "output_node0";
String[] outputNodes = new String[]{outputName};
float[] outputs = new float[4*36];
bitmap.getPixels(intValues, 0, bitmap.getWidth(), 0, 0, bitmap.getWidth(), bitmap.getHeight());
for (int i = 0; i < intValues.length; ++i) {
final int val = intValues[i];
floatValues[i * 3 + 0] = ((val >> 16) & 0xFF) / 255;
floatValues[i * 3 + 1] = ((val >> 8) & 0xFF) / 255;
floatValues[i * 3 + 2] = (val & 0xFF) / 255;
}
inferenceInterface.feed("conv2d_1_input", floatValues, 1, 45, 129, 3);
inferenceInterface.run(outputNodes, false);
inferenceInterface.fetch(outputName, outputs);
非常感谢任何帮助!
答案 0 :(得分:3)
一个问题在于:
floatValues[i * 3 + 0] = ((val >> 16) & 0xFF) / 255;
floatValues[i * 3 + 1] = ((val >> 8) & 0xFF) / 255;
floatValues[i * 3 + 2] = (val & 0xFF) / 255;
其中RGB值除以整数,从而产生整数结果(即每次为0)。
此外,即使用255.0
执行产生0到1.0之间的浮点值的分割也可能会产生问题,因为值不像投影空间(0..1)那样分布在Natura。为了解释这一点:传感器域中的值255(例如,R值)意味着测量信号的自然值落在“255”桶中的某处,这是整个能量/强度范围/等。将此值映射到1.0很可能会减少其范围的一半,因为后续计算可能会在1.0的最大乘数处饱和,这实际上只是+ - 1/256桶的中点。因此,转换可能更准确地映射到0..1范围的256桶分区的中点:
((val & 0xff) / 256.0) + (0.5/256.0)
但这只是我身边的猜测。