Reputation: 2591
Is there any way to EASILY use a Caffe Snapshot to predict a new Image?
and by "EASILY" I mean:
train.prototxt
to deploy.prototxt
by hand and careful considerations.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
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:
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
}
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