Exemple #1
0
    def __setstate__(self, state):
        super(ImageClassificationDatasetJob, self).__setstate__(state)

        if self.pickver_job_dataset_image_classification <= 1:
            print 'Upgrading ImageClassificationDatasetJob to version 2'
            task = self.train_db_task()
            if task.image_dims[2] == 3:
                if task.encoding == "jpg":
                    if task.mean_file.endswith('.binaryproto'):
                        print '\tConverting mean file "%s" from RGB to BGR.' % task.path(
                            task.mean_file)
                        import numpy as np
                        import caffe_pb2

                        old_blob = caffe_pb2.BlobProto()
                        with open(task.path(task.mean_file), 'rb') as infile:
                            old_blob.ParseFromString(infile.read())
                        data = np.array(old_blob.data).reshape(
                            old_blob.channels, old_blob.height, old_blob.width)
                        data = data[[2, 1, 0], ...]  # channel swap
                        new_blob = caffe_pb2.BlobProto()
                        new_blob.num = 1
                        new_blob.channels, new_blob.height, new_blob.width = data.shape
                        new_blob.data.extend(data.astype(float).flat)
                        with open(task.path(task.mean_file), 'wb') as outfile:
                            outfile.write(new_blob.SerializeToString())
                else:
                    print '\tSetting "%s" status to ERROR because it was created with RGB channels' % self.name(
                    )
                    self.status = Status.ERROR
                    for task in self.tasks:
                        task.status = Status.ERROR
                        task.exception = 'This dataset was created with unencoded RGB channels. Caffe requires BGR input.'

        self.pickver_job_dataset_image_classification = PICKLE_VERSION
Exemple #2
0
 def create_mean_file(self):
     filename = os.path.join(self.job_dir, constants.MEAN_FILE_IMAGE)
     # don't recreate file if it already exists
     if not os.path.exists(filename):
         mean_file = self.dataset.get_mean_file()
         assert mean_file != None and mean_file.endswith(
             '.binaryproto'
         ), 'Mean subtraction required but dataset has no mean file in .binaryproto format'
         blob = caffe_pb2.BlobProto()
         with open(self.dataset.path(mean_file), 'rb') as infile:
             blob.ParseFromString(infile.read())
         data = np.array(blob.data,
                         dtype=np.uint8).reshape(blob.channels, blob.height,
                                                 blob.width)
         if blob.channels == 3:
             # converting from BGR to RGB
             data = data[[2, 1, 0], ...]  # channel swap
             # convert to (height, width, channels)
             data = data.transpose((1, 2, 0))
         else:
             assert blob.channels == 1
             # convert to (height, width)
             data = data[0]
         # save to file
         image = PIL.Image.fromarray(data)
         image.save(filename)
     return filename
Exemple #3
0
    def save_mean(self, feature_sum, entry_count, dataset_dir, stage):
        """
        Save mean to file
        """
        data = np.around(feature_sum / entry_count).astype(np.uint8)
        mean_file = os.path.join(stage, 'mean.binaryproto')
        # Transform to caffe's format requirements
        if data.ndim == 3:
            if data.shape[0] == 3:
                # channel swap
                # XXX see issue #59
                data = data[[2, 1, 0], ...]
        elif data.ndim == 2:
            # Add a channels axis
            data = data[np.newaxis, :, :]

        blob = caffe_pb2.BlobProto()
        blob.num = 1
        blob.channels, blob.height, blob.width = data.shape
        blob.data.extend(data.astype(float).flat)

        with open(os.path.join(dataset_dir, mean_file), 'wb') as outfile:
            outfile.write(blob.SerializeToString())

        logger.info('Created mean file for stage %s in %s' %
                    (stage, mean_file))
def readMeanFile(mean_path=''):
    with open(mean_path, 'rb') as f:
        blob = caffe_proto.BlobProto()
        blob.ParseFromString(f.read())
        f.close()
        return {
            'data': blob.data._values,
            # 'channels':blob.channels,
            # 'width':blob.width,
            # 'height':blob.height
        }
Exemple #5
0
def array_to_blobproto(arr, diff=None):
    """Converts a N-dimensional array to blob proto. If diff is given, also
    convert the diff. You need to make sure that arr and diff have the same
    shape, and this function does not do sanity check.
    """
    blob = caffe_pb2.BlobProto()
    blob.shape.dim.extend(arr.shape)
    blob.data.extend(arr.astype(float).flat)
    if diff is not None:
        blob.diff.extend(diff.astype(float).flat)
    return blob
Exemple #6
0
def array_to_blobproto(arr, diff=None):
    """Converts a 4-dimensional array to blob proto. If diff is given, also
  convert the diff. You need to make sure that arr and diff have the same
  shape, and this function does not do sanity check.
  """
    if arr.ndim != 4:
        raise ValueError('Incorrect array shape.')
    blob = caffe_pb2.BlobProto()
    blob.num, blob.channels, blob.height, blob.width = arr.shape
    blob.data.extend(arr.astype(float).flat)
    if diff is not None:
        blob.diff.extend(diff.astype(float).flat)
    return blob
Exemple #7
0
def convert_array_to_blob(arr):
    """convert numpy array to caffe blob
    Parameters
    ==========
    arr: np.array
        array

    Returns
    =======
    blob: caffe.BlobProto
        blob
    """
    blob = caffe_pb2.BlobProto()
    blob.shape.dim.extend(arr.shape)
    blob.data.extend(arr.flatten())
    return blob
Exemple #8
0
def show_alpha(iter):
    blob_file = blob_file_tpl % iter
    blob = caffe_pb2.BlobProto()
    f = open(blob_file, 'rb')
    blob.ParseFromString(f.read())
    f.close()

    print 'blob: %sx%sx%sx%s' % (blob.num, blob.channels, blob.height,
                                 blob.width)

    img = np.zeros((blob.height, blob.width), dtype=np.uint8)

    for idx, p in enumerate(blob.data):
        value = min(max((p + 1.0) * 128, 0), 255)
        img[idx / blob.width, idx % blob.width] = np.uint8(value)

    # cv2.imshow("alpha", img)
    cv2.imwrite(blob_file + ".bmp", img)
Exemple #9
0
    def get_transformer(self):
        """
        Returns an instance of caffe.io.Transformer
        """
        # check if already loaded
        if hasattr(self, '_transformer') and self._transformer is not None:
            return self._transformer

        data_shape = (1, self.dataset.image_dims[2])
        if self.crop_size:
            data_shape += (self.crop_size, self.crop_size)
        else:
            data_shape += (self.dataset.image_dims[0],
                           self.dataset.image_dims[1])

        t = caffe.io.Transformer(inputs={'data': data_shape})
        t.set_transpose('data',
                        (2, 0, 1))  # transpose to (channels, height, width)

        if self.dataset.image_dims[2] == 3 and \
                self.dataset.train_db_task().image_channel_order == 'BGR':
            # channel swap
            # XXX see issue #59
            t.set_channel_swap('data', (2, 1, 0))

        if self.use_mean:
            # set mean
            with open(self.dataset.path(
                    self.dataset.train_db_task().mean_file)) as f:
                blob = caffe_pb2.BlobProto()
                blob.MergeFromString(f.read())
                pixel = np.reshape(blob.data, (
                    self.dataset.image_dims[2],
                    self.dataset.image_dims[0],
                    self.dataset.image_dims[1],
                )).mean(1).mean(1)
                t.set_mean('data', pixel)

        #t.set_raw_scale('data', 255) # [0,255] range instead of [0,1]

        self._transformer = t
        return self._transformer
Exemple #10
0
def generate_submit_file(iter):
    out_file = open(out_file_tpl % iter, 'w')
    out_file.write(header)
    f_idx = 0
    line_idx = 0
    while os.path.isfile(blob_file_tpl % (iter, f_idx)):
        blob_file = blob_file_tpl % (iter, f_idx)
        blob = caffe_pb2.BlobProto()
        f = open(blob_file, 'rb')
        blob.ParseFromString(f.read())
        f.close()
        print 'blob: %sx%sx%sx%s' % (blob.num, blob.channels, blob.height,
                                     blob.width)

        for i in range(blob.num):
            print >> out_file, '%s,' % f_name[line_idx] + ','.join(
                map(str, blob.data[i * 121:(i + 1) * 121]))
            line_idx += 1
        f_idx += 1
    out_file.close()
Exemple #11
0
def _save_mean(mean, filename):
    """
    Saves mean to file

    Arguments:
    mean -- the mean as an np.ndarray
    filename -- the location to save the image
    """
    if filename.endswith('.binaryproto'):
        blob = caffe_pb2.BlobProto()
        blob.num = 1
        blob.channels = mean.shape[0]
        blob.height = mean.shape[1]
        blob.width = mean.shape[2]
        blob.data.extend(mean.astype(float).flat)
        with open(filename, 'wb') as outfile:
            outfile.write(blob.SerializeToString())

    elif filename.endswith(('.jpg', '.jpeg', '.png')):
        _save_image(mean, filename)
    else:
        raise ValueError('unrecognized file extension')
Exemple #12
0
def _save_means(image_sum, image_count, mean_files):
    """
    Save mean[s] to file
    """
    mean = np.around(image_sum / image_count).astype(np.uint8)
    for mean_file in mean_files:
        if mean_file.lower().endswith('.npy'):
            np.save(mean_file, mean)
        elif mean_file.lower().endswith('.binaryproto'):
            data = mean
            # Transform to caffe's format requirements
            if data.ndim == 3:
                # Transpose to (channels, height, width)
                data = data.transpose((2, 0, 1))
                if data.shape[0] == 3:
                    # channel swap
                    # XXX see issue #59
                    data = data[[2, 1, 0], ...]
            elif mean.ndim == 2:
                # Add a channels axis
                data = data[np.newaxis, :, :]

            blob = caffe_pb2.BlobProto()
            blob.num = 1
            blob.channels, blob.height, blob.width = data.shape
            blob.data.extend(data.astype(float).flat)

            with open(mean_file, 'wb') as outfile:
                outfile.write(blob.SerializeToString())
        elif mean_file.lower().endswith(('.jpg', '.jpeg', '.png')):
            image = PIL.Image.fromarray(mean)
            image.save(mean_file)
        else:
            logger.warning('Unrecognized file extension for mean file: "%s"' %
                           mean_file)
            continue

        logger.info('Mean saved at "%s"' % mean_file)
Exemple #13
0
                    help='Path to model.caffemodel')
parser.add_argument('--data',
                    help='Print all arrays in full',
                    action='store_true')
parser.add_argument(
    '--codegenDir',
    help=
    'Path to an existing temporary directory to save generated protobuf Python classes',
    default=tempfile.mkdtemp())
args = parser.parse_args()

local_caffe_proto = os.path.join(args.codegenDir,
                                 os.path.basename(args.caffe_proto))
with open(local_caffe_proto, 'w') as f:
    f.write((urllib2.urlopen(args.caffe_proto)
             if 'http' in args.caffe_proto else open(args.caffe_proto)).read())

subprocess.check_call([
    'protoc', '--proto_path',
    os.path.dirname(local_caffe_proto), '--python_out', args.codegenDir,
    local_caffe_proto
])
sys.path.insert(0, args.codegenDir)
import caffe_pb2

deserialized = caffe_pb2.NetParameter() if os.path.splitext(
    args.model_caffemodel)[1] == '.caffemodel' else caffe_pb2.BlobProto()
deserialized.ParseFromString(open(args.model_caffemodel, 'rb').read())

json.dump(pb2json(deserialized, args.data), sys.stdout, indent=2)
Exemple #14
0
def as_blob(array):
    blob = pb2.BlobProto()
    blob.shape.dim.extend(array.shape)
    blob.data.extend(array.astype(float).flat)
    return blob
Exemple #15
0
    def create(self, input_file, width, height,
            channels    = 3,
            resize_mode = None,
            image_folder= None,
            shuffle     = True,
            mean_files  = None,
            encoding    = 'none',
            ):
        """
        Read an input file and create a database from the specified image/label pairs
        Returns True on success

        Arguments:
        input_file -- gives paths to images and their label (e.g. "path/to/image1.jpg 0\npath/to/image2.jpg 3")
        width -- width of resized images
        height -- width of resized images

        Keyword arguments:
        channels -- channels of resized images
        resize_mode -- can be crop, squash, fill or half_crop
        image_folder -- folder in which the images can be found
        shuffle -- shuffle images before saving
        mean_files -- an array of mean files to save (can be empty)
        encoding -- 'none', 'png' or 'jpg'
        """
        ### Validate input

        if not os.path.exists(input_file):
            logger.error('input_file does not exist')
            return False
        if height <= 0:
            logger.error('unsupported image height')
            return False
        self.height = height
        if width <= 0:
            logger.error('unsupported image width')
            return False
        self.width = width
        if channels not in [1,3]:
            logger.error('unsupported number of channels')
            return False
        self.channels = channels
        if resize_mode not in ['crop', 'squash', 'fill', 'half_crop']:
            logger.error('unsupported resize_mode')
            return False
        self.resize_mode = resize_mode
        if image_folder is not None and not os.path.exists(image_folder):
            logger.error('image_folder does not exist')
            return False
        self.image_folder = image_folder
        if mean_files:
            for mean_file in mean_files:
                if os.path.exists(mean_file):
                    logger.warning('overwriting existing mean file "%s"!' % mean_file)
                else:
                    dirname = os.path.dirname(mean_file)
                    if not dirname:
                        dirname = '.'
                    if not os.path.exists(dirname):
                        logger.error('Cannot save mean file at "%s"' % mean_file)
                        return False
        self.compute_mean = (mean_files and len(mean_files) > 0)
        if encoding not in ['none', 'png', 'jpg']:
            raise ValueError('Unsupported encoding format "%s"' % encoding)
        self.encoding = encoding

        ### Start working

        start = time.time()

        # TODO: adjust these values in real-time based on system load
        if not shuffle:
            #XXX This is the only way to preserve order for now
            # This obviously hurts performance considerably
            read_threads = 1
            write_threads = 1
        else:
            read_threads = 10
            write_threads = 10
        batch_size = 100

        total_images_added = 0
        total_image_sum = None

        # NOTE: The data could really stack up in these queues
        self.read_queue = Queue.Queue()
        self.write_queue = Queue.Queue(2*batch_size)

        # Tells read threads that if read_queue is empty, they can stop
        self.read_queue_built = threading.Event()
        self.read_thread_results = Queue.Queue()
        # Tells write threads that if write_queue is empty, they can stop
        self.write_queue_built = threading.Event()
        self.write_thread_results = Queue.Queue()

        # Read input_file and produce items to read_queue
        # NOTE This secion should be very efficient, because no progress about the job gets reported until after the read/write threads start
        lines_read = 0
        lines_per_category = {}
        with open(input_file, 'r') as f:
            lines = f.readlines()
            if shuffle:
                random.shuffle(lines)
            for line in lines:
                # Expect format - [/]path/to/file.jpg 123
                match = re_match(r'(.+)\s+(\d+)\s*$', line)
                if match is not None:
                    path = match.group(1)
                    label = int(match.group(2))
                    self.read_queue.put( (path, label) )
                    if label not in lines_per_category:
                        lines_per_category[label] = 1
                    else:
                        lines_per_category[label] += 1
                    lines_read += 1
        self.read_queue_built.set()

        if lines_read > 0:
            logger.info('Input images: %d' % lines_read)
        else:
            logger.error('no lines in input_file')
            return False

        for key in sorted(lines_per_category):
            logger.debug('Category %s has %d images.' % (key, lines_per_category[key]))

        # Start read threads
        for i in xrange(read_threads):
            p = threading.Thread(target=self.read_thread)
            p.daemon = True
            p.start()

        # Start write threads
        for i in xrange(write_threads):
            first_batch = int(batch_size * (i+1)/write_threads)
            p = threading.Thread(target=self.write_thread, args=(batch_size, first_batch))
            p.daemon = True
            p.start()

        # Wait for threads to finish
        wait_time = time.time()
        read_threads_done = 0
        write_threads_done = 0
        total_images_written = 0
        while write_threads_done < write_threads:
            if self.shutdown.is_set():
                # Die immediately
                return False

            # Send update every 2 seconds
            if time.time() - wait_time > 2:
                logger.debug('Processed %d/%d' % (lines_read - self.read_queue.qsize(), lines_read))
                #print '\tRead queue size: %d' % self.read_queue.qsize()
                #print '\tWrite queue size: %d' % self.write_queue.qsize()
                #print '\tRead threads done: %d' % read_threads_done
                #print '\tWrite threads done: %d' % write_threads_done
                wait_time = time.time()

            if not self.write_queue_built.is_set() and read_threads_done == read_threads:
                self.write_queue_built.set()

            while not self.read_thread_results.empty():
                images_added, image_sum = self.read_thread_results.get()
                total_images_added += images_added
                # Update total_image_sum
                if self.compute_mean and images_added > 0 and image_sum is not None:
                    if total_image_sum is None:
                        total_image_sum = image_sum
                    else:
                        total_image_sum += image_sum
                read_threads_done += 1

            while not self.write_thread_results.empty():
                result = self.write_thread_results.get()
                total_images_written += result
                write_threads_done += 1

            try:
                time.sleep(0.2)
            except KeyboardInterrupt:
                self.shutdown.set()
                return False

        if total_images_added == 0:
            logger.error('no images added')
            return False

        # Compute image mean
        if self.compute_mean and total_image_sum is not None:
            mean = np.around(total_image_sum / total_images_added).astype(np.uint8)
            for mean_file in mean_files:
                if mean_file.lower().endswith('.npy'):
                    np.save(mean_file, mean)
                elif mean_file.lower().endswith('.binaryproto'):
                    data = mean
                    # Transform to caffe's format requirements
                    if data.ndim == 3:
                        # Transpose to (channels, height, width)
                        data = data.transpose((2,0,1))
                        if data.shape[0] == 3:
                            # channel swap
                            # XXX see issue #59
                            data = data[[2,1,0],...]
                    elif mean.ndim == 2:
                        # Add a channels axis
                        data = data[np.newaxis,:,:]

                    blob = caffe_pb2.BlobProto()
                    blob.num = 1
                    blob.channels, blob.height, blob.width = data.shape
                    blob.data.extend(data.astype(float).flat)

                    with open(mean_file, 'w') as outfile:
                        outfile.write(blob.SerializeToString())
                elif mean_file.lower().endswith(('.jpg', '.jpeg', '.png')):
                    image = PIL.Image.fromarray(mean)
                    image.save(mean_file)
                else:
                    logger.warning('Unrecognized file extension for mean file: "%s"' % mean_file)
                    continue

                logger.info('Mean saved at "%s"' % mean_file)

        logger.info('Database created after %d seconds.' % (time.time() - start))
        logger.info('Total images added: %d' % total_images_written)

        self.shutdown.set()
        return True
Exemple #16
0
# https://raw.githubusercontent.com/BVLC/caffe/master/src/caffe/proto/caffe.proto
codegenDir = os.path.dirname(os.path.abspath(__file__)) + '/tmp'
if not os.path.exists(codegenDir): os.makedirs(codegenDir)
local_caffe_proto = os.path.join(codegenDir, 'caffe.proto')

subprocess.check_call([
    'protoc', '--proto_path',
    os.path.dirname(local_caffe_proto), '--python_out', codegenDir,
    local_caffe_proto
])
sys.path.insert(0, codegenDir)
import caffe_pb2

deserialized = caffe_pb2.NetParameter() if os.path.splitext(
    args.mpath)[1] == '.caffemodel' else caffe_pb2.BlobProto()
deserialized.ParseFromString(open(args.mpath, 'rb').read())

# json.dump(pb2json(deserialized, args.data), sys.stdout, indent = 2)
jsobj = pb2json(deserialized, False)
with open('small.json', 'w') as jsfile:
    json.dump(jsobj, jsfile, indent=2)

if weight is not None: npobj[npname + '.weight'] = weight
if bias is not None: npobj[npname + '.bias'] = bias
weight = None
bias = None
np.save('m', npobj)

# a = np.load('m.npy')
# m = a[()]
Exemple #17
0
import csv
import base64

labels = list()

with open('./stanford-cars-model/labels.csv', 'rb') as csvfile:
    labels_data = csv.reader(csvfile, delimiter=',')
    for row in labels_data:
        labels.append(row[1])

import caffe
import caffe_pb2

caffe.set_mode_cpu()

mean_blob = caffe_pb2.BlobProto()
with open('./stanford-cars-model/mean.binaryproto') as f:
    mean_blob.ParseFromString(f.read())
mean_array = numpy.asarray(mean_blob.data, dtype=numpy.float32).reshape(
    (mean_blob.channels, mean_blob.height, mean_blob.width))

model_def = './stanford-cars-model/deploy.prototxt'
model_weights = './stanford-cars-model/caffe_model_1_iter_22169.caffemodel'

net = caffe.Net(
    model_def,  # defines the structure of the model
    model_weights,  # contains the trained weights
    caffe.TEST)  # use test mode (e.g., don't perform dropout)

net.blobs['data'].reshape(
    1,  # batch size
Exemple #18
0
 def getBlob(weight):
     blob = caffe_pb2.BlobProto()
     blob.raw_data_type = caffe_pb2.FLOAT
     blob.raw_data = weight.data.tobytes()
     blob.shape.dim.extend(weight.shape)
     return blob
with zipfile.ZipFile('weights.zip', 'w') as f:
    for l in cq2.layer:
        if hasattr(l, 'blobs'):
            if len(l.blobs) > 0:
                name = l.name

                count = 0
                for b in l.blobs:
                    data = np.array(b.data, dtype=np.float32)
                    shape = np.array(b.shape.dim, dtype=np.int32)

                    data = data.reshape(shape)
                    data = _to_npy_str(data)

                    save_name = name + ('-%d.npy' % count)
                    count += 1

                    f.writestr(save_name, data)

                    print(save_name)

# parse the mean file
# note that the channels for caffe model are BGR not RGB
# https://github.com/BVLC/caffe/wiki/Image-Format:-BGR-not-RGB
with open('places365CNN_mean.binaryproto', 'rb') as f:
    cq3 = cq.BlobProto()
    cq3.ParseFromString(f.read())

mean_img = np.array(cq3.data).reshape((cq3.channels, cq3.height, cq3.width))
np.save('places365CNN_mean.npy', mean_img)
Exemple #20
0
    def save_prototxt_files(self):
        """
        Save solver, train_val and deploy files to disk
        """

        has_val_set = self.dataset.val_db_task() is not None

        ### Check what has been specified in self.network

        tops = []
        bottoms = {}
        train_data_layer = None
        val_data_layer = None
        hidden_layers = caffe_pb2.NetParameter()
        loss_layers = []
        accuracy_layers = []
        for layer in self.network.layer:
            assert layer.type not in ['MemoryData', 'HDF5Data', 'ImageData'
                                      ], 'unsupported data layer type'
            if layer.type == 'Data':
                for rule in layer.include:
                    if rule.phase == caffe_pb2.TRAIN:
                        assert train_data_layer is None, 'cannot specify two train data layers'
                        train_data_layer = layer
                    elif rule.phase == caffe_pb2.TEST:
                        assert val_data_layer is None, 'cannot specify two test data layers'
                        val_data_layer = layer
            elif layer.type == 'SoftmaxWithLoss':
                loss_layers.append(layer)
            elif layer.type == 'Accuracy':
                addThis = True
                if layer.accuracy_param.HasField('top_k'):
                    if layer.accuracy_param.top_k >= len(self.get_labels()):
                        self.logger.warning(
                            'Removing layer %s because top_k=%s while there are are only %s labels in this dataset'
                            % (layer.name, layer.accuracy_param.top_k,
                               len(self.get_labels())))
                        addThis = False
                if addThis:
                    accuracy_layers.append(layer)
            else:
                hidden_layers.layer.add().CopyFrom(layer)
                if len(layer.bottom) == 1 and len(
                        layer.top) == 1 and layer.bottom[0] == layer.top[0]:
                    pass
                else:
                    for top in layer.top:
                        tops.append(top)
                    for bottom in layer.bottom:
                        bottoms[bottom] = True

        if train_data_layer is None:
            assert val_data_layer is None, 'cannot specify a test data layer without a train data layer'

        assert len(loss_layers) > 0, 'must specify a loss layer'

        network_outputs = []
        for name in tops:
            if name not in bottoms:
                network_outputs.append(name)
        assert len(network_outputs), 'network must have an output'

        # Update num_output for any output InnerProduct layers automatically
        for layer in hidden_layers.layer:
            if layer.type == 'InnerProduct':
                for top in layer.top:
                    if top in network_outputs:
                        layer.inner_product_param.num_output = len(
                            self.get_labels())
                        break

        ### Write train_val file

        train_val_network = caffe_pb2.NetParameter()

        # data layers
        if train_data_layer is not None:
            if train_data_layer.HasField('data_param'):
                assert not train_data_layer.data_param.HasField(
                    'source'), "don't set the data_param.source"
                assert not train_data_layer.data_param.HasField(
                    'backend'), "don't set the data_param.backend"
            max_crop_size = min(self.dataset.image_dims[0],
                                self.dataset.image_dims[1])
            if self.crop_size:
                assert self.crop_size <= max_crop_size, 'crop_size is larger than the image size'
                train_data_layer.transform_param.crop_size = self.crop_size
            elif train_data_layer.transform_param.HasField('crop_size'):
                cs = train_data_layer.transform_param.crop_size
                if cs > max_crop_size:
                    # don't throw an error here
                    cs = max_crop_size
                train_data_layer.transform_param.crop_size = cs
                self.crop_size = cs
            train_val_network.layer.add().CopyFrom(train_data_layer)
            train_data_layer = train_val_network.layer[-1]
            if val_data_layer is not None and has_val_set:
                if val_data_layer.HasField('data_param'):
                    assert not val_data_layer.data_param.HasField(
                        'source'), "don't set the data_param.source"
                    assert not val_data_layer.data_param.HasField(
                        'backend'), "don't set the data_param.backend"
                if self.crop_size:
                    # use our error checking from the train layer
                    val_data_layer.transform_param.crop_size = self.crop_size
                train_val_network.layer.add().CopyFrom(val_data_layer)
                val_data_layer = train_val_network.layer[-1]
        else:
            train_data_layer = train_val_network.layer.add(type='Data',
                                                           name='data')
            train_data_layer.top.append('data')
            train_data_layer.top.append('label')
            train_data_layer.include.add(phase=caffe_pb2.TRAIN)
            train_data_layer.data_param.batch_size = constants.DEFAULT_BATCH_SIZE
            if self.crop_size:
                train_data_layer.transform_param.crop_size = self.crop_size
            if has_val_set:
                val_data_layer = train_val_network.layer.add(type='Data',
                                                             name='data')
                val_data_layer.top.append('data')
                val_data_layer.top.append('label')
                val_data_layer.include.add(phase=caffe_pb2.TEST)
                val_data_layer.data_param.batch_size = constants.DEFAULT_BATCH_SIZE
                if self.crop_size:
                    val_data_layer.transform_param.crop_size = self.crop_size
        train_data_layer.data_param.source = self.dataset.path(
            self.dataset.train_db_task().db_name)
        train_data_layer.data_param.backend = caffe_pb2.DataParameter.LMDB
        if val_data_layer is not None and has_val_set:
            val_data_layer.data_param.source = self.dataset.path(
                self.dataset.val_db_task().db_name)
            val_data_layer.data_param.backend = caffe_pb2.DataParameter.LMDB
        if self.use_mean:
            mean_pixel = None
            with open(self.dataset.path(
                    self.dataset.train_db_task().mean_file)) as f:
                blob = caffe_pb2.BlobProto()
                blob.MergeFromString(f.read())
                mean = np.reshape(blob.data, (
                    self.dataset.image_dims[2],
                    self.dataset.image_dims[0],
                    self.dataset.image_dims[1],
                ))
                mean_pixel = mean.mean(1).mean(1)
            for value in mean_pixel:
                train_data_layer.transform_param.mean_value.append(value)
            if val_data_layer is not None and has_val_set:
                for value in mean_pixel:
                    val_data_layer.transform_param.mean_value.append(value)
        if self.batch_size:
            train_data_layer.data_param.batch_size = self.batch_size
            if val_data_layer is not None and has_val_set:
                val_data_layer.data_param.batch_size = self.batch_size
        else:
            if not train_data_layer.data_param.HasField('batch_size'):
                train_data_layer.data_param.batch_size = constants.DEFAULT_BATCH_SIZE
            if val_data_layer is not None and has_val_set and not val_data_layer.data_param.HasField(
                    'batch_size'):
                val_data_layer.data_param.batch_size = constants.DEFAULT_BATCH_SIZE

        # hidden layers
        train_val_network.MergeFrom(hidden_layers)

        # output layers
        train_val_network.layer.extend(loss_layers)
        train_val_network.layer.extend(accuracy_layers)

        with open(self.path(self.train_val_file), 'w') as outfile:
            text_format.PrintMessage(train_val_network, outfile)

        ### Write deploy file

        deploy_network = caffe_pb2.NetParameter()

        # input
        deploy_network.input.append('data')
        deploy_network.input_dim.append(1)
        deploy_network.input_dim.append(self.dataset.image_dims[2])
        if self.crop_size:
            deploy_network.input_dim.append(self.crop_size)
            deploy_network.input_dim.append(self.crop_size)
        else:
            deploy_network.input_dim.append(self.dataset.image_dims[0])
            deploy_network.input_dim.append(self.dataset.image_dims[1])

        # hidden layers
        deploy_network.MergeFrom(hidden_layers)

        # output layers
        if loss_layers[-1].type == 'SoftmaxWithLoss':
            prob_layer = deploy_network.layer.add(type='Softmax', name='prob')
            prob_layer.bottom.append(network_outputs[-1])
            prob_layer.top.append('prob')

        with open(self.path(self.deploy_file), 'w') as outfile:
            text_format.PrintMessage(deploy_network, outfile)

        ### Write solver file

        solver = caffe_pb2.SolverParameter()
        # get enum value for solver type
        solver.solver_type = getattr(solver, self.solver_type)
        solver.net = self.train_val_file

        # Set CPU/GPU mode
        if config_value('caffe_root')['cuda_enabled'] and \
                bool(config_value('gpu_list')):
            solver.solver_mode = caffe_pb2.SolverParameter.GPU
        else:
            solver.solver_mode = caffe_pb2.SolverParameter.CPU

        solver.snapshot_prefix = self.snapshot_prefix

        # Epochs -> Iterations
        train_iter = int(
            math.ceil(
                float(self.dataset.train_db_task().entries_count) /
                train_data_layer.data_param.batch_size))
        solver.max_iter = train_iter * self.train_epochs
        snapshot_interval = self.snapshot_interval * train_iter
        if 0 < snapshot_interval <= 1:
            solver.snapshot = 1  # don't round down
        elif 1 < snapshot_interval < solver.max_iter:
            solver.snapshot = int(snapshot_interval)
        else:
            solver.snapshot = 0  # only take one snapshot at the end

        if has_val_set and self.val_interval:
            solver.test_iter.append(
                int(
                    math.ceil(
                        float(self.dataset.val_db_task().entries_count) /
                        val_data_layer.data_param.batch_size)))
            val_interval = self.val_interval * train_iter
            if 0 < val_interval <= 1:
                solver.test_interval = 1  # don't round down
            elif 1 < val_interval < solver.max_iter:
                solver.test_interval = int(val_interval)
            else:
                solver.test_interval = solver.max_iter  # only test once at the end

        # Learning rate
        solver.base_lr = self.learning_rate
        solver.lr_policy = self.lr_policy['policy']
        scale = float(solver.max_iter) / 100.0
        if solver.lr_policy == 'fixed':
            pass
        elif solver.lr_policy == 'step':
            # stepsize = stepsize * scale
            solver.stepsize = int(
                math.ceil(float(self.lr_policy['stepsize']) * scale))
            solver.gamma = self.lr_policy['gamma']
        elif solver.lr_policy == 'multistep':
            for value in self.lr_policy['stepvalue']:
                # stepvalue = stepvalue * scale
                solver.stepvalue.append(int(math.ceil(float(value) * scale)))
            solver.gamma = self.lr_policy['gamma']
        elif solver.lr_policy == 'exp':
            # gamma = gamma^(1/scale)
            solver.gamma = math.pow(self.lr_policy['gamma'], 1.0 / scale)
        elif solver.lr_policy == 'inv':
            # gamma = gamma / scale
            solver.gamma = self.lr_policy['gamma'] / scale
            solver.power = self.lr_policy['power']
        elif solver.lr_policy == 'poly':
            solver.power = self.lr_policy['power']
        elif solver.lr_policy == 'sigmoid':
            # gamma = -gamma / scale
            solver.gamma = -1.0 * self.lr_policy['gamma'] / scale
            # stepsize = stepsize * scale
            solver.stepsize = int(
                math.ceil(float(self.lr_policy['stepsize']) * scale))
        else:
            raise Exception('Unknown lr_policy: "%s"' % solver.lr_policy)

        # go with the suggested defaults
        if solver.solver_type != solver.ADAGRAD:
            solver.momentum = 0.9
        solver.weight_decay = 0.0005

        # Display 8x per epoch, or once per 5000 images, whichever is more frequent
        solver.display = max(
            1,
            min(
                int(
                    math.floor(
                        float(solver.max_iter) / (self.train_epochs * 8))),
                int(math.ceil(5000.0 /
                              train_data_layer.data_param.batch_size))))

        if self.random_seed is not None:
            solver.random_seed = self.random_seed

        with open(self.path(self.solver_file), 'w') as outfile:
            text_format.PrintMessage(solver, outfile)
        self.solver = solver  # save for later

        return True
Exemple #21
0
    def task_arguments(self, resources, env):
        if config_value('torch_root') == '<PATHS>':
            torch_bin = 'th'
        else:
            torch_bin = os.path.join(config_value('torch_root'), 'bin', 'th')

        dataset_backend = self.dataset.train_db_task().backend
        assert dataset_backend=='lmdb' or dataset_backend=='hdf5'

        args = [torch_bin,
                os.path.join(os.path.dirname(os.path.dirname(digits.__file__)),'tools','torch','main.lua'),
                '--network=%s' % self.model_file.split(".")[0],
                '--epoch=%d' % int(self.train_epochs),
                '--networkDirectory=%s' % self.job_dir,
                '--save=%s' % self.job_dir,
                '--snapshotPrefix=%s' % self.snapshot_prefix,
                '--snapshotInterval=%s' % self.snapshot_interval,
                '--learningRate=%s' % self.learning_rate,
                '--policy=%s' % str(self.lr_policy['policy']),
                '--dbbackend=%s' % dataset_backend
                ]

        if self.batch_size is not None:
            args.append('--batchSize=%d' % self.batch_size)

        if isinstance(self.dataset, ImageClassificationDatasetJob):
            args.append('--train=%s' % self.dataset.path(constants.TRAIN_DB))
            if os.path.exists(self.dataset.path(constants.VAL_DB)) and self.val_interval > 0:
                args.append('--validation=%s' % self.dataset.path(constants.VAL_DB))
            args.append('--mean=%s' % self.dataset.path(constants.MEAN_FILE_IMAGE))
            args.append('--labels=%s' % self.dataset.path(self.dataset.labels_file))
        elif isinstance(self.dataset, dataset.GenericImageDatasetJob):
            train_image_db = None
            train_labels_db = None
            val_image_db = None
            val_labels_db = None
            for task in self.dataset.tasks:
                if task.purpose == 'Training Images':
                    train_image_db = task
                if task.purpose == 'Training Labels':
                    train_labels_db = task
                if task.purpose == 'Validation Images':
                    val_image_db = task
                if task.purpose == 'Validation Labels':
                    val_labels_db = task
            assert train_image_db is not None, 'Training images are required'
            args.append('--train=%s' % train_image_db.path(train_image_db.database))
            if train_labels_db:
                args.append('--train_labels=%s' % train_labels_db.path(train_labels_db.database))
            if val_image_db:
                args.append('--validation=%s' % val_image_db.path(val_image_db.database))
            if val_labels_db:
                args.append('--validation_labels=%s' % val_labels_db.path(val_labels_db.database))
            if self.use_mean != 'none':
                assert self.dataset.mean_file.endswith('.binaryproto'), 'Mean subtraction required but dataset has no mean file in .binaryproto format'
                blob = caffe_pb2.BlobProto()
                with open(task.path(self.dataset.mean_file),'rb') as infile:
                    blob.ParseFromString(infile.read())
                data = np.array(blob.data, dtype=np.uint8).reshape(blob.channels, blob.height, blob.width)
                if blob.channels == 3:
                    # converting from BGR to RGB
                    data = data[[2,1,0],...] # channel swap
                    # convert to (height, width, channels)
                    data = data.transpose((1,2,0))
                else:
                    assert blob.channels == 1
                    # convert to (height, width)
                    data = data[0]
                 # save to file
                filename = os.path.join(self.job_dir, constants.MEAN_FILE_IMAGE)
                image = PIL.Image.fromarray(data)
                image.save(filename)
                args.append('--mean=%s' % filename)

        #learning rate policy input parameters
        if self.lr_policy['policy'] == 'fixed':
            pass
        elif self.lr_policy['policy'] == 'step':
            args.append('--gamma=%s' % self.lr_policy['gamma'])
            args.append('--stepvalues=%s' % self.lr_policy['stepsize'])
        elif self.lr_policy['policy'] == 'multistep':
            args.append('--stepvalues=%s' % self.lr_policy['stepvalue'])
            args.append('--gamma=%s' % self.lr_policy['gamma'])
        elif self.lr_policy['policy'] == 'exp':
            args.append('--gamma=%s' % self.lr_policy['gamma'])
        elif self.lr_policy['policy'] == 'inv':
            args.append('--gamma=%s' % self.lr_policy['gamma'])
            args.append('--power=%s' % self.lr_policy['power'])
        elif self.lr_policy['policy'] == 'poly':
            args.append('--power=%s' % self.lr_policy['power'])
        elif self.lr_policy['policy'] == 'sigmoid':
            args.append('--stepvalues=%s' % self.lr_policy['stepsize'])
            args.append('--gamma=%s' % self.lr_policy['gamma'])

        if self.shuffle:
            args.append('--shuffle=yes')

        if self.crop_size:
            args.append('--crop=yes')
            args.append('--croplen=%d' % self.crop_size)

        if self.use_mean == 'pixel':
            args.append('--subtractMean=pixel')
        elif self.use_mean == 'image':
            args.append('--subtractMean=image')
        else:
            args.append('--subtractMean=none')

        if self.random_seed is not None:
            args.append('--seed=%s' % self.random_seed)

        if self.solver_type == 'NESTEROV':
            args.append('--optimization=nag')

        if self.solver_type == 'ADAGRAD':
            args.append('--optimization=adagrad')

        if self.solver_type == 'SGD':
            args.append('--optimization=sgd')

        if self.val_interval > 0:
            args.append('--interval=%s' % self.val_interval)

        if 'gpus' in resources:
            identifiers = []
            for identifier, value in resources['gpus']:
                identifiers.append(int(identifier))
            if len(identifiers) == 1:
                # only one device must be visible to the th process
                # to prevent Torch from loading libraries on all GPUs
                env['CUDA_VISIBLE_DEVICES'] = str(identifiers[0])
                args.append('--devid=1')
            elif len(identifiers) > 1:
                raise NotImplementedError("Multi-GPU with Torch not supported yet")
        else:
            # switch to CPU mode
            args.append('--type=float')
            self.trained_on_cpu = True

        if self.pretrained_model:
            args.append('--weights=%s' % self.path(self.pretrained_model))

        return args
Exemple #22
0
builder.add_inner_product(name="ip2",
                          W=W,
                          b=b,
                          input_channels=64,
                          output_channels=10,
                          has_bias=True,
                          input_name="ip1_output",
                          output_name="ip2_output")

builder.add_softmax(name="softmax",
                    input_name="ip2_output",
                    output_name="labelProbs")

import caffe_pb2

mean_image = caffe_pb2.BlobProto()
mean_image.ParseFromString(open("mean.binaryproto", "rb").read())
mean_image = np.array(mean_image.data)
builder.spec.neuralNetworkClassifier.preprocessing[
    0].meanImage.meanImage.extend(mean_image)

mlmodel = coremltools.models.MLModel(builder.spec)

mlmodel.short_description = "cifar10_quick"
mlmodel.author = "https://github.com/BVLC/caffe/tree/master/examples/cifar10"
mlmodel.license = "https://github.com/BVLC/caffe/blob/master/LICENSE"

mlmodel.input_description["image"] = "The input image"
mlmodel.output_description["labelProbs"] = "The predicted probabilities"
mlmodel.output_description["label"] = "The class with the highest score"
Exemple #23
0
            print(f'export {name}')
            layer = net.layer.add()
            layer.name = name
            layer.type = 'Convolution'
            layer.bottom.append(bottom)
            layer.top.append(name)
            layer.convolution_param.num_output = module.out_channels
            layer.convolution_param.bias_term = module.bias is not None
            layer.convolution_param.pad.append(module.kernel_size[0] == 3)
            layer.convolution_param.kernel_size.append(module.kernel_size[0])
            layer.convolution_param.stride.append(module.stride[0])
            if residual and 'conv1' in name:
                skip_bottom = bottom  # first bottom of Eltwise layer
            bottom = name

            layer.blobs.append(pb.BlobProto())
            layer.blobs[-1].shape.dim.append(module.weight.size(0))
            layer.blobs[-1].shape.dim.append(module.weight.size(1))
            layer.blobs[-1].shape.dim.append(module.weight.size(2))
            layer.blobs[-1].shape.dim.append(module.weight.size(3))
            for data in module.weight.detach().cpu().numpy().flatten():
                layer.blobs[-1].data.append(data)
            if module.bias is not None:
                layer.blobs.append(pb.BlobProto())
                layer.blobs[-1].shape.dim.append(module.bias.size(0))
                for data in module.bias.detach().cpu().numpy().flatten():
                    layer.blobs[-1].data.append(data)
        elif isinstance(module, torch.nn.BatchNorm2d):  # BatchNorm and Scale
            print(f'export {name}')
            bn_layer = net.layer.add()
            bn_layer.name = name
Exemple #24
0
    def load_weights(self, weightfile):
        if self.blocks[0].has_key('mean_file'):
            import caffe_pb2
            mean_file = self.blocks[0]['mean_file']
            mean_file = mean_file.strip('"')
            self.has_mean = True
            blob = caffe_pb2.BlobProto()
            blob.ParseFromString(open(mean_file, 'rb').read())
            mean_img = torch.from_numpy(np.array(blob.data)).float()
            channels = int(self.blocks[0]['channels'])
            height = int(self.blocks[0]['height'])
            width = int(self.blocks[0]['width'])
            mean_img = mean_img.view(channels, height, width)

            self.register_buffer('mean_img',
                                 torch.zeros(channels, height, width))
            self.mean_img.copy_(mean_img)

        fp = open(weightfile, 'rb')
        header = np.fromfile(fp, count=4, dtype=np.int32)
        self.header = torch.from_numpy(header)
        self.seen = self.header[3]
        buf = np.fromfile(fp, dtype=np.float32)
        fp.close()

        start = 0
        ind = -2
        is_first = True
        for block in self.blocks:
            if start >= buf.size:
                break
            ind = ind + 1
            if block['type'] == 'net':
                continue
            elif block['type'] == 'convolutional':
                model = self.models[ind]
                batch_normalize = int(block['batch_normalize'])
                if batch_normalize:
                    start = load_conv_bn(buf, start, model[0], model[1])
                else:
                    start = load_conv(buf, start, model[0])
            elif block['type'] == 'connected':
                model = self.models[ind]
                if block['activation'] != 'linear':
                    if is_first:
                        start = load_fc(buf, start, model[1])
                        is_first = False
                    else:
                        start = load_fc(buf, start, model[0])
                else:
                    if is_first:
                        start = load_fc(buf, start, model[1])
                        is_first = False
                    else:
                        start = load_fc(buf, start, model)
            elif block['type'] == 'maxpool':
                pass
            elif block['type'] == 'reorg':
                pass
            elif block['type'] == 'route':
                pass
            elif block['type'] == 'shortcut':
                pass
            elif block['type'] == 'avgpool':
                pass
            elif block['type'] == 'softmax':
                pass
            elif block['type'] == 'cost':
                pass
            elif block['type'] == 'region':
                pass
            elif block['type'] == 'dropout':
                pass
            else:
                print('unknown type %s' % (block['type']))
    def load_weights(self, caffemodel):
        if self.net_info['props'].has_key('mean_file'):
            import caffe_pb2
            self.has_mean = True
            mean_file = self.net_info['props']['mean_file']
            blob = caffe_pb2.BlobProto()
            blob.ParseFromString(open(mean_file, 'rb').read())
            mean_img = torch.from_numpy(np.array(blob.data)).float()

            if self.net_info['props'].has_key('input_shape'):
                channels = int(self.net_info['props']['input_shape']['dim'][1])
                height = int(self.net_info['props']['input_shape']['dim'][2])
                width = int(self.net_info['props']['input_shape']['dim'][3])
            else:
                channels = int(self.net_info['props']['input_dim'][1])
                height = int(self.net_info['props']['input_dim'][2])
                width = int(self.net_info['props']['input_dim'][3])
            mean_img = mean_img.view(channels, height, width)  #.mean(0)
            #mean_img = mean_img.repeat(3, 1, 1)
            self.register_buffer('mean_img',
                                 torch.zeros(channels, height, width))
            self.mean_img.copy_(mean_img)

        model = parse_caffemodel(caffemodel)
        layers = model.layer
        if len(layers) == 0:
            print('Using V1LayerParameter')
            layers = model.layers

        lmap = {}
        for l in layers:
            lmap[l.name] = l

        layers = self.net_info['layers']
        layer_num = len(layers)
        i = 0
        while i < layer_num:
            layer = layers[i]
            lname = layer['name']
            ltype = layer['type']
            if ltype == 'Convolution':
                convolution_param = layer['convolution_param']
                bias = True
                if convolution_param.has_key(
                        'bias_term'
                ) and convolution_param['bias_term'] == 'false':
                    bias = False
                self.models[lname].weight.data.copy_(
                    torch.from_numpy(np.array(lmap[lname].blobs[0].data)))
                if bias and len(lmap[lname].blobs) > 1:
                    print('convlution %s has bias' % lname)
                    self.models[lname].bias.data.copy_(
                        torch.from_numpy(np.array(lmap[lname].blobs[1].data)))
                i = i + 1
            elif ltype == 'BatchNorm':
                scale_layer = layers[i + 1]
                self.models[lname].running_mean.copy_(
                    torch.from_numpy(
                        np.array(lmap[lname].blobs[0].data) /
                        lmap[lname].blobs[2].data[0]))
                self.models[lname].running_var.copy_(
                    torch.from_numpy(
                        np.array(lmap[lname].blobs[1].data) /
                        lmap[lname].blobs[2].data[0]))
                self.models[lname].weight.data.copy_(
                    torch.from_numpy(
                        np.array(lmap[scale_layer['name']].blobs[0].data)))
                self.models[lname].bias.data.copy_(
                    torch.from_numpy(
                        np.array(lmap[scale_layer['name']].blobs[1].data)))
                i = i + 2
            elif ltype == 'InnerProduct':
                if type(self.models[lname]) == nn.Sequential:
                    self.models[lname][1].weight.data.copy_(
                        torch.from_numpy(np.array(lmap[lname].blobs[0].data)))
                    if len(lmap[lname].blobs) > 1:
                        self.models[lname][1].bias.data.copy_(
                            torch.from_numpy(
                                np.array(lmap[lname].blobs[1].data)))
                else:
                    self.models[lname].weight.data.copy_(
                        torch.from_numpy(np.array(lmap[lname].blobs[0].data)))
                    if len(lmap[lname].blobs) > 1:
                        self.models[lname].bias.data.copy_(
                            torch.from_numpy(
                                np.array(lmap[lname].blobs[1].data)))
                i = i + 1
            elif ltype == 'Pooling' or ltype == 'Eltwise' or ltype == 'ReLU' or ltype == 'Region':
                i = i + 1
            else:
                print('load_weights: unknown type %s' % ltype)
                i = i + 1