我有一个训练有素的神经网络(Alexnet)作为Keras模型,应该用于android分类应用。首先,我将模型转换为TensorFlow.pb
文件:
class Model2Graph(object):
@staticmethod
def Convert(ModelPath, OutputPath = "output"):
print("[INFO] Converting model '{}' into TensorFlow graph...".format(ModelPath))
# Get the model name
ModelName = os.path.splitext(ModelPath)[0].rsplit(os.path.sep, 1)[-1]
# Load the model from file
Model = load_model(filepath = ModelPath)
Backend.set_learning_phase(0)
Session = Backend.get_session()
OutputCount = len(Model.outputs)
Temp = [None] * OutputCount
NodeNames = [None] * OutputCount
for i in range(OutputCount):
NodeNames[i] = "output_node" + str(i)
Temp[i] = tf.identity(Model.outputs[i], name = NodeNames[i])
constant_graph = graph_util.convert_variables_to_constants(Session, Session.graph.as_graph_def(), NodeNames)
graph_io.write_graph(constant_graph, OutputPath, ModelName + ".pb", as_text = False)
此图(带有Labels.txt
文件)放在我的android应用程序的assets文件夹中。
现在,我将图像加载为JPG文件。我将其调整IrfanView
为227x227图像的大小(网络的输入大小,忽略了宽高比),并使用我的应用加载了该图像(该图像称为1.jpg
)。
该应用程序开始对此图像进行分类(此代码基于TensorFlow示例):
public List<Float> Classify(Bitmap InputImage)
{
float[] Results = new float[_mClassLabels.size()];
float[] Output = new float[_mWidth * _mHeight * 3];
int[] intValues = new int[InputImage.getHeight() * InputImage.getWidth()];
InputImage.getPixels(intValues, 0, InputImage.getWidth(), 0, 0, InputImage.getWidth(), InputImage.getHeight());
for (int i = 0; i < intValues.length; ++i)
{
final int val = intValues[i];
Output[i * 3] = ((val >> 16) & 0xFF) / 255.0f;
Output[i * 3 + 1] = ((val >> 8) & 0xFF) / 255.0f;
Output[i * 3 + 2] = (val & 0xFF) / 255.0f;
}
_mTensorFlowInterface.feed("conv2d_1_input", Output, 1L, _mWidth, _mHeight, 3);
_mTensorFlowInterface.run(_mOutputName, false);
_mTensorFlowInterface.fetch(_mOutputName[0], Results);
// Convert the results into a list
List<Float> Result = new ArrayList<Float>(Results.length);
for(float f : Results)
{
Result.add(f);
}
return Result;
}
我的Android应用程序为我提供了以下分类结果:
但是,当我使用Python应用程序和Keras模型时,却得到了不同的结果。Python应用程序给出以下结果:
现在,我想知道为什么同一个网络在两个应用程序中会产生不同的结果。这是怎么了?
我的Android / Java不太好,所以我不确定预测代码是否正确。将Keras模型转换.pb
为TensorFlow的文件时也是如此。
抱歉回复晚了。我为此创建了一个新帖子,因为我想分享解决方案。感谢@Steven。TensorFlow lite的提示非常不错。所以我将Keras模型转换为TensorFlow lite图
Converter = lite.TFLiteConverter.from_keras_model_file(ModelPath)
open(OutputPath + os.path.sep + ModelName + ".tflite" , "wb") .write(Converter.convert())
现在可以使用TensorFlow lite加载此图:
private Interpreter _mTfLite;
private Interpreter.Options _mTfliteOptions = new Interpreter.Options();
private MappedByteBuffer loadModelFile(AssetManager Manager, String Path) throws IOException
{
AssetFileDescriptor fileDescriptor = Manager.openFd(Path);
FileInputStream inputStream = new
FileInputStream(fileDescriptor.getFileDescriptor());
FileChannel fileChannel = inputStream.getChannel();
long startOffset = fileDescriptor.getStartOffset();
long declaredLength = fileDescriptor.getDeclaredLength();
return fileChannel.map(FileChannel.MapMode.READ_ONLY, startOffset, declaredLength);
}
_mTfLite = new Interpreter(loadModelFile(_mAssetManager, Path), _mTfliteOptions.setNumThreads(1));
现在,您可以在位图上运行预测:
private ByteBuffer _mInput;
private float[][] _mOutput;
public float[] Classify(Bitmap InputImage)
{
_mInput.rewind();
int width = InputImage.getWidth();
int height = InputImage.getHeight();
int[] pixels = new int[width * height];
InputImage.getPixels(pixels, 0, width, 0, 0, width, height);
int j = 0;
for(int i = 0; i < pixels.length * 3; i = i + 3)
{
final int Pixel = pixels[j];
_mInput.putFloat((((Pixel >> 16) & 0xFF)) / 1.0f);
_mInput.putFloat((((Pixel >> 8) & 0xFF)) / 1.0f);
_mInput.putFloat(((Pixel & 0xFF)) / 1.0f);
j++;
}
_mTfLite.run(_mInput, _mOutput);
return _mOutput[0];
}
但是你需要添加
aaptOptions {
noCompress "tflite"
noCompress "lite"
}
到您的build.gradle
文件。否则,您的模型将在构建过程中被压缩,从而导致模型的加载错误。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句