It seems that I have some conversion issue using `coremltool` and a trained .caffemodel. I was able to train and test `caffe` dogs model (120 categories, 20k images) and it passed my tests with direct `caffe` classifications. Unfortunately, after converting to `mlmodel` it doesn't give me a valid prediction on the same input.
Traning model
The model has been trained using Caffe, GoogleNet, set of 20k images over 120 categories packed into lmdb and about 500k iterations. I've prepared images database and all the rest and put all files together here
Classification with `caffe`
This classification example by `caffe`. When I'm trying to run a classification request against the trained `caffemodel` - it works just great, high probability (80-99%), right results
https://i.stack.imgur.com/KR9q2.jpg
Classification with `Apple` `iOS 11` `CoreML`
Unfortunately, when I'm trying to pack this `DTDogs.caffemodel` & `deploy.txt` into .mlmodel consumable by Apple iOS 11 `CoreML` I have different prediction results. Actually, no errors loading and using the model but I'm unable to get valid classifications, all the predictions are 0-15% confidence and have wrong labels. In order to test it properly I'm using exactly the same images I used for the direct classification with `caffe`. I've also tried the pre-trained and pre-packed models with my iOS app from here - they work just fine so it seems to be an issue with packing procedure.
https://i.stack.imgur.com/acaAn.jpg
What did I miss?
---
Here is the example of classification with `caffe`: no issues, right answers (`python`):
import numpy as np
import sys
import caffe
import os
import urllib2
import matplotlib.pyplot as plt
%matplotlib inline
test_folder = '/home/<username>/Desktop/CaffeTest/'
test_image_path = "http://cdn.akc.org/content/hero/irish-terrier-Hero.jpg"
# init caffe net
model_def = test_folder + 'deploy.prototxt'
model_weights = test_folder + 'DTDogs.caffemodel'
# caffe.set_mode_gpu()
net = caffe.Net(model_def, model_weights, caffe.TEST)
# prepare transformer
transformer = caffe.io.Transformer({'data': net.blobs['data'].data.shape})
transformer.set_transpose('data', (2,0,1))
transformer.set_raw_scale('data', 255)
transformer.set_channel_swap('data', (2,1,0))
net.blobs['data'].reshape(1, 3, 256, 256)
test_image = urllib2.urlopen(test_image_path)
with open(test_folder + 'testImage.jpg','wb') as output:
output.write(test_image.read())
image = caffe.io.load_image(test_folder + 'testImage.jpg')
transformed_image = transformer.preprocess('data', image)
net.blobs['data'].data[...] = transformed_image
# classify
output = net.forward()
output_prob = output['prob'][0]
output_prob_val = output_prob.max() * 100
output_prob_ind = output_prob.argmax()
labels_file = test_folder + 'labels.txt'
labels = np.loadtxt(labels_file, str, delimiter='\t')
plt.imshow(image)
print 'predicted class is:', output_prob_ind
print 'predicted probabily is:', output_prob_val
print 'output label:', labels[output_prob_ind]
---
Here is the example of packing the `DTDogs.mlmodel` model using `coremltools`. I see that resulted `.mlmodel` file is twice smaller then the original `.caffemodel` but it's probably some kind of archiving or compression optimisation by `coremltools` (`python`):
import coremltools;
caffe_model = ('DTDogs.caffemodel', 'deploy.prototxt')
labels = 'labels.txt'
coreml_model = coremltools.converters.caffe.convert(caffe_model, class_labels = labels, image_input_names= "data")
coreml_model.short_description = "Dogs Model v1.14"
coreml_model.save('DTDogs.mlmodel')
---
Here is an example of using the `DTDogs.mlmodel` in the app. I'm using a regular image picker to pick the same image I used for the `.caffe` classification test (`swift`):
funcimagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
picker.dismiss(animated: true)
print("Analyzing Image…")
guard let uiImage = info[UIImagePickerControllerOriginalImage] as? UIImage
else { print("no image from image picker"); return }
guard let ciImage = CIImage(image: uiImage)
else { print("can't create CIImage from UIImage"); return }
imageView.image = uiImage
do {
let model = try VNCoreMLModel(for: DTDogs().model)
let classificationRequest = VNCoreMLRequest(model: model, completionHandler: self.handleClassification)
let orientation = CGImagePropertyOrientation(uiImage.imageOrientation)
let handler = VNImageRequestHandler(ciImage: ciImage, orientation: Int32(orientation.rawValue))
try handler.perform([classificationRequest])
} catch {
print(error)
}
}