Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Trained YOLOv8 model converted to CoreML doesn't give any predictions #13794

Open
1 task done
tardoe opened this issue Jun 19, 2024 · 10 comments
Open
1 task done

Trained YOLOv8 model converted to CoreML doesn't give any predictions #13794

tardoe opened this issue Jun 19, 2024 · 10 comments
Labels
question Further information is requested

Comments

@tardoe
Copy link

tardoe commented Jun 19, 2024

Search before asking

Question

I'm having some issues exporting a YOLOv8 model I trained to CoreML. Testing the model in yolo format predicts just fine, after converting to CoreML, testing with coremltools predictions and using the Xcode preview return no results.

I trained the custom model based on 640x640 jpg images across 43 classes, used the yolov8m model as the base, using CUDA on an RTX4090. The training was done like this: results = model.train(data="yolov8_dataset/dataset.yaml", epochs=350, device=0). The training ended normally after 330 epochs having not changed in 100 epochs.

This is how I'm exporting the model: model.export(format="coreml", nms=True, half=False, imgsz=640) using coremltools 7.2.
I'm using YOLOv8.2.35 / Python-3.11.6 torch-2.2.0 CPU (Apple M1 Max) to do the conversion. No errors in the conversion process

Testing against the designated 640x640 test images from my original dataset.

I also tried this same process on the YOLOv8m "vanilla" model and it worked just fine, the Xcode preview showed predictions - what have I likely done wrong with the custom model?

What am I likely missing here?

Additional

No response

@tardoe tardoe added the question Further information is requested label Jun 19, 2024
Copy link

👋 Hello @tardoe, thank you for your interest in Ultralytics YOLOv8 🚀! We recommend a visit to the Docs for new users where you can find many Python and CLI usage examples and where many of the most common questions may already be answered.

If this is a 🐛 Bug Report, please provide a minimum reproducible example to help us debug it.

If this is a custom training ❓ Question, please provide as much information as possible, including dataset image examples and training logs, and verify you are following our Tips for Best Training Results.

Join the vibrant Ultralytics Discord 🎧 community for real-time conversations and collaborations. This platform offers a perfect space to inquire, showcase your work, and connect with fellow Ultralytics users.

Install

Pip install the ultralytics package including all requirements in a Python>=3.8 environment with PyTorch>=1.8.

pip install ultralytics

Environments

YOLOv8 may be run in any of the following up-to-date verified environments (with all dependencies including CUDA/CUDNN, Python and PyTorch preinstalled):

Status

Ultralytics CI

If this badge is green, all Ultralytics CI tests are currently passing. CI tests verify correct operation of all YOLOv8 Modes and Tasks on macOS, Windows, and Ubuntu every 24 hours and on every commit.

@glenn-jocher
Copy link
Member

Hi @tardoe,

Thank you for reaching out and providing detailed information about your issue. Let's work through this together to identify the problem.

Firstly, it's great to hear that the vanilla YOLOv8m model works fine after conversion to CoreML. This indicates that the conversion process itself is functioning correctly. The issue seems to be specific to your custom-trained model.

Here are a few steps to help diagnose and potentially resolve the issue:

  1. Verify Model Performance Before Export:
    Ensure that your custom-trained model performs as expected in its original format before conversion. You can do this by running predictions on your test images using the predict method in the YOLO format:

    results = model.predict(source='path/to/test/images', imgsz=640)
    results.show()
  2. Check CoreML Export Parameters:
    Your export command looks correct, but let's ensure that the parameters are optimal. You might want to try exporting without the nms parameter to see if it affects the predictions:

    model.export(format="coreml", half=False, imgsz=640)
  3. Inspect CoreML Model in Xcode:
    After exporting, use Xcode to inspect the CoreML model. Ensure that the input and output shapes match your expectations. Sometimes, discrepancies in input/output shapes can lead to no predictions.

  4. Test CoreML Model with CoreMLTools:
    Use coremltools to test the CoreML model directly in Python before deploying it to Xcode. This can help isolate whether the issue is with the model or the deployment environment:

    import coremltools as ct
    from PIL import Image
    import numpy as np
    
    # Load the CoreML model
    coreml_model = ct.models.MLModel('yolov8n.mlpackage')
    
    # Load and preprocess an image
    image = Image.open('path/to/test/image.jpg').resize((640, 640))
    image_np = np.array(image).astype(np.float32)
    
    # Make a prediction
    prediction = coreml_model.predict({'image': image_np})
    print(prediction)
  5. Ensure Compatibility:
    Verify that the versions of torch, ultralytics, and coremltools are compatible. Sometimes, version mismatches can cause unexpected behavior. Ensure you are using the latest versions:

    pip install --upgrade torch ultralytics coremltools

If the issue persists, please provide a minimum reproducible example of your code and dataset configuration. This will help us reproduce the bug and investigate further. You can find guidelines for creating a minimum reproducible example here.

Feel free to reach out with any additional questions or updates on your progress. We're here to help!

@tardoe
Copy link
Author

tardoe commented Jun 20, 2024

Thanks for the advice, I'll address each one accordingly:

  1. The model performs as expected, I saw accurate predictions for 95% of of 225 image testing image set (separate to the training set).
  2. Exporting without NMS means the import into Xcode doesn't show the class labels and doesn't allow me to test the prediction inside Xcode.
  3. Testing with coremltools results in the following error:
>>> import coremltools as ct
>>> from PIL import Image
>>> import numpy as np
>>> coreml_model = ct.models.MLModel('./runs/detect/train3/weights/best.mlpackage')
>>> image = Image.open('./dataset/test/images/test_21.jpg')
>>> image_np = np.array(image).astype(np.float32)
>>> prediction = coreml_model.predict({'image': image_np})
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "./venv/lib/python3.11/site-packages/coremltools/models/model.py", line 627, in predict
    return MLModel._get_predictions(self.__proxy__, verify_and_convert_input_dict, data)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "./venv/lib/python3.11/site-packages/coremltools/models/model.py", line 669, in _get_predictions
    preprocess_method(data)
  File "./venv/lib/python3.11/site-packages/coremltools/models/model.py", line 615, in verify_and_convert_input_dict
    self._verify_input_dict(d)
  File "./venv/lib/python3.11/site-packages/coremltools/models/model.py", line 741, in _verify_input_dict
    self._verify_pil_image_modes(input_dict)
  File "./venv/lib/python3.11/site-packages/coremltools/models/model.py", line 752, in _verify_pil_image_modes
    raise TypeError(msg.format(input_desc.name))
TypeError: Image input, 'image' must be of type PIL.Image.Image in the input dict

Trying again, by just passing in the PIL Image object, I get a valid prediction:

>>> prediction = coreml_model.predict({'image': image})
>>> print(prediction)
{'var_1140': array([[[     9.2656,      40.438,      31.188, ...,         501,         523,       543.5],
        [     33.344,      4.4141,      4.3789, ...,         621,         618,         610],
        [     23.406,      92.625,      166.38, ...,         398,       373.5,         249],
        ...,
        [          0,           0,           0, ...,           0,           0,           0],
        [          0,           0,           0, ...,           0,           0,           0],
        [          0,           0,           0, ...,           0,           0,           0]]], dtype=float32)}

Though I don't understand the output. This is on the model converted without nms=True.
If I export the model with nms , I don't get a result:

>>> from PIL import Image
>>> import numpy as np
>>> coreml_model = ct.models.MLModel('cpe_id/cpe_id_2/runs/detect/train3/weights/best.mlpackage')
>>> image = Image.open('/Users/tim/Development/cpe-id/cpe_id_model/cpe_id/cpe_id_2/dataset/test/images/tplink_vx220g2v_21.jpg')
>>> prediction = coreml_model.predict({'image': image})
>>> prediction
{'coordinates': array([], shape=(0, 4), dtype=float32), 'confidence': array([], shape=(0, 44), dtype=float32)}

However, trying to use the model without nms=True in Xcode throws an error because the labels are missing from the metadata, how do you fix that?

  1. I'm running the latest versions of all tools:
❯ pip freeze | grep -E "torch=|ultralytics=|coremltools="
coremltools==7.2
torch==2.2.0
ultralytics==8.2.36

@glenn-jocher
Copy link
Member

Hi @tardoe,

Thank you for the detailed follow-up! Let's address each point to help you resolve the issue:

  1. Model Performance:
    It's great to hear that your model performs well on the test set. This confirms that the training process was successful.

  2. Exporting Without NMS:
    Since exporting without NMS results in missing class labels in Xcode, it's essential to include NMS during export. This ensures that the model's predictions are properly formatted for Xcode.

  3. CoreMLTools Testing:
    The error you encountered with coremltools indicates that the input should be a PIL.Image.Image object. Your subsequent test with the PIL image object worked, but the output format seems unclear. When exporting with nms=True, the model should include the necessary metadata for proper predictions. Let's ensure the export process is correct:

    model.export(format="coreml", nms=True, half=False, imgsz=640)

    If the exported model with nms=True still doesn't give results, it might be due to the input preprocessing or post-processing steps. Ensure that the input image is correctly preprocessed and matches the expected input format of the CoreML model.

  4. CoreML Model Output:
    The output you received without NMS ('var_1140': array([...])) seems to be raw predictions. When NMS is applied, the output should be more structured, including coordinates and confidence scores. If the model with nms=True returns empty arrays, it might be due to a thresholding issue. Ensure that the confidence threshold is set appropriately during inference.

  5. Metadata for Xcode:
    To fix the issue with missing labels in Xcode, ensure that the CoreML model includes the class labels in its metadata. You can manually add metadata to the CoreML model using coremltools:

    import coremltools as ct
    
    # Load the CoreML model
    coreml_model = ct.models.MLModel('path/to/your/model.mlpackage')
    
    # Add class labels to the model's metadata
    coreml_model.user_defined_metadata['classes'] = 'path/to/your/classes.txt'
    
    # Save the updated model
    coreml_model.save('path/to/your/updated_model.mlpackage')
  6. Versions:
    You're using the latest versions of torch, ultralytics, and coremltools, which is excellent. This ensures compatibility and access to the latest features and fixes.

If the issue persists, please provide a minimum reproducible example of your code and dataset configuration. This will help us reproduce the bug and investigate further. You can find guidelines for creating a minimum reproducible example here.

Feel free to reach out with any additional questions or updates on your progress. We're here to help! 😊

@tardoe
Copy link
Author

tardoe commented Jun 20, 2024

Thanks, for the suggestions.

  1. Agreed.
  2. Noted
  3. When testing the model in Xcode, I use the same, correctly formatted images as I had in the testing set. They match the model's expected input.
  4. The confidence thresholds in the model are already very low:
  userDefined {
    key: "Confidence threshold"
    value: "0.25"
  }
  userDefined {
    key: "IoU threshold"
    value: "0.45"
  }
  1. The missing labels are only the case when nms=False which is expect as per your comments in 2.
  2. Ok.

I believe I've already provided the minimal examples above for reproducibility.

@glenn-jocher
Copy link
Member

Hi @tardoe,

Thank you for the detailed follow-up and for confirming the steps you've taken so far. Let's dive deeper into resolving this issue.

Key Points Recap:

  1. Model Performance: Confirmed to be accurate before export.
  2. Export with NMS: Necessary for proper predictions in Xcode.
  3. Testing in Xcode: Using correctly formatted images.
  4. Confidence Thresholds: Already set to low values.
  5. Labels with NMS: Confirmed to be included when nms=True.
  6. Versions: Using the latest versions of all tools.

Next Steps:

Given that the CoreML model with nms=True still returns empty predictions, let's ensure the input preprocessing and post-processing steps are correctly handled. Here are a few additional checks and steps:

  1. Verify Input Preprocessing:
    Ensure the input image is preprocessed to match the model's expected format. This includes resizing and normalizing the image:

    from PIL import Image
    import numpy as np
    import coremltools as ct
    
    # Load the CoreML model
    coreml_model = ct.models.MLModel('path/to/your/model.mlpackage')
    
    # Load and preprocess the image
    image = Image.open('path/to/test/image.jpg').resize((640, 640))
    image_np = np.array(image).astype(np.float32) / 255.0  # Normalize if required
    
    # Make a prediction
    prediction = coreml_model.predict({'image': image_np})
    print(prediction)
  2. Check Post-Processing:
    Ensure that the post-processing steps, such as applying the confidence and IoU thresholds, are correctly implemented in your CoreML model. This can sometimes be a source of issues if not properly configured.

  3. Inspect Model Metadata:
    Verify that the model metadata includes the correct class labels and other necessary information:

    import coremltools as ct
    
    # Load the CoreML model
    coreml_model = ct.models.MLModel('path/to/your/model.mlpackage')
    
    # Inspect metadata
    print(coreml_model.user_defined_metadata)
  4. Test with Different Confidence Thresholds:
    Try adjusting the confidence threshold to see if it affects the predictions:

    coreml_model.user_defined_metadata['Confidence threshold'] = '0.1'
    coreml_model.save('path/to/your/updated_model.mlpackage')

If the issue persists, please provide a more detailed minimum reproducible example, including the specific steps and code used for training, exporting, and testing the model. This will help us reproduce the issue on our end and investigate further. You can refer to our minimum reproducible example guide for more details.

Thank you for your patience and cooperation. We're here to help you get this resolved! 😊

@tardoe
Copy link
Author

tardoe commented Jun 21, 2024

Thanks,

  1. The process you provided isn't valid, you can't pass a numpy array to coremltools.model.predict()
  2. As far as I know, these are correct in the exported metadata.
  3. This is confirmed correct
  4. Setting a low confidence of 0.01 does offer any predictions.

@glenn-jocher
Copy link
Member

Hi @tardoe,

Thank you for your detailed feedback and for confirming the steps you've taken. Let's address your points to help resolve the issue:

  1. CoreMLTools Prediction:
    You're right; CoreMLTools requires a PIL.Image.Image object for prediction. Apologies for the confusion. Here's the correct approach:

    from PIL import Image
    import coremltools as ct
    
    # Load the CoreML model
    coreml_model = ct.models.MLModel('path/to/your/model.mlpackage')
    
    # Load and preprocess the image
    image = Image.open('path/to/test/image.jpg').resize((640, 640))
    
    # Make a prediction
    prediction = coreml_model.predict({'image': image})
    print(prediction)
  2. Metadata Verification:
    It's good to hear that the metadata is correct. This ensures that the model should theoretically work as expected.

  3. Input Format:
    Confirmed to be correct, which is crucial for accurate predictions.

  4. Low Confidence Threshold:
    If setting a low confidence threshold still doesn't yield predictions, it might indicate an issue with the model's post-processing or the way predictions are handled in CoreML.

Next Steps:

To further diagnose the issue, could you please provide a minimum reproducible example of your code and dataset configuration? This will help us reproduce the bug and investigate a solution. You can find guidelines for creating a minimum reproducible example here.

Additionally, please ensure you are using the latest versions of torch, ultralytics, and coremltools. Sometimes, updates can resolve unexpected issues.

Thank you for your cooperation and patience. We're here to help you get this resolved! 😊

@tardoe
Copy link
Author

tardoe commented Jun 21, 2024

  1. I've provided this example above that illustrates the exact issue:
>>> from PIL import Image
>>> import numpy as np
>>> coreml_model = ct.models.MLModel('cpe_id/cpe_id_2/runs/detect/train3/weights/best.mlpackage')
>>> image = Image.open('/Users/tim/Development/cpe-id/cpe_id_model/cpe_id/cpe_id_2/dataset/test/images/tplink_vx220g2v_21.jpg')
>>> prediction = coreml_model.predict({'image': image})
>>> prediction
{'coordinates': array([], shape=(0, 4), dtype=float32), 'confidence': array([], shape=(0, 44), dtype=float32)}

@glenn-jocher
Copy link
Member

Hi @tardoe,

Thank you for providing the code example and detailed information. Let's work through this together to resolve the issue.

Steps to Diagnose and Resolve:

  1. Verify Latest Versions:
    Ensure you are using the latest versions of torch, ultralytics, and coremltools. Sometimes, updates can resolve unexpected issues. You can upgrade your packages using:

    pip install --upgrade torch ultralytics coremltools
  2. Check Model Export:
    Ensure the model is exported correctly with NMS enabled. This is crucial for proper predictions in CoreML:

    model.export(format="coreml", nms=True, half=False, imgsz=640)
  3. CoreML Prediction:
    Use the following code to test predictions with CoreMLTools:

    from PIL import Image
    import coremltools as ct
    
    # Load the CoreML model
    coreml_model = ct.models.MLModel('path/to/your/model.mlpackage')
    
    # Load and preprocess the image
    image = Image.open('path/to/test/image.jpg').resize((640, 640))
    
    # Make a prediction
    prediction = coreml_model.predict({'image': image})
    print(prediction)
  4. Inspect Metadata:
    Verify that the model metadata includes the correct class labels and other necessary information:

    import coremltools as ct
    
    # Load the CoreML model
    coreml_model = ct.models.MLModel('path/to/your/model.mlpackage')
    
    # Inspect metadata
    print(coreml_model.user_defined_metadata)

If the issue persists, please provide a more detailed minimum reproducible example, including the specific steps and code used for training, exporting, and testing the model. This will help us reproduce the issue on our end and investigate further. You can refer to our minimum reproducible example guide for more details.

Thank you for your cooperation and patience. We're here to help you get this resolved! 😊

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

2 participants