pytorch / android-demo-app

PyTorch android examples of usage in applications
1.45k stars 593 forks source link

Totally different results when using the same model on PC and android mobilephone? #329

Open btdan opened 11 months ago

btdan commented 11 months ago

Hello, I have trained a mobilenetv2 model with the help of pytorch(version: 1.9.0) and convert to .pt format, deploy the .pt model on android mobilephone. However, I get very different result from the result on PC. Can anyone help me to solve this problem? The details are as follows: First,train the new model(named result.ckpt) from mobilenetv2(the same problem with mobilenetv3 ) with the help of pytorch. Secondly, convert the model result.ckpt to result.pt the key source codes is as follows:

import torch
import torchvision
from torch.utils.mobile_optimizer import optimize_for_mobile
import torchvision.models as models

model= torch.load('result.ckpt', map_location=torch.device('cpu'))
print(model)
model.eval()
example = torch.rand(1, 3, 224, 224)
traced_script_module = torch.jit.trace(model, example)
traced_script_module.save("result.pt")

Thirdly, deploy the result.pt model inside app source code. And then compile to get the apk the key source codes are as follows:

module = LiteModuleLoader.load(assetFilePath(this, "largeMbv3.pt"));
bitmap = decodeFile(imgPath);
newbitmap = compressImageFromBitmap(bitmap,224,224);
final Tensor inputTensor = TensorImageUtils.bitmapToFloat32Tensor(newbitmap,
                TensorImageUtils.TORCHVISION_NORM_MEAN_RGB, TensorImageUtils.TORCHVISION_NORM_STD_RGB, MemoryFormat.CHANNELS_LAST);

        // running the model
        final Tensor outputTensor = module.forward(IValue.from(inputTensor)).toTensor();
        final float[] scores = outputTensor.getDataAsFloatArray();

And the function compressImageFromBitmap is as follows:

    public static Bitmap compressImageFromBitmap(Bitmap bitmap, int pixelW, int pixelH) {
        ByteArrayOutputStream os = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, os);
        if( os.toByteArray().length / 1024>512) {
            os.reset();
            bitmap.compress(Bitmap.CompressFormat.JPEG, 50, os);
        }
        ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        options.inPreferredConfig = Bitmap.Config.RGB_565;
        BitmapFactory.decodeStream(is, null, options);
        options.inJustDecodeBounds = false;
        options.inSampleSize = computeSampleSize(options , pixelH > pixelW ? pixelW : pixelH ,pixelW * pixelH );
        is = new ByteArrayInputStream(os.toByteArray());
        Bitmap newBitmap = BitmapFactory.decodeStream(is, null, options);
        return newBitmap;
    }

However, I get quiet different result for same image to identify on PC and android Can anyone help me to solve this problem? Thans very much.

By the way, I have set random to a fix number when training the model.Just as follows:

seed=42
random.seed(seed)
numpy.random.seed(seed)
torch.manual_seed(seed)
if torch.cuda.is_available():
    torch.cuda.manual_seed(seed)
    torch.cuda.manual_seed_all(seed)  # all gpus
    torch.backends.cudnn.benchmark = False
    torch.backends.cudnn.deterministic = True
torch.use_deterministic_algorithms(True)
torch.set_default_tensor_type(torch.float32)

But it does not have any change at all. Thans very much for your help . Best wishes to you.

NeighborhoodCoding commented 11 months ago

Android and Python are different OSes and the code is not the same. This means that even pytorch, for example, is not 100% compatible between android and python, and the reproducibility of some operations may differ between versions.

You're using AI for mobile, not for python, and you shouldn't expect exactly the same results. It's probably technically easier to accept some differences than to change the random seed.