Does LMDB data layer automatically do mean subtraction?

288 views
Skip to first unread message

zic...@ualberta.ca

unread,
Apr 28, 2016, 3:20:26 PM4/28/16
to Caffe Users
Hi,

I'm training a conv net on grayscale images, which were simply copied to 3 channels and in range [0,255.] before saving to lmdb.
I verified that the image looks normal when reading from lmdb with the following code:
lmdb_file = "/usr/work/data/train_lmdb" 
lmdb_env = lmdb.open(lmdb_file, readonly=True)
lmdb_txn = lmdb_env.begin()
lmdb_cursor = lmdb_txn.cursor()
datum = caffe.proto.caffe_pb2.Datum()
  
i = 0
print "Starting reading"
for key, value in lmdb_cursor:
  if i < 1:
    print 'iteration: ', i
    datum.ParseFromString(value)
    label = datum.label
    flat_x = np.fromstring(datum.data, dtype=np.float32)
    x = flat_x.reshape(datum.channels, datum.height, datum.width)
    print 'label: ', label
    i += 1
  else:
    break
lmdb_env.close()
plt.imshow(
x.transpose(1,2,0)/255, cmap=plt.cm.gray)
plt.show()




Now the training does not seem to work from the beginning. I checked the data to make sure it's correct. But the image looks strange to me. 


I wonder if caffe does mean subtraction even if it's not defined in the net model. Below is the model of the data layer. And I was just doing this to visualize:

plt.imshow(solver.test_nets[0].blobs['data'].data[0,...].transpose(1,2,0)/255, cmap=plt.cm.gray)
plt
.show()
plt
.imshow(solver.net.blobs['data'].data[0,...].transpose(1,2,0)/255, cmap=plt.cm.gray)
plt
.show()


layer {
  name
: "data"
  type
: "Data"
  top
: "data"
  top
: "label"
  data_param
{
    source
: "/usr/work/data/train_lmdb"
    backend
: LMDB
    batch_size
: 50
 
}
  include
{
    phase
: TRAIN
 
}
}
layer
{
  name
: "data"
  type
: "Data"
  top
: "data"
  top
: "label"
  data_param
{
    source
: "/usr/work/data/test_lmdb"
    backend
: LMDB
    batch_size
: 50
 
}
  include
{
    phase
: TEST
 
}
}


Does anyone spot any possible issue?

Thanks,
Vincent  

zic...@ualberta.ca

unread,
Apr 28, 2016, 4:15:47 PM4/28/16
to Caffe Users
I'm thinking maybe the way I created lmdb wasn't what caffe was expecting?
Below is a simplified version of how I saved the data to lmdb:
# Resized image
X = np.zeros((100, 3, RESIZE_HEIGHT, RESIZE_WIDTH), dtype=np.float32)
# this is the label
y = np.array(img_labels, dtype=np.int32)
map_size = X.nbytes * 50
# Read the images into X
X = ...

...

# write to lmdb
      env = lmdb.open(test_lmdb, map_size=map_size)
      with env.begin(write=True) as txn:
        for i in xrange(100):
          print "Image id: ", i
          datum = caffe.proto.caffe_pb2.Datum()
          datum.channels = X.shape[1]
          datum.height = X.shape[2]
          datum.width = X.shape[3]
          datum.float_data = X[i].tobytes()
          datum.label = int(y[i])
          str_id = '{:08}'.format(i)
          txn.put(str_id.encode('ascii'), datum.SerializeToString())


zic...@ualberta.ca

unread,
Apr 28, 2016, 4:19:35 PM4/28/16
to Caffe Users
Sorry there was a typo:

datum.float_data = X[i].tobytes()



should be
:


datum
.data = X[i].tobytes()

I've also corrected it inline below.

I wanted to save the image(type:float32) as float number into lmdb. I was suspecting that there's something wrong with using datum.data instead of datum.float_data, so I was just doing some testing to see. Not sure yet.

On Thursday, April 28, 2016 at 2:15:47 PM UTC-6, zic...@ualberta.ca wrote:
I'm thinking maybe the way I created lmdb wasn't what caffe was expecting?
Below is a simplified version of how I saved the data to lmdb:
# Resized image
X = np.zeros((100, 3, RESIZE_HEIGHT, RESIZE_WIDTH), dtype=np.float32)
# this is the label
y = np.array(img_labels, dtype=np.int32)
map_size = X.nbytes * 50
# Read the images into X
X = ...

...

# write to lmdb
      env = lmdb.open(test_lmdb, map_size=map_size)
      with env.begin(write=True) as txn:
        for i in xrange(100):
          print "Image id: ", i
          datum = caffe.proto.caffe_pb2.Datum()
          datum.channels = X.shape[1]
          datum.height = X.shape[2]
          datum.width = X.shape[3]
          datum.data = X[i].tobytes()

zic...@ualberta.ca

unread,
Apr 28, 2016, 6:12:28 PM4/28/16
to Caffe Users
Just figured it out. In case anyone comes across similar issues, here's the solution:

The issue was that when I saved the float number image data into lmdb, I incorrectly converted them into bytes and put it into datum.data instead of float_data. When caffe reads from it, I think it interprets it as integer so the input data to the net is totally messed up. 
The correct way is to use the filed float_data in Datum message:
datum.float_data.extend(X[i]) when saving image X[i] into datum.
Reply all
Reply to author
Forward
0 new messages