in PyTorchClassification/data_loader_cv.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):
# load annotations
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():
self.classes = [aa['category_id'] for aa in ann_data['annotations']]
else:
self.classes = [0]*len(self.imgs)
# load taxonomy
if (dataFormat2017):
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
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])
# 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] for cc in self.classes]
print("The division-by-zero-error is handled properly, so don't worry.")
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