Model Prediction

After converting a source model to a Core ML model, you can evaluate the Core ML model by verifying that the predictions made by the Core ML model match the predictions made by the source model.

The following example makes predictions for the HousePricer.mlmodel using the predict() method.

import coremltools as ct

# Load the model
model = ct.models.MLModel('HousePricer.mlmodel')

# Make predictions
predictions = model.predict({'bedroom': 1.0, 'bath': 1.0, 'size': 1240})

📘

macOS required for model prediction

For the prediction API, coremltools interacts with the Core ML framework which is available on macOS only. The prediction API is not available on Linux.

However, Core ML models can be imported and executed with TVM, which may provide a way to test Core ML models on non-macOS systems.

Types of inputs and outputs

Core ML supports several feature types for inputs and outputs. The following are two feature types that are commonly used with neural network models:

  • ArrayFeatureType, which maps to the MLMultiArray Feature Value in Swift
  • ImageFeatureType, which maps to the Image Feature Value in Swift

When using the Core ML model in your Xcode app, use an MLFeatureValue, which wraps an underlying value and bundles it with that value’s type, represented by MLFeatureType.

To evaluate a Core ML model in python using the predict method, use one of the following inputs:

  • For a multi-array, use a numpy array.
  • For an image, use a PIL image python object.

📘

Learn more about image inputs

To learn how to work with images as inputs and achieve better performance and more convenience, see Image Inputs.

Multi-array prediction

A model that takes a MultiArray input requires a numpy array as an input with the predict() call. For example:

import coremltools as ct
import numpy as np

model = ct.models.MLModel('path/to/the/saved/model.mlmodel')

# print input description to get input shape
print(model.get_spec().description.input)

input_shape = (...) # insert correct shape of the input

# call predict
output_dict = model.predict({'input_name': np.random.rand(*input_shape)}, useCPUOnly=True)

Image prediction

A model that takes an image input requires a PIL image as an input with the predict() call. For example:

import coremltools as ct
import numpy as np
import PIL.Image

# load a model whose input type is "Image"
model = ct.models.MLModel('path/to/the/saved/model.mlmodel')

Height = 20  # use the correct input image height
Width = 60  # use the correct input image width


# Scenario 1: load an image from disk
def load_image(path, resize_to=None):
    # resize_to: (Width, Height)
    img = PIL.Image.open(path)
    if resize_to is not None:
        img = img.resize(resize_to, PIL.Image.ANTIALIAS)
    img_np = np.array(img).astype(np.float32)
    return img_np, img


# load the image and resize using PIL utilities
_, img = load_image('/path/to/image.jpg', resize_to=(Width, Height))
out_dict = model.predict({'image': img})

# Scenario 2: load an image from a numpy array
shape = (Height, Width, 3)  # height x width x RGB
data = np.zeros(shape, dtype=np.uint8)
# manipulate numpy data
pil_img = PIL.Image.fromarray(data)
out_dict = model.predict({'image': pil_img})

Image prediction for a multi-array model

If the Core ML model has a MultiArray input type that actually represents a jpeg image, you can still use the jpeg image for the prediction if you first convert the loaded image to a numpy array, as shown in this example:

Height = 20  # use the correct input image height
Width = 60  # use the correct input image width

# assumption: the mlmodel's input is of type MultiArray and of shape (1, 3, Height, Width)
model_expected_input_shape = (1, 3, Height, Width) # depending on the model description, this could be (3, Height, Width)

# load the model
model = coremltools.models.MLModel('path/to/the/saved/model.mlmodel')

def load_image_as_numpy_array(path, resize_to=None):
    # resize_to: (Width, Height)
    img = PIL.Image.open(path)
    if resize_to is not None:
        img = img.resize(resize_to, PIL.Image.ANTIALIAS)
    img_np = np.array(img).astype(np.float32) # shape of this numpy array is (Height, Width, 3)
    return img_np

# load the image and resize using PIL utilities
img_as_np_array = load_image_as_numpy_array('/path/to/image.jpg', resize_to=(Width, Height)) # shape (Height, Width, 3)

# note that PIL returns an image in the format in which the channel dimension is in the end,
# which is different than Core ML's input format, so that needs to be modified
img_as_np_array = np.transpose(img_as_np_array, (2,0,1)) # shape (3, Height, Width)

# add the batch dimension if the model description has it
img_as_np_array = np.reshape(img_as_np_array, model_expected_input_shape)

# now call predict
out_dict = model.predict({'image': img_as_np_array})