danieldux commited on
Commit
5966251
·
1 Parent(s): 5264d3a
Files changed (4) hide show
  1. README.md +1 -1
  2. hierarchical_softmax_loss.py +100 -10
  3. level_dict.py +25 -0
  4. requirements.txt +2 -1
README.md CHANGED
@@ -1,7 +1,7 @@
1
  ---
2
  title: Hierarchical Softmax Loss
3
  datasets:
4
- -
5
  tags:
6
  - evaluate
7
  - metric
 
1
  ---
2
  title: Hierarchical Softmax Loss
3
  datasets:
4
+ - danieldux/ISCO-08
5
  tags:
6
  - evaluate
7
  - metric
hierarchical_softmax_loss.py CHANGED
@@ -13,16 +13,19 @@
13
  # limitations under the License.
14
  """TODO: Add a description here."""
15
 
 
16
  import evaluate
17
  import datasets
18
-
 
 
19
 
20
  # TODO: Add BibTeX citation
21
  _CITATION = """\
22
  @InProceedings{huggingface:module,
23
- title = {A great new module},
24
- authors={huggingface, Inc.},
25
- year={2020}
26
  }
27
  """
28
 
@@ -58,7 +61,7 @@ BAD_WORDS_URL = "http://url/to/external/resource/bad_words.txt"
58
 
59
 
60
  @evaluate.utils.file_utils.add_start_docstrings(_DESCRIPTION, _KWARGS_DESCRIPTION)
61
- class HierarchicalSoftmaxLoss(evaluate.Metric):
62
  """TODO: Short description of my evaluation module."""
63
 
64
  def _info(self):
@@ -83,13 +86,100 @@ class HierarchicalSoftmaxLoss(evaluate.Metric):
83
 
84
  def _download_and_prepare(self, dl_manager):
85
  """Optional: download external resources useful to compute the scores"""
86
- # TODO: Download external resources if needed
87
  pass
88
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
89
  def _compute(self, predictions, references):
90
- """Returns the scores"""
91
- # TODO: Compute the different scores of the module
92
- accuracy = sum(i == j for i, j in zip(predictions, references)) / len(predictions)
 
 
 
 
 
 
93
  return {
94
- "accuracy": accuracy,
95
  }
 
13
  # limitations under the License.
14
  """TODO: Add a description here."""
15
 
16
+ from hierarchicalsoftmax import HierarchicalSoftmaxLoss
17
  import evaluate
18
  import datasets
19
+ import pickle
20
+ import torch
21
+ import torch.nn as nn
22
 
23
  # TODO: Add BibTeX citation
24
  _CITATION = """\
25
  @InProceedings{huggingface:module,
26
+ title = {Hierarchical Softmax Loss},
27
+ authors={Danieldux},
28
+ year={2023}
29
  }
30
  """
31
 
 
61
 
62
 
63
  @evaluate.utils.file_utils.add_start_docstrings(_DESCRIPTION, _KWARGS_DESCRIPTION)
64
+ class HierarchicalISCOSoftmaxLoss(evaluate.Metric):
65
  """TODO: Short description of my evaluation module."""
66
 
67
  def _info(self):
 
86
 
87
  def _download_and_prepare(self, dl_manager):
88
  """Optional: download external resources useful to compute the scores"""
89
+ # TODO: Download ISCO hierachical metadata
90
  pass
91
 
92
+
93
+
94
+ class HierarchicalLossNetwork:
95
+ """Logics to calculate the loss of the model.
96
+ """
97
+
98
+ def __init__(self, metafile_path, hierarchical_labels, device='cpu', total_level=2, alpha=1, beta=0.8, p_loss=3):
99
+ """Param init.
100
+ """
101
+ self.total_level = total_level
102
+ self.alpha = alpha
103
+ self.beta = beta
104
+ self.p_loss = p_loss
105
+ self.device = device
106
+ self.level_one_labels, self.level_two_labels, self.level_three_labels, self.level_four_labels = read_meta(metafile=metafile_path)
107
+ self.hierarchical_labels = hierarchical_labels
108
+ self.numeric_hierarchy = self.words_to_indices()
109
+
110
+ def read_meta(metafile):
111
+ """Read the meta file and return the coarse and fine labels.
112
+ """
113
+ # TODO: Replace with metadata from the dataset
114
+ meta_data = unpickle(metafile)
115
+ fine_label_names = [t.decode('utf8') for t in meta_data[b'fine_label_names']]
116
+ coarse_label_names = [t.decode('utf8') for t in meta_data[b'coarse_label_names']]
117
+ return coarse_label_names, fine_label_names
118
+
119
+ def hierarchical_softmax_loss_fn(logits: torch.Tensor, labels: torch.Tensor, root) -> torch.Tensor:
120
+ loss = HierarchicalSoftmaxLoss(root=root)
121
+ return loss(logits, labels)
122
+
123
+ def words_to_indices(self):
124
+ """Convert the classes from words to indices."""
125
+ numeric_hierarchy = {}
126
+ for k, v in self.hierarchical_labels.items():
127
+ numeric_hierarchy[self.level_one_labels.index(k)] = [self.level_two_labels.index(i) for i in v]
128
+
129
+ return numeric_hierarchy
130
+
131
+
132
+ def check_hierarchy(self, current_level, previous_level):
133
+ """
134
+ Check if the predicted class at level l is a child of the class predicted at level l-1 for the entire batch.
135
+ """
136
+
137
+ #check using the dictionary whether the current level's prediction belongs to the superclass (prediction from the prev layer)
138
+ bool_tensor = [not current_level[i] in self.numeric_hierarchy[previous_level[i].item()] for i in range(previous_level.size()[0])]
139
+
140
+ return torch.FloatTensor(bool_tensor).to(self.device)
141
+
142
+
143
+ def calculate_lloss(self, predictions, true_labels):
144
+ """Calculates the layer loss."""
145
+
146
+ lloss = 0
147
+ for l in range(self.total_level):
148
+
149
+ lloss += nn.CrossEntropyLoss()(predictions[l], true_labels[l])
150
+
151
+ return self.alpha * lloss
152
+
153
+
154
+ def calculate_dloss(self, predictions, true_labels):
155
+ """Calculate the dependence loss."""
156
+
157
+ dloss = 0
158
+ for l in range(1, self.total_level):
159
+
160
+ current_lvl_pred = torch.argmax(nn.Softmax(dim=1)(predictions[l]), dim=1)
161
+ prev_lvl_pred = torch.argmax(nn.Softmax(dim=1)(predictions[l-1]), dim=1)
162
+
163
+ D_l = self.check_hierarchy(current_lvl_pred, prev_lvl_pred)
164
+
165
+ l_prev = torch.where(prev_lvl_pred == true_labels[l-1], torch.FloatTensor([0]).to(self.device), torch.FloatTensor([1]).to(self.device))
166
+ l_curr = torch.where(current_lvl_pred == true_labels[l], torch.FloatTensor([0]).to(self.device), torch.FloatTensor([1]).to(self.device))
167
+
168
+ dloss += torch.sum(torch.pow(self.p_loss, D_l*l_prev)*torch.pow(self.p_loss, D_l*l_curr) - 1)
169
+
170
+ return self.beta * dloss
171
+
172
+
173
  def _compute(self, predictions, references):
174
+ """Returns the accuracy score of the prediction"""
175
+
176
+ num_data = references.size()[0]
177
+ predicted = torch.argmax(predictions, dim=1)
178
+
179
+ correct_pred = torch.sum(predicted == references)
180
+
181
+ accuracy = correct_pred*(100/num_data)
182
+
183
  return {
184
+ "accuracy": accuracy.item(),
185
  }
level_dict.py ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ '''Dictionary for CIFAR-100 hierarchy.
2
+ '''
3
+
4
+ hierarchy = {
5
+ 'aquatic_mammals':['beaver', 'dolphin', 'otter', 'seal', 'whale'],
6
+ 'fish': ['aquarium_fish', 'flatfish', 'ray', 'shark', 'trout'],
7
+ 'flowers':['orchid', 'poppy', 'rose', 'sunflower', 'tulip'],
8
+ 'food_containers' : ['bottle', 'bowl', 'can', 'cup', 'plate'],
9
+ 'fruit_and_vegetables':['apple', 'mushroom', 'orange', 'pear', 'sweet_pepper'],
10
+ 'household_electrical_devices' :['clock', 'keyboard', 'lamp', 'telephone', 'television'],
11
+ 'household_furniture': ['bed', 'chair', 'couch', 'table', 'wardrobe'],
12
+ 'insects': ['bee', 'beetle', 'butterfly', 'caterpillar', 'cockroach'],
13
+ 'large_carnivores':['bear', 'leopard', 'lion', 'tiger', 'wolf'],
14
+ 'large_man-made_outdoor_things':['bridge', 'castle', 'house', 'road', 'skyscraper'],
15
+ 'large_natural_outdoor_scenes':['cloud', 'forest', 'mountain', 'plain', 'sea'],
16
+ 'large_omnivores_and_herbivores' : ['camel', 'cattle', 'chimpanzee', 'elephant', 'kangaroo'],
17
+ 'medium_mammals': ['fox', 'porcupine', 'possum', 'raccoon', 'skunk'],
18
+ 'non-insect_invertebrates': ['crab', 'lobster', 'snail', 'spider', 'worm'],
19
+ 'people': ['baby', 'boy', 'girl', 'man', 'woman'],
20
+ 'reptiles': ['crocodile', 'dinosaur', 'lizard', 'snake', 'turtle'],
21
+ 'small_mammals': ['hamster', 'mouse', 'rabbit', 'shrew', 'squirrel'],
22
+ 'trees' : ['maple_tree', 'oak_tree', 'palm_tree', 'pine_tree', 'willow_tree'],
23
+ 'vehicles_1':['bicycle', 'bus', 'motorcycle', 'pickup_truck', 'train'],
24
+ 'vehicles_2': ['lawn_mower', 'rocket', 'streetcar', 'tank', 'tractor']
25
+ }
requirements.txt CHANGED
@@ -1 +1,2 @@
1
- git+https://github.com/huggingface/evaluate@main
 
 
1
+ git+https://github.com/huggingface/evaluate@main
2
+ hierarchicalsoftmax