Reading protobuf DB in Python
Caffe uses Google Protocol buffer and LMDB or LevelDB to save data in a single unified database file. This allows faster data loading.
Saving Database in LMDB
I will not cover this step. If you are using ImageNet, CIFAR10, MNIST or some common datasets, please refer to Caffe examples to make LMDB or LevelDB databases.
Loading the Dataset
All the data has to be first converted into a common protobuf Caffe Datum
format. The protobuf message for the Dataum
is defined in caffe.proto
file.
Copy the following excerpt from caffe.proto
to datum.proto
and follow the instruction and compile it.
message Datum {
optional int32 channels = 1;
optional int32 height = 2;
optional int32 width = 3;
// the actual image data, in bytes
optional bytes data = 4;
optional int32 label = 5;
// Optionally, the datum could also hold float data.
repeated float float_data = 6;
// If true data contains an encoded image that need to be decoded
optional bool encoded = 7 [default = false];
}
Reading LMDB CIFAR10 in Python
import os
import lmdb
import numpy
import matplotlib.pyplot as plt
# First compile the Datum, protobuf so that we can load using protobuf
# This will create datum_pb2.py
os.system('protoc -I={0} --python_out={1} {0}datum.proto'.format("./", "./"))
import datum_pb2
LMDB_PATH = "/path/to/caffe/examples/cifar10/cifar10_train_lmdb/"
env = lmdb.open(LMDB_PATH, readonly=True, lock=False)
visualize = True
datum = datum_pb2.Datum()
with env.begin() as txn:
cur = txn.cursor()
for i in xrange(10):
if not cur.next():
cur.first()
# Read the current cursor
key, value = cur.item()
# convert to datum
datum.ParseFromString(value)
# Read the datum.data
img_data = numpy.array(bytearray(datum.data))\
.reshape(datum.channels, datum.height, datum.width)
if visualize:
plt.imshow(img_data.transpose([1,2,0]))
plt.show()
print key
Loading a binaryproto file
The mean of the data sometimes drastically affect the training. Caffe
provides an elegant way to compute mean of data and creates mean.binaryproto
file. To load, use the following excerpt from Caffe
issue pages 1.
Create blob.proto
and put the following scripts into the file.
// Specifies the shape (dimensions) of a Blob.
message BlobShape {
repeated int64 dim = 1 [packed = true];
}
message BlobProto {
optional BlobShape shape = 7;
repeated float data = 5 [packed = true];
repeated float diff = 6 [packed = true];
// 4D dimensions -- deprecated. Use "shape" instead.
optional int32 num = 1 [default = 0];
optional int32 channels = 2 [default = 0];
optional int32 height = 3 [default = 0];
optional int32 width = 4 [default = 0];
}
// The BlobProtoVector is simply a way to pass multiple blobproto instances
// around.
message BlobProtoVector {
repeated BlobProto blobs = 1;
}
To load the file in python, compile the above blob.proto
(or just put the above proto on datum).
mean_blob = blob_pb2.BlobProto()
data = open(os.path.join(LMDB_PATH, "mean.binaryproto"), 'rb').read()
mean_blob.ParseFromString(data)
img_mean = np.array(mean_blob.data).reshape(mean_blob.num,
mean_blob.channels,
mean_blob.height,
mean_blob.width)
https://github.com/BVLC/caffe/issues/290 ↩
Leave a Comment