Cypher
Cypher

Reputation: 2591

Caffe: Predict an image from snapshot as simple as possible

Is there any way to EASILY use a Caffe Snapshot to predict a new Image?

and by "EASILY" I mean:

  1. no changing the train.prototxt to deploy.prototxt by hand and careful considerations.
  2. no converting the files to LMDB (or some other format like that) and just using plain simple image files (without any filename lists or stuff)
  3. only using python code (and no CLI)

I have trained a binary classification network based on the Caffe MNIST Example. I changed MNIST to be used for classifying 2 classes and it trains really good. But now that I'm finished training the network and generating the Snapshot (containing 'snapshot.caffemodel' and 'solver.caffemodel') I'm stuck on how to use this snapshot to predict JUST ONE image without all the hassle...

my current code is (and I really prefer if I could do the prediction as simple as this):

#I'M NOT SURE IF I SHOULD USE 'caffe.Net(...)' OR 'caffe.Classifier(...)'
net = caffe.Classifier('Data/train.prototxt',
                       'Data/Snapshot_iter_1000.caffemodel',
                       mean=convertBinaryProtoToNPY('Data/mean_image.binaryproto'),
                       image_dims=(100, 100),
                       raw_scale=255)

score = net.predict([caffe.io.load_image('/Data/Images/1.jpg')])
print score

I got this error:

File "C:\Anaconda2\lib\site-packages\caffe\classifier.py", line 29, in __init__ in_ = self.inputs[0]
IndexError: list index out of range

and after searching I found out that I shouldn't be using 'train.prototxt' but something called 'deploy.prototxt'.

the current way Caffe handles things sometimes seems too complex especially for trivial tasks such as predicting an image using a snapshot... maybe I'm doing things the wrong way...

Upvotes: 4

Views: 1094

Answers (1)

Shai
Shai

Reputation: 114796

You do need to manually change your train_val.prototxt to deploy.protoxt.
However, this change is easier than you think.

copy train_val.prototxt to a new deploy.prototxt and edit deploy.prototxt according to the following steps:

First change: the inputs.

Instead of using the training/validation datasets (usually represented as "Data"/"HDF5Data"/"Imagedata" layers), you need to tell caffe to allocate memory to an image that you will later provide manually.
To do so you need to delete the existing input layers (for both TRAIN and TEST phases), and replace them with:

layer {
  name: "input"
  type: "Input"
  top: "data"  # or whatever was the name of the "top" of the training input. no need for "label" top - you do not have ground truth labels in test.
  input_param { shape: { dim: 1 dim: 3 dim: 100 dim: 100 } } # give caffe the expected dimensions of your input for memory allocation
}

Second change: the net's output.

During training, your net outputs loss, rather than prediction.
So, first remove all loss layers (in particular, any layer that expects to get "label" as "bottom"). This includes "SoftmaxWithLoss"/"Accuracy"/"SigmoidCrossEntropyLoss" etc.
You need to replace the loss layer with appropriate prediction layer. For instance, "SoftmaxWithLoss" layer should be replaced by a simple "Softmax" layer, "SigmoidCrossEntropy" layer should be replaced with "Sigmoid" layer and so on.
Hence, if you had something like

layer {
  type: "SoftmaxWithLoss"
  name: "loss"
  bottom: "fc8"  # we need this name !
  bottom: "label"
  ...
}

Replace it with:

layer {
  name: "prob"
  type: "Softmax"
  bottom: "fc8" # the SAME as the train loss layer!
  top: "prob"
}

save you changes and now you have a proper deploy.prototxt.

For more info see this post.

Upvotes: 3

Related Questions