预训练的keras模型在android中重现相同的结果

时间:2019-05-26 13:40:15

标签: android tensorflow machine-learning keras deep-learning

我已经在Keras中创建了图像分类器,后来我将模型保存为pb格式,以便在Android中使用。

但是,在python代码中,它可以正确分类图像。但是在android中,无论我提供什么图像作为输入,输出始终是相同的。

这就是我训练模型的方式

rom keras.models import Sequential
from keras.layers import Conv2D
from keras.layers import MaxPooling2D
from keras.layers import Flatten
from keras.layers import Dense

# Initialising the CNN
classifier = Sequential()

# Step 1 - Convolution
classifier.add(Conv2D(32, (3, 3), input_shape = (64, 64, 3), activation = 'relu'))

# Step 2 - Pooling
classifier.add(MaxPooling2D(pool_size = (2, 2)))

# Adding a second convolutional layer
classifier.add(Conv2D(32, (3, 3), activation = 'relu'))
classifier.add(MaxPooling2D(pool_size = (2, 2)))

# Step 3 - Flattening
classifier.add(Flatten())

# Step 4 - Full connection
classifier.add(Dense(units = 128, activation = 'relu'))
classifier.add(Dense(units = 1, activation = 'sigmoid'))

# Compiling the CNN
classifier.compile(optimizer = 'adam', loss = 'binary_crossentropy', metrics = ['accuracy'])

# Part 2 - Fitting the CNN to the images

from keras.preprocessing.image import ImageDataGenerator

train_datagen = ImageDataGenerator(rescale = 1./255,
                                   shear_range = 0.2,
                                   zoom_range = 0.2,
                                   horizontal_flip = True)

test_datagen = ImageDataGenerator(rescale = 1./255)

training_set = train_datagen.flow_from_directory('dataset/training_set',
                                                 target_size = (64, 64),
                                                 batch_size = 32,
                                                 class_mode = 'binary')

test_set = test_datagen.flow_from_directory('dataset/test_set',
                                            target_size = (64, 64),
                                            batch_size = 32,
                                            class_mode = 'binary')

classifier.fit_generator(training_set,
                         steps_per_epoch = 8000,
                         epochs = 25,
                         validation_data = test_set,
                         validation_steps = 2000)
classifier.summary()
classifier.save('saved_model.h5')

稍后,我使用this将keras模型(saved_model.h5)转换为张量流模型

这就是我转换位图浮点数组的方式

    public static float[] getPixels(Bitmap bitmap) {

        final int IMAGE_SIZE = 64;

        int[] intValues = new int[IMAGE_SIZE * IMAGE_SIZE];
        float[] floatValues = new float[IMAGE_SIZE * IMAGE_SIZE * 3];

        if (bitmap.getWidth() != IMAGE_SIZE || bitmap.getHeight() != IMAGE_SIZE) {
            // rescale the bitmap if needed
            bitmap = ThumbnailUtils.extractThumbnail(bitmap, IMAGE_SIZE, IMAGE_SIZE);
        }

        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];
        // bitwise shifting - without our image is shaped [1, 64, 64, 1] but we need [1, 168, 168, 3]
            floatValues[i * 3 + 2] = Color.red(val) / 255.0f;
            floatValues[i * 3 + 1] = Color.green(val) / 255.0f;
            floatValues[i * 3] = Color.blue(val) / 255.0f;
        }
        return floatValues;
    }

后来,我尝试使用android中的tensorflow对图像进行分类,如下所示。

TensorFlowInferenceInterface tensorFlowInferenceInterface; 
tensorFlowInferenceInterface = new TensorFlowInferenceInterface(getAssets(),"model.pb");
float[] output = new float[2];
tensorFlowInferenceInterface.feed("conv2d_11_input",
                getPixels(bitmap), 1,64,64,3);
tensorFlowInferenceInterface.run(new String[]{"dense_12/Sigmoid"});
tensorFlowInferenceInterface.fetch("dense_12/Sigmoid",output);

无论我给output赋予什么图像,都是[1,0]

有什么我想念的吗?

1 个答案:

答案 0 :(得分:1)

Color.red(int)Color.blue(int)Color.green(int)返回的颜色分量是[0,255]范围内的整数(请参阅doc)。使用Keras的ImageDataGenerator读取图像时,同样的情况也适用。但是,正如我在评论部分所述,在预测阶段,您需要执行与训练阶段相同的预处理步骤。您正在训练中通过1./255缩放图像像素(使用rescale = 1./255中的ImageDataGenerator),因此,根据我提到的第一点,这也必须在预测中完成:

floatValues[i * 3 + 2] = Color.red(val) / 255.0;
floatValues[i * 3 + 1] = Color.green(val) / 255.0;
floatValues[i * 3] = Color.blue(val) / 255.0;