使用Caffe预训练模型预测时报错:TypeError: unhashable type: 'numpy.ndarray'
Let's break down why you're hitting this error and how to fix it step by step:
Root Cause
The error comes from how you're passing the image to net.forward():
res = net.forward({image})
Here, {image} tries to create a dictionary where the key is the numpy array image—but numpy arrays are unhashable, which is why Python throws that TypeError. Caffe expects you to pass a dictionary where the key is the name of your network's input blob (like 'data' for LeNet) and the value is the preprocessed image data.
Step-by-Step Fix
1. Use the Correct Input Blob Name
First, check your lenet_train_test.prototxt—the input layer is almost certainly named data. That's the key you need to use in the dictionary for net.forward().
2. Preprocess the Image to Match Caffe's Requirements
Caffe expects input data in a specific format (different from OpenCV's default):
- Channel-first order (
CHWinstead of OpenCV'sHWC) - Batch dimension added (since networks are designed for batch processing)
- Normalization/matching the mean value used during training (critical for accurate predictions)
3. Corrected Code
Here's the fixed version with proper preprocessing:
import caffe import cv2 import numpy as np # Set Caffe mode (CPU or GPU) caffe.set_mode_cpu() # caffe.set_mode_gpu() # Uncomment if you have GPU support # Load model and weights (note: for prediction, it's better to use deploy.prototxt instead of train_test.prototxt) model = 'lenet_train_test.prototxt' weights = 'lenet_iter_10000.caffemodel' net = caffe.Net(model, weights, caffe.TEST) # Load and preprocess image image = cv2.imread('test1.png', cv2.IMREAD_GRAYSCALE) # LeNet uses grayscale images image = image.astype(np.float32) # Resize to match LeNet's input size (typically 28x28) image = cv2.resize(image, (28, 28)) # Normalize (adjust based on your training mean/scale; example assumes mean 0, scale 1/255) image /= 255.0 # Add channel and batch dimensions: (H, W) -> (1, 1, H, W) (1 channel for grayscale, 1 batch) image = image[np.newaxis, np.newaxis, :, :] # Forward pass with correct input blob name net.blobs['data'].data[...] = image # Alternative way to set input res = net.forward() # Get the prediction result prediction = res['prob'].argmax() # Assuming your output blob is named 'prob' print(f"Predicted class: {prediction}")
Additional Notes
- Use deploy.prototxt: Your current code uses
lenet_train_test.prototxt, which includes training layers likeDataorLoss. For inference, it's better to use adeploy.prototxtthat removes training-specific layers and usesInputlayer instead. - Mean Subtraction: If you used a mean file during training, add this step after loading the image:
mean_file = 'mean.binaryproto' mean_blob = caffe.proto.caffe_pb2.BlobProto() with open(mean_file, 'rb') as f: mean_blob.ParseFromString(f.read()) mean = caffe.io.blobproto_to_array(mean_blob)[0] image -= mean[0] # Subtract grayscale mean
内容的提问来源于stack exchange,提问作者Zhe Ma

