def __init__()

in PyTorchClassification/data_loader.py [0:0]


    def __init__(self, root, ann_file, image_sizes, is_train, dataFormat2017=False, multi_crop=False,
                 percentUse=100, bbox_predictions=None, label_smoothing=0, bg_classes = None):
        ''' Initializes a dataset class.
        Paramters:
            *root* Path to the root directory of the dataset. The training and validation json paths will be
            relative to this one
            *ann_file* Path to json file containing the annotations, relative to *root*
            *image_sizes* List of integers representing the sizes of the input images for each model in an ensemble. If
            only one model is used, pass a list with one element, e.g. [224]
            *is_train* boolean representing whether this is the training or validation dataset. This value determines
            the preprocessing applied to the images.
            *dataFormat2017* boolean representing whether this is the 2017 annotation format. If False, the 2018 format is
            assumed.
            *multi_crop* If true, we perform over-sampling on load. This is useful for evaluation.
            *percentUse* Integer representing the percentage of data to use. Useful for profiling.
            *bbox_predictions* Optional path to corresponding bounding box annotations for the images in this dataset.
            *label_smoothing* Value in [0.0, 1.0) representing the amount of smoothing applied to targets. If 0.0, we
            force the network to predict with a confidence of 1.0 to predict the class. For values > 0, the target will
            be smoothed considering the taxonomy of the classes.
            *bg_classes* This class allows to use certain classes as background images, which means the target is 0 probability
            for each output element. The output corresponding output elements of the classes selected by bg_classes
            will be unused.
        '''
        # load annotations
        # import pdb; pdb.set_trace()
        print('Loading annotations from: ' + os.path.basename(ann_file))
        with open(ann_file) as data_file:
            ann_data = json.load(data_file)

        # set up the filenames and annotations
        self.imgs = [aa['file_name'] for aa in ann_data['images']]
        self.ids = [aa['id'] for aa in ann_data['images']]

        # if we dont have class labels set them to '0'
        if 'annotations' in ann_data.keys():
            im_to_cat = {aa['image_id']:aa['category_id'] for aa in ann_data['annotations']}
            self.classes = [im_to_cat[im_id] for im_id in self.ids]
        else:
            self.classes = [0]*len(self.imgs)

        # load taxonomy
        if (dataFormat2017):
            self.tax_levels = ['id', 'name', 'supercategory']
            #self.tax_levels = ['id', 'name']
            if label_smoothing > 0:
                assert len(self.tax_levels) == 3, "Please comment in the line above to include the taxonomy " + \
                    "level 'supercategory' in order for label smoothing to work. It should look like this: " + \
                    "self.tax_levels = ['id', 'name', 'supercategory']"
        else:
            self.tax_levels = ['id', 'genus', 'family', 'order', 'class', 'phylum', 'kingdom']
                               #8142, 4412,    1120,     273,     57,      25,       6

        self.taxonomy, self.classes_taxonomic, self.classnames = self.load_taxonomy(
                                             ann_data, self.tax_levels, self.classes)
        # Set targets 
        if label_smoothing > 0:
            # Build a list of the taxonomic assignment of each class
            # This is a list of list
            # tax_assignments[0] describes the assignment of each class at self.tax_levels[0]
            # tax_assignments[1] at the level of self.tax_levels[1], and so on
            tax_assignments = list(zip(*[[cc[tax_level] for tax_level in self.tax_levels] 
                                                        for cc in ann_data['categories']]))
            # Permute the class order to be 0, ..., num_classes-1 by assuming that 
            # tax_assignments[0] contains the class_ids as integer
            # First, compute how to permute the classes
            cat_permutation = np.argsort(tax_assignments[0])
            # Then apply the permutation to all lists
            # We cannot permute everything at once using numpy arrays as there are different dtype
            for tax_level in range(len(tax_assignments)):
                tax_assignments[tax_level] = np.array(tax_assignments[tax_level])[cat_permutation]
                # Also cut off the genus of the family name in 2017 format
            if dataFormat2017 and isinstance(tax_assignments[1][0], str):
                tax_assignments[1] = [ss.split(' ')[0] for ss in tax_assignments[1]]
                tax_assignments[1] = np.array(tax_assignments[1])
            else:
                raise Exception('Taxonomic label smoothing is not yet supported for the ' + \
                                '2018 annotation format.')

            # We create a matrix of realtionships of shape num_classes x num_classes
            # For now, we will store a number between 0 and len(self.tax_lavels)
            # with higher numbers denoting a closer relationship
            self.relationship = np.zeros((self.get_num_classes(), self.get_num_classes()))
            for tax_level, levelname in list(enumerate(self.tax_levels))[::-1]:
                assingm = tax_assignments[tax_level]
                self.relationship[assingm[:,None] == assingm[None,:]] = len(self.tax_levels) - tax_level

            # Compute the probability mass to be distributed for same genus, same family, etc
            # Start with the relative weights for each level: 2**(level)
            prob_per_tax_level = np.array([2**i for i in range(len(self.tax_levels) - 1)])
            # Distribute (1 - label_smoothing) according to these weights
            prob_per_tax_level = label_smoothing * prob_per_tax_level / np.sum(prob_per_tax_level)
            # Prob mass for unrelated classes as all probabilities have to be non-zero
            eps = prob_per_tax_level[0] * 0.1
            prob_per_tax_level[0] -= eps
            # Add probability mass for the same class predicition and unrelated class prediciton
            prob_per_tax_level = [eps] + prob_per_tax_level.tolist() + [1 - label_smoothing] 

            # Now convert the numbers in the matrix to probabilities
            self.targets = np.zeros_like(self.relationship, dtype=np.float64)
            # We will distribute prob_per_tax_level[LEVEL] across all entries in a row with entry LEVEL
            # Accumulate left over prob mass in case a class does not have any other classes with same 
            # family across the next level 
            # We will start from to most specific tax level and go more and more generic
            leftover_prob_mass = np.zeros((len(self.targets),))
            for tax_level in range(len(prob_per_tax_level))[::-1]:
                per_row_count = np.sum(self.relationship==tax_level, axis=1)
                prob_mass = prob_per_tax_level[tax_level] + leftover_prob_mass
                self.targets[self.relationship==tax_level] = np.repeat(prob_mass / per_row_count, per_row_count)
                leftover_prob_mass = prob_per_tax_level[tax_level] * (per_row_count==0)
            # Create a memory efficient target representation for each sample
            assert not np.any(np.isclose(0, self.targets))
            self.targets = self.targets.tolist()
            self.targets = [np.array(aa) for aa in self.targets]
            self.targets = [self.targets[cc].astype(np.float32) for cc in self.classes]
            print("The division-by-zero-error is handled properly, so don't worry.")

            self.bg_classes = bg_classes
            if isinstance(bg_classes, list):
                for idx in range(len(self.classes)):
                    if np.any(np.isclose(self.classes[idx], self.bg_classes)):
                        self.targets[idx][:] = 0
        else:
            self.targets = self.classes


        # print out some stats
        print ('\t' + str(len(self.imgs)) + ' images')
        print ('\t' + str(len(set(self.classes))) + ' classes')

        self.root = root
        self.is_train = is_train
        self.loader = ImageLoader(image_sizes)
        self.multi_crop = multi_crop

        self.imagesInZip = (".zip" in self.root)
        if (self.imagesInZip):
            self.archive = zipfile.ZipFile(self.root, 'r')

        numToUse = int((len(self.imgs)*percentUse)/100)
        self.imgs = self.imgs[:numToUse]
        self.ids = self.ids[:numToUse]
        self.classes = self.classes[:numToUse]

        if bbox_predictions:
            img_id_to_idx = {image_id:idx for idx,image_id in enumerate(self.ids)}
            self.bboxes = [None for _ in range(len(self.ids))]
            self.bbox_labels = [None for _ in range(len(self.ids))]
            self.bbox_scores = [None for _ in range(len(self.ids))]
            loaded_dict = np.load(bbox_predictions)
            image_ids = loaded_dict['image_ids']
            for image_id, bbox, bbox_labels, bbox_scores in zip(image_ids,
                                                   loaded_dict['pred_bboxes'],
                                                   loaded_dict['pred_labels'],
                                                   loaded_dict['pred_scores']):
                if len(bbox) > 0:
                    assert image_id[0].tolist() in img_id_to_idx, 'Didn\'t find image for bounding box, ' + \
                                                                  'maybe it\'s the wrong json file?'
                    idx = img_id_to_idx[image_id[0].tolist()]
                    self.bboxes[idx] = bbox
                    self.bbox_labels[idx] = bbox_labels
                    self.bbox_scores[idx] = bbox_scores

        else:
            self.bboxes = None
            self.bbox_labels = None
            self.bbox_scores = None
        self.label_smoothing = label_smoothing