As the subject states, I’m having problems making a model adapter for image data. Specifically, I don’t work around the api method. For all of the examples in the documetation, pm.Pandas() is used. Of course, for my task, I need images as inputs, not Pandas. When I saw the list of available functions in the palantir_models library, these seemed promising:
Object
ObjectSet
Pandas
However, I don’t know how to use them, and the lack of examples is making this workflow pretty difficult. Here’s what I have so far, with comments abstracting what I don’t know how to do:
class ImageGeolocatorV1Adapter(pm.ModelAdapter):
@pm.auto_serialize(
model=PytorchStateSerializer()
)
def __init__(self, model):
self.model = model
# Input image preprocessing steps
self.transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
@classmethod
def api(cls):
# Define inputs, outputs
return inputs, outputs
def predict(self, image_in):
# Some way to load the images
image = self.transform(image).unsqueeze(0).to(device) # Convert to Tensor
image = image.to(torch.device('cpu'))
# Run the model to predict latitude and longitude
self.model.eval()
with torch.no_grad():
prediction = self.model(image)
# Return the output (latitude, longitude) as the most convenient format
Thanks for flagging! Are you sure this is still the case? It is explicitly listed as supported here, and the source code I posted above is from an example using it (Disclaimer; I did not verify that example).
Of course, using this requires wrapping your input as tabular so if you want to avoid that using base64 is probably easier. Media references are also not supported as outputs.
Hey! This works for the most part, and it is relatively easy to implement. I’ve submitted the model, but I’m getting a different error when testing it out via the Sandbox tool.
TypeError: Compose.__call__() got an unexpected keyword argument 'image_base64'
I’m following an example, and my inputs and outputs match pretty closely. I must be overlooking something entirely; I can’t quite tell what the error is. The model’s .predict() function seems to work fine (I was able to pass in an input in my Code Workspace and it worked), but there seems to be an error elsewhere.
class ImageGeolocatorV1Adapter(pm.ModelAdapter):
@pm.auto_serialize(
model=pms.DillSerializer()
)
def __init__(self, model):
self.model = model
self.transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(
mean=[0.485, 0.456, 0.406],
std=[0.229, 0.224, 0.225])
])
@classmethod
def api(cls):
inputs = {
"image_base64": pm.Parameter(type=str),
}
outputs = {
"coordinates": pm.Parameter(type=dict),
}
return inputs, outputs
def predict(self, image_base64):
image_data = base64.b64decode(image_base64)
# Convert the byte data to an image
image = Image.open(BytesIO(image_data)).convert('RGB')
image = self.transform(image).unsqueeze(0)
with torch.no_grad():
outputs = self.model(image)
latitude, longitude = outputs.squeeze().cpu().numpy()
result = {'latitude': latitude.item(), 'longitude': longitude.item()}
return result
I’ve found the issue! Seems like the image_base64 input was getting passed into all constructor members, which wasn’t an intended effect. I simply had to move my self.transform variable within the self.predict() method. Thanks for the help!!