相同的Tensorflow模型在Android和Python上提供不同的结果

red*_*uht 6 python android machine-learning tensorflow

我试图在我的Android应用程序上运行Tensorflow模型,但是与在桌面上运行Python时相比,相同的训练模型会产生不同的结果(错误的推断).

该模型是一个简单的连续CNN,用于识别字符,就像这个车牌识别网络一样,减去窗口,因为我的模型已经将字符裁剪到位.

我有:

  • 模型保存在protobuf(.pb)文件中 - 在Keras上在Python/Linux + GPU上建模和训练
  • 推理是在纯Tensorflow上的另一台计算机上测试的,以确保Keras不是罪魁祸首.在这里,结果如预期.
  • Tensorflow 1.3.0正在Python和Android上使用.在PIP上安装Python和jcenter在Android上安装.
  • Android上的结果与预期结果不符.
  • 输入是129*45 RGB图像,因此是129*45*3阵列,输出是4*36阵列(代表0-9和az的4个字符).

我使用此代码将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})
Run Code Online (Sandbox Code Playgroud)

Android代码,基于此示例 ; 这给出了看似随机的结果:

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);
Run Code Online (Sandbox Code Playgroud)

任何帮助是极大的赞赏!

Vro*_*del 4

一个问题是:

    floatValues[i * 3 + 0] = ((val >> 16) & 0xFF) / 255;
    floatValues[i * 3 + 1] = ((val >> 8) & 0xFF) / 255;
    floatValues[i * 3 + 2] = (val & 0xFF) / 255;
Run Code Online (Sandbox Code Playgroud)

其中 RGB 值除以整数,从而产生整数结果(即每次都是 0)。

此外,即使以255.00 到 1.0 之间的浮点数执行除法也可能会产生问题,因为这些值不像 Natura 中那样分布在投影空间 (0..1) 中。解释一下:传感器域中的值 255(例如 R 值)意味着测量信号的自然值落在“255”桶中的某个位置,该桶是能量/强度/等的整个范围。将此值映射到 1.0 很可能会缩小其范围的一半,因为后续计算可能会在最大乘数 1.0 处饱和,这实际上只是 +- 1/256 桶的中点。因此,也许该转换更正确地映射到 0..1 范围的 256 个桶划分的中点:

((val & 0xff) / 256.0) + (0.5/256.0)
Run Code Online (Sandbox Code Playgroud)

但这只是我的猜测。