代码之家  ›  专栏  ›  技术社区  ›  Code Pope

Keras神经网络输出与Java TensorFlowInference接口输出不同

  •  1
  • Code Pope  · 技术社区  · 4 年前

    我使用Keras创建了一个神经网络 InceptionV3 预训练模型:

    base_model = applications.inception_v3.InceptionV3(weights='imagenet', include_top=False)
    
    # add a global spatial average pooling layer
    x = base_model.output
    x = GlobalAveragePooling2D()(x)
    
    # let's add a fully-connected layer
    x = Dense(2048, activation='relu')(x)
    x = Dropout(0.5)(x)
    predictions = Dense(len(labels_list), activation='sigmoid')(x)
    

    我成功地训练了模型,并希望遵循以下图片: https://i.stack.imgur.com/N43F9.jpg 因此,图像被裁剪为299x299并归一化(仅除以255):

    def img_to_array(img, data_format='channels_last', dtype='float32'):
        if data_format not in {'channels_first', 'channels_last'}:
            raise ValueError('Unknown data_format: %s' % data_format)
        # Numpy array x has format (height, width, channel)
        # or (channel, height, width)
        # but original PIL image has format (width, height, channel)
        x = np.asarray(img, dtype=dtype)
        if len(x.shape) == 3:
            if data_format == 'channels_first':
                x = x.transpose(2, 0, 1)
        elif len(x.shape) == 2:
            if data_format == 'channels_first':
                x = x.reshape((1, x.shape[0], x.shape[1]))
            else:
                x = x.reshape((x.shape[0], x.shape[1], 1))
        else:
            raise ValueError('Unsupported image shape: %s' % (x.shape,))
        return x
    def load_image_as_array(path):
        if pil_image is not None:
            _PIL_INTERPOLATION_METHODS = {
                'nearest': pil_image.NEAREST,
                'bilinear': pil_image.BILINEAR,
                'bicubic': pil_image.BICUBIC,
            }
            # These methods were only introduced in version 3.4.0 (2016).
            if hasattr(pil_image, 'HAMMING'):
                _PIL_INTERPOLATION_METHODS['hamming'] = pil_image.HAMMING
            if hasattr(pil_image, 'BOX'):
                _PIL_INTERPOLATION_METHODS['box'] = pil_image.BOX
            # This method is new in version 1.1.3 (2013).
            if hasattr(pil_image, 'LANCZOS'):
                _PIL_INTERPOLATION_METHODS['lanczos'] = pil_image.LANCZOS
    
        with open(path, 'rb') as f:
            img = pil_image.open(io.BytesIO(f.read()))
            width_height_tuple = (IMG_HEIGHT, IMG_WIDTH)
            resample = _PIL_INTERPOLATION_METHODS['nearest']
            img = img.resize(width_height_tuple, resample)
        return img_to_array(img, data_format=K.image_data_format())
    
    img_array = load_image_as_array('https://i.stack.imgur.com/N43F9.jpg')
    img_array = img_array/255
    

    然后我用Keras中训练好的模型进行预测:

    predict(img_array.reshape(1,img_array.shape[0],img_array.shape[1],img_array.shape[2]))
    

    结果如下:

    array([[0.02083278, 0.00425783, 0.8858412 , 0.17453966, 0.2628744 ,
            0.00428194, 0.2307986 , 0.01038828, 0.07561868, 0.00983179,
            0.09568241, 0.03087404, 0.00751176, 0.00651798, 0.03731382,
            0.02220723, 0.0187968 , 0.02018479, 0.3416505 , 0.00586909,
            0.02030778, 0.01660049, 0.00960067, 0.02457979, 0.9711478 ,
            0.00666443, 0.01468313, 0.0035468 , 0.00694743, 0.03057212,
            0.00429407, 0.01556832, 0.03173089, 0.01407397, 0.35166138,
            0.00734553, 0.0508953 , 0.00336689, 0.0169737 , 0.07512951,
            0.00484502, 0.01656419, 0.01643038, 0.02031735, 0.8343202 ,
            0.02500874, 0.02459189, 0.01325032, 0.00414564, 0.08371573,
            0.00484318]], dtype=float32)
    

    重要的是,它有四个大于0.8的值:

    >>> y[y>=0.8]
    array([0.9100583 , 0.96635956, 0.91707945, 0.9711707 ], dtype=float32))
    

    现在我已经将我的网络转换为.pb,并将其导入到一个android项目中。我想在安卓系统中预测同样的图像。因此,我还调整了图像的大小,并使用以下代码对其进行了规范化,就像我在Python中所做的那样:

    // Resize image:
    InputStream imageStream = getAssets().open("test3.jpg");
    Bitmap bitmap = BitmapFactory.decodeStream(imageStream);
    Bitmap resized_image = utils.processBitmap(bitmap,299);
    

    然后使用以下函数进行归一化:

    public static float[] normalizeBitmap(Bitmap source,int size){
    
        float[] output = new float[size * size * 3];
    
        int[] intValues = new int[source.getHeight() * source.getWidth()];
    
        source.getPixels(intValues, 0, source.getWidth(), 0, 0, source.getWidth(), source.getHeight());
        for (int i = 0; i < intValues.length; ++i) {
            final int val = intValues[i];
            output[i * 3] = Color.blue(val) / 255.0f;
            output[i * 3 + 1] =  Color.green(val) / 255.0f;
            output[i * 3 + 2] = Color.red(val) / 255.0f ;
        }
        return output;
    }
    

    但在java中,我得到了其他值。这四个指数的值都不大于0.8。
    四个指数的值在0.1和0.4之间!!!
    我已经检查了我的代码几次,但我不明白为什么在android中,同一张图片的值不一样?有什么想法或提示吗?

    0 回复  |  直到 4 年前