Выход нейросети Keras отличается от Java Выход TensorFlowInferenceInterface - PullRequest
1 голос
/ 10 февраля 2020

Я создал нейронную сеть в Керасе, используя предварительно обученную модель 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://imgur.com/a/hoNjDfR. Таким образом, изображение обрезается до 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://imgur.com/a/hoNjDfR')
img_array = img_array/255

Затем я прогнозирую его с помощью обученной модели в Керасе:

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 проект. Я хотел предсказать то же изображение в 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 Я не получаю одинаковые значения для одного изображения? Любая идея или намек?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...