macOS Sierra (10.12.4)下Caffe执行Python代码报告错误“Mean shape incompatible with input shape”

在执行macOS Sierra (10.12.4)下Caffe通过Python接口加载binaryproto格式的均值文件的时候,最后报告错误:

Traceback (most recent call last):
  File "analysis_memnet.py", line 29, in <module>
    detector = caffe.Detector(model_def, pretrained_model, mean=means)
  File "/Users/Source/caffe/distribute/python/caffe/detector.py", line 46, in __init__
    self.transformer.set_mean(in_, mean)
  File "/Users/Source/caffe/distribute/python/caffe/io.py", line 259, in set_mean
    raise ValueError('Mean shape incompatible with input shape.')
ValueError: Mean shape incompatible with input shape.

这个错误发生的原因是由于memnet提供的均值文件是256*256的,但是提供的配置文件却是227*227的,导致在io.py里面的代码在进行判断的时候发生异常。调整源代码中的python/caffe/io.py里面的代码:

    def set_mean(self, in_, mean):
        """
        Set the mean to subtract for centering the data.

        Parameters
        ----------
        in_ : which input to assign this mean.
        mean : mean ndarray (input dimensional or broadcastable)
        """
        self.__check_input(in_)
        ms = mean.shape
        if mean.ndim == 1:
            # broadcast channels
            if ms[0] != self.inputs[in_][1]:
                raise ValueError('Mean channels incompatible with input.')
            mean = mean[:, np.newaxis, np.newaxis]
        else:
            # elementwise mean
            if len(ms) == 2:
                ms = (1,) + ms
            if len(ms) != 3:
                raise ValueError('Mean shape invalid')
            if ms != self.inputs[in_][1:]:
                raise ValueError('Mean shape incompatible with input shape.')
        self.mean[in_] = mean

调整为:

    def set_mean(self, in_, mean):
        """
        Set the mean to subtract for centering the data.

        Parameters
        ----------
        in_ : which input to assign this mean.
        mean : mean ndarray (input dimensional or broadcastable)
        """
        self.__check_input(in_)
        ms = mean.shape
        if mean.ndim == 1:
            # broadcast channels
            if ms[0] != self.inputs[in_][1]:
                raise ValueError('Mean channels incompatible with input.')
            mean = mean[:, np.newaxis, np.newaxis]
        else:
            # elementwise mean
            if len(ms) == 2:
                ms = (1,) + ms
            if len(ms) != 3:
                raise ValueError('Mean shape invalid')
            if ms != self.inputs[in_][1:]:
                in_shape = self.inputs[in_][1:]
                m_min, m_max = mean.min(), mean.max()
                normal_mean = (mean - m_min) / (m_max - m_min)
                mean = resize_image(normal_mean.transpose((1,2,0)),in_shape[1:]).transpose((2,0,1)) * (m_max - m_min) + m_min
                #raise ValueError('Mean shape incompatible with input shape.')
        self.mean[in_] = mean

调整完成后,需要重新编译Caffe:

$ make clean
$ make
$ make pycaffe
$ make distribute

参考链接


macOS Sierra (10.12.4)下Caffe通过Python接口加载binaryproto格式的均值文件

macOS Sierra (10.12.4)下Caffe通过Python接口加载均值文件的时候,都是加载的.npy格式的文件,这个格式是Python存储的格式,跟我们经常下载到的.binaryproto格式的均值文件是不同的,这样就导致了加载问题。
.binaryprotoGoogleProtocol Buffer序列化后的数据,而.npy格式是Pythonnumpy模块序列化后的数据。

之所以会出现两种不同的存储格式,目前猜测是由于目前Python 3不能很好的支持Protocol Buffer导致的。

Python下是不能直接加载.binaryproto格式的数据的,必须进行一次转换才行,示例代码如下:

#coding=utf-8
#加载必要的库
import numpy as np
 
import sys,os

#设置当前目录
caffe_root = '/Users/Source/caffe/distribute/'
sys.path.append(caffe_root + 'python')

import caffe
os.chdir(caffe_root)

memnet_root = '/Users/Source/caffe/'
model_def =memnet_root + 'models/memnet/deploy.prototxt'
pretrained_model=memnet_root + 'models/memnet/memnet.caffemodel'
means_file=memnet_root + 'models/memnet/mean.binaryproto'

caffe.set_mode_cpu() 
blobProto=caffe.io.caffe_pb2.BlobProto()
binProtoFile=open(means_file,'rb')
blobProto.ParseFromString(binProtoFile.read())
means = caffe.io.blobproto_to_array(blobProto)[0]
binProtoFile.close()

# Make detector.
detector = caffe.Detector(model_def, pretrained_model, mean=means)

参考链接