2017-06-20 4 views
3

Je travaille pour comprendre CoreML. Pour un modèle de démarrage, j'ai téléchargé Yahoo's Open NSFW caffemodel. Vous lui donnez une image, il vous donne un score de probabilité (entre 0 et 1) que l'image contient un contenu inapproprié.Conversion du modèle Caffe en CoreML

En utilisant coremltools, j'ai converti le modèle en .mlmodel et l'a introduit dans mon application. Il apparaît dans Xcode comme ceci:

enter image description here

Dans mon application, je peux passer avec succès une image, et la sortie apparaît comme un MLMultiArray. Là où j'ai du mal à comprendre comment utiliser ce MLMultiArray pour obtenir mon score de probabilité. Mon code est comme ceci:

func testModel(image: CVPixelBuffer) throws { 

    let model = myModel() 
    let prediction = try model.prediction(data: image) 
    let output = prediction.prob // MLMultiArray 
    print(output[0]) // 0.9992402791976929 
    print(output[1]) // 0.0007597212097607553 
} 

Pour référence, le CVPixelBuffer est redimensionnée à la nécessaire 224x224 que le modèle demande (je vais en jouer avec Vision une fois que je peux comprendre cela).

Les deux index que j'ai imprimés sur la console changent si je fournis une image différente, mais leurs scores sont très différents du résultat obtenu si j'exécute le modèle en Python. La même image passée dans le modèle en Python me donne une sortie de 0.16, alors que ma sortie CoreML, par l'exemple ci-dessus, est très différente (et un dictionnaire, contrairement au double résultat de Python) que ce que je m'attends à voir.

Est-ce qu'il y a plus de travail nécessaire pour obtenir un résultat comme je m'y attendais?

+0

Je ne pense pas que vous ayez besoin de redimensionner le tampon manuellement. Je pense que CoreML gère cela pour vous – Guig

+0

Je crois que cela peut seulement être le cas lors de l'utilisation de Vision. Si seulement en utilisant CoreML lui-même, je crois que le tampon doit être redimensionné (je peux confirmer, il jette une erreur si je passe le CVPixelBuffer sans redimensionnement). – ZbadhabitZ

+0

Droite. Sauf si vous aimez écrire, réécrire et conserver le code de gestion d'image, il est beaucoup plus simple d'utiliser Vision pour envoyer des images à votre modèle. – rickster

Répondre

2

Il semble que vous ne transformiez pas l'image d'entrée de la même manière que le modèle l'attend.
La plupart des modèles caffe attendent des images «soustraites moyennes» en entrée, de même que ce modèle. Si vous regardez le code python fourni avec Yahoo's Open NSFW (classify_nsfw.py):

# Note that the parameters are hard-coded for best results 
caffe_transformer = caffe.io.Transformer({'data': nsfw_net.blobs['data'].data.shape}) 
caffe_transformer.set_transpose('data', (2, 0, 1)) # move image channels to outermost 
caffe_transformer.set_mean('data', np.array([104, 117, 123])) # subtract the dataset-mean value in each channel 
caffe_transformer.set_raw_scale('data', 255) # rescale from [0, 1] to [0, 255] 
caffe_transformer.set_channel_swap('data', (2, 1, 0)) # swap channels from RGB to BGR 

il y a une manière spécifique aussi une image est resized to 256x256 and then cropped to 224x224. Pour obtenir exactement les mêmes résultats, vous devez transformer votre image d'entrée exactement de la même manière sur les deux plates-formes. Pour plus d'informations, voir this thread pour plus d'informations.

+0

C'est tout à fait logique! J'avais examiné le fichier classify_nsfw.py, mais j'avais espéré que le cadre Vision s'occuperait de tout cela pour moi. Lorsque cela a échoué, j'ai choisi d'utiliser CoreML, mais je n'ai pas pensé à la nécessité d'ajuster l'image. Il est temps de comprendre comment faire toutes ces conversions! – ZbadhabitZ

+2

@ZbadhabitZ - En plus de ce que Shai a souligné, vous pouvez essayer de définir 'is_bgr = True' pour' caffe.convert() 'lors de la génération de votre mlmodel, car la plupart des modèles Caffe utilisent des entrées BGR.Par défaut, Core ML convertira en supposant une entrée RVB, et j'imagine que l'échange des canaux de couleur aurait un grand impact sur la précision de quelque chose à la recherche de tons de peau humaine. –

+0

@BradLarson Merci pour ça! J'avais essayé de convertir le modèle avec coremltools en utilisant le drapeau is_bgr dans les deux sens, sans différence. La réponse de Shai devra probablement être abordée en premier, puis je vais essayer à nouveau le modèle avec l'ensemble de balises is_bgr. Merci pour le commentaire! – ZbadhabitZ