├── .gitignore ├── CUB-Hierarchy ├── README.md ├── classes_balanced.txt ├── classes_flat.txt ├── classes_wikispecies-hierarchy.txt ├── classes_wikispecies.txt ├── cub_balanced.parent-child.txt ├── cub_flat.parent-child.txt ├── cub_wikispecies.parent-child.txt ├── encode_hierarchy.py ├── hierarchy_balanced.svg ├── hierarchy_balanced.txt ├── hierarchy_flat.svg ├── hierarchy_flat.txt ├── hierarchy_wikispecies.svg └── hierarchy_wikispecies.txt ├── Cifar-Hierarchy ├── cifar.parent-child.txt ├── class_names.txt ├── encode_hierarchy.py ├── graph_wordnet.pdf ├── hierarchy.svg └── hierarchy.txt ├── CosineLoss.md ├── ILSVRC ├── imagenet_class_index.json ├── imagenet_class_index.unitsphere.json ├── wordnet.parent-child.mintree.txt ├── wordnet.parent-child.pruned.txt └── wordnet.parent-child.txt ├── LICENSE ├── NAB-Hierarchy ├── classes.txt ├── hierarchy.svg ├── hierarchy.txt └── nab_class_index.unitsphere.json ├── README.md ├── class_hierarchy.py ├── clr_callback.py ├── compute_class_embedding.py ├── datasets ├── __init__.py ├── cars.py ├── cifar.py ├── common.py ├── flowers.py ├── ilsvrc.py ├── inat.py ├── nab.py └── subdirectory.py ├── embeddings ├── cifar100.glove.pickle ├── cifar100.unitsphere.pickle ├── cub_balanced.unitsphere.pickle ├── cub_flat.unitsphere.pickle ├── cub_wikispecies.unitsphere.pickle ├── imagenet_mintree.unitsphere.pickle ├── inat.sim1024.pickle ├── inat2019.pickle ├── nab.sim.pickle ├── nab.sim128.pickle ├── nab.sim128_unnormed.pickle ├── nab.sim16.pickle ├── nab.sim16_unnormed.pickle ├── nab.sim256.pickle ├── nab.sim256_unnormed.pickle ├── nab.sim32.pickle ├── nab.sim32_unnormed.pickle ├── nab.sim64.pickle ├── nab.sim64_unnormed.pickle ├── nab.sim8.pickle ├── nab.sim8_unnormed.pickle └── nab.unitsphere.pickle ├── evaluate_classification_accuracy.py ├── evaluate_retrieval.py ├── iNaturalist-Hierarchy ├── hierarchy_inat.txt ├── hierarchy_inat2019.txt ├── hierarchy_inat_insecta.txt ├── iNaturalist_hierarchies.py ├── inat_class_index.json └── inat_class_index.unitsphere.json ├── learn_center_loss.py ├── learn_classifier.py ├── learn_devise.py ├── learn_image_embeddings.py ├── learn_labelembedding.py ├── models ├── DenseNet │ ├── LICENSE │ ├── README.md │ ├── cifar10.py │ ├── cifar100.py │ ├── densenet.py │ ├── densenet_fast.py │ ├── imagenet_inference.py │ ├── subpixel.py │ ├── tensorflow_backend.py │ └── theano_backend.py ├── cifar_pyramidnet.py ├── cifar_resnet.py ├── plainnet.py └── wide_residual_network.py ├── plot_hierarchy.py ├── plot_recall_precision.py ├── sgdr_callback.py └── utils.py /.gitignore: -------------------------------------------------------------------------------- 1 | # ---> Python 2 | # Byte-compiled / optimized / DLL files 3 | __pycache__/ 4 | *.py[cod] 5 | *$py.class 6 | 7 | # C extensions 8 | *.so 9 | 10 | # Distribution / packaging 11 | .Python 12 | env/ 13 | build/ 14 | develop-eggs/ 15 | dist/ 16 | downloads/ 17 | eggs/ 18 | .eggs/ 19 | lib/ 20 | lib64/ 21 | parts/ 22 | sdist/ 23 | var/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *,cover 47 | 48 | # Translations 49 | *.mo 50 | *.pot 51 | 52 | # Django stuff: 53 | *.log 54 | 55 | # Sphinx documentation 56 | docs/_build/ 57 | 58 | # PyBuilder 59 | target/ 60 | 61 | -------------------------------------------------------------------------------- /CUB-Hierarchy/README.md: -------------------------------------------------------------------------------- 1 | Class Hierarchy for CUB-200-2011 2 | ================================ 3 | 4 | This directory contains hierarchical information about the 200 bird classes in the [Caltech-UCSD Birds-200-2011][1] dataset. 5 | 6 | [**classes_wikispecies.txt**](classes_wikispecies.txt) maps the numerical class labels (ranging from 1 to 200) to the scientific names of the birds. 7 | For determining these, we searched [Wikispecies][2] for the respective English name of the bird and used [Wikidata][3] as a fall-back if the bird could not be found in Wikispecies. 8 | 9 | [**hierarchy_wikispecies.txt**](hierarchy_wikispecies.txt) defines the class taxonomy in a human-readable tree format. 10 | This taxonomy corresponds to the one provided by [Wikispecies][2], where we used the following taxonomy levels: 11 | 12 | - ***ordo*** (ending on *-formes*) 13 | - ***subordo*** 14 | - ***superfamilia*** (ending on *-oidea*) 15 | - ***familia*** (ending on *-idae*) 16 | - ***subfamilia*** (ending on *-inae*) 17 | - ***genus*** 18 | - ***species*** (consisting of two words, the first one being the *genus*) 19 | 20 | Note that *subordo*, *superfamilia*, and *subfamilia* only exist in some branches of the hierarchy and are denoted by comments in parentheses. 21 | The root node of the hierarchy is the class *Aves* (birds). 22 | 23 | [**hierarchy_balanced.txt**](hierarchy_balanced.txt) is a derivation of the Wikispecies-based taxonomy, where we added some *subordines*, *superfimiliae*, *subfamiliae*, and *tribes*, so that all species have the same depth in the resulting hierarchy. 24 | We grounded this extension on systematic information found in the English [Wikipedia][4] or, as a fall-back, the [Open Tree of Life][5]. 25 | In some cases, where we could not find sufficient information, we had to make up some intermediate levels. These are indicated by question marks following their names. 26 | 27 | Moreover, we have introduced an additional first level dividing the *ordines* into 5 groups of *superordines* and *clades* based on information from [Wikipedia][4]: 28 | 29 | - *Aequorlitornithes* (water birds) 30 | - *Telluraves* (land birds) 31 | - *Cypselomorphae* (nightjars, nighthawks, swifts, hummingbirds etc.) 32 | - *Columbaves* (cuckoos, turacos, bustards, pigeons, mesites, sandgrouses) 33 | - *Galloanserae* (fowl) 34 | 35 | [**hierarchy_flat.txt**](hierarchy_flat.txt), on the other hand, is derived from the Wikispecies-based taxonomy by removing all *subordo*, *superfamilia*, and *subfamilia* levels, hence resulting in a very flat but balanced hierarchy comprising only the levels *ordo*, *familia*, *genus*, and *species*. 36 | 37 | The script [**encode_hierarchy.py**](encode_hierarchy.py) can be used to translate these human-readable taxonomies into machine-readable pairs of parent-child tuples, where each node is encoded with a numeric class label. 38 | The remaining files in this directory are the results of this process for each of the three hierarchies. 39 | 40 | 41 | Known Issues 42 | ------------ 43 | 44 | - Class 130 (**Tree Sparrow**) mixed images of two classes from different *familiae*: 45 | There are 34 images of *Spizelloides arborea* (American Tree Sparrow) and 26 images of *Passer montanus* (Tree Sparrow). 46 | Though the ratio is quite balanced, we mapped this class to the species with slightly more images, i.e., *Spizelloides arborea*. 47 | Ideally, one should split this class into two separate ones, but we wanted to maintain the original class structure of CUB-200-2011 for comparability. 48 | 49 | - Class 91 (**Mockingbird**) is actually an informal group of species from 3 *genera* of the *familia* *mimidae*, but the images seem to mainly show instances of the *species* *Mimus polyglottos*, which is the only mockingbird commonly found North America. Thus, we map that class to this *species*. 50 | 51 | - While most classes have a species-level resolution, a handful of them are coarser: 52 | - Class 44 (**Frigatebird**) resolves to *Fregata* (*genus* level), which encompasses 5 bird species of quite different appearance. 53 | - Class 92 (**Nighthawk**) resolves to *Chordeiles* (*genus* level), which comprises 6 species. 54 | - Class 103 (***Sayornis***) is at the *genus* level, comprising 3 species. 55 | - Class 110 (***Geococcyx***) is at the *genus* level, but there are only 2 possible species with minor visual differences. 56 | 57 | 58 | Citation 59 | -------- 60 | 61 | If you use this hierarchy for the CUB dataset in your work, please cite the following paper: 62 | 63 | > [**Deep Learning on Small Datasets without Pre-Training usine Cosine Loss.**][6] 64 | > Björn Barz and Joachim Denzler. 65 | > IEEE Winter Conference on Applications of Computer Vision (WACV), 2020. 66 | 67 | 68 | [1]: http://www.vision.caltech.edu/visipedia/CUB-200-2011.html 69 | [2]: https://species.wikimedia.org/ 70 | [3]: https://www.wikidata.org/ 71 | [4]: https://en.wikipedia.org/ 72 | [5]: https://tree.opentreeoflife.org/ 73 | [6]: https://arxiv.org/pdf/1901.09054 -------------------------------------------------------------------------------- /CUB-Hierarchy/classes_balanced.txt: -------------------------------------------------------------------------------- 1 | 1 Phoebastria nigripes 2 | 2 Phoebastria immutabilis 3 | 3 Phoebetria fusca 4 | 4 Crotophaga sulcirostris 5 | 5 Aethia cristatella 6 | 6 Aethia pusilla 7 | 7 Aethia psittacula 8 | 8 Cerorhinca monocerata 9 | 9 Euphagus cyanocephalus 10 | 10 Agelaius phoeniceus 11 | 11 Euphagus carolinus 12 | 12 Xanthocephalus xanthocephalus 13 | 13 Dolichonyx oryzivorus 14 | 14 Passerina cyanea 15 | 15 Passerina amoena 16 | 16 Passerina ciris 17 | 17 Cardinalis cardinalis 18 | 18 Ailuroedus melanotis 19 | 19 Dumetella carolinensis 20 | 20 Icteria virens 21 | 21 Pipilo erythrophthalmus 22 | 22 Caprimulgus carolinensis 23 | 23 Phalacrocorax penicillatus 24 | 24 Phalacrocorax urile 25 | 25 Phalacrocorax pelagicus 26 | 26 Molothrus aeneus 27 | 27 Molothrus bonariensis 28 | 28 Certhia americana 29 | 29 Corvus brachyrhynchos 30 | 30 Corvus ossifragus 31 | 31 Coccyzus erythropthalmus 32 | 32 Coccyzus minor 33 | 33 Coccyzus americanus 34 | 34 Leucosticte tephrocotis 35 | 35 Haemorhous purpureus 36 | 36 Colaptes auratus 37 | 37 Empidonax virescens 38 | 38 Myiarchus crinitus 39 | 39 Empidonax minimus 40 | 40 Contopus cooperi 41 | 41 Tyrannus forficatus 42 | 42 Pyrocephalus obscurus 43 | 43 Empidonax flaviventris 44 | 44 Fregata 45 | 45 Fulmarus glacialis 46 | 46 Anas strepera 47 | 47 Spinus tristis 48 | 48 Carduelis carduelis 49 | 49 Quiscalus major 50 | 50 Podiceps nigricollis 51 | 51 Podiceps auritus 52 | 52 Podilymbus podiceps 53 | 53 Aechmophorus occidentalis 54 | 54 Passerina caerulea 55 | 55 Hesperiphona vespertina 56 | 56 Pinicola enucleator 57 | 57 Pheucticus ludovicianus 58 | 58 Cepphus columba 59 | 59 Larus californicus 60 | 60 Larus glaucescens 61 | 61 Larus heermanni 62 | 62 Larus argentatus 63 | 63 Pagophila eburnea 64 | 64 Larus delawarensis 65 | 65 Larus schistisagus 66 | 66 Larus occidentalis 67 | 67 Calypte anna 68 | 68 Archilochus colubris 69 | 69 Selasphorus rufus 70 | 70 Colibri thalassinus 71 | 71 Stercorarius longicaudus 72 | 72 Stercorarius pomarinus 73 | 73 Cyanocitta cristata 74 | 74 Aphelocoma coerulescens 75 | 75 Cyanocorax luxuosus 76 | 76 Junco hyemalis 77 | 77 Tyrannus melancholicus 78 | 78 Tyrannus dominicensis 79 | 79 Megaceryle alcyon 80 | 80 Chloroceryle americana 81 | 81 Ceryle rudis 82 | 82 Megaceryle torquata 83 | 83 Halcyon smyrnensis 84 | 84 Rissa brevirostris 85 | 85 Eremophila alpestris 86 | 86 Gavia pacifica 87 | 87 Anas platyrhynchos 88 | 88 Sturnella neglecta 89 | 89 Lophodytes cucullatus 90 | 90 Mergus serrator 91 | 91 Mimus polyglottos 92 | 92 Chordeiles 93 | 93 Nucifraga columbiana 94 | 94 Sitta carolinensis 95 | 95 Icterus galbula 96 | 96 Icterus cucullatus 97 | 97 Icterus spurius 98 | 98 Icterus parisorum 99 | 99 Seiurus aurocapilla 100 | 100 Pelecanus occidentalis 101 | 101 Pelecanus onocrotalus 102 | 102 Contopus sordidulus 103 | 103 Sayornis 104 | 104 Anthus rubescens 105 | 105 Caprimulgus vociferus 106 | 106 Fratercula corniculata 107 | 107 Corvus corax 108 | 108 Corvus albicollis 109 | 109 Setophaga ruticilla 110 | 110 Geococcyx 111 | 111 Lanius ludovicianus 112 | 112 Lanius excubitor 113 | 113 Ammodramus bairdii 114 | 114 Amphispiza bilineata 115 | 115 Spizella breweri 116 | 116 Spizella passerina 117 | 117 Spizella pallida 118 | 118 Passer domesticus 119 | 119 Spizella pusilla 120 | 120 Passerella iliaca 121 | 121 Ammodramus savannarum 122 | 122 Zonotrichia querula 123 | 123 Ammodramus henslowii 124 | 124 Ammodramus leconteii 125 | 125 Melospiza lincolnii 126 | 126 Ammodramus nelsoni 127 | 127 Passerculus sandwichensis 128 | 128 Ammodramus maritimus 129 | 129 Melospiza melodia 130 | 130 Spizelloides arborea 131 | 131 Pooecetes gramineus 132 | 132 Zonotrichia leucophrys 133 | 133 Zonotrichia albicollis 134 | 134 Lamprotornis nitens 135 | 135 Riparia riparia 136 | 136 Hirundo rustica 137 | 137 Petrochelidon pyrrhonota 138 | 138 Tachycineta bicolor 139 | 139 Piranga olivacea 140 | 140 Piranga rubra 141 | 141 Sterna paradisaea 142 | 142 Chlidonias niger 143 | 143 Hydroprogne caspia 144 | 144 Sterna hirundo 145 | 145 Thalasseus elegans 146 | 146 Sterna forsteri 147 | 147 Sternula antillarum 148 | 148 Pipilo chlorurus 149 | 149 Toxostoma rufum 150 | 150 Oreoscoptes montanus 151 | 151 Vireo atricapilla 152 | 152 Vireo solitarius 153 | 153 Vireo philadelphicus 154 | 154 Vireo olivaceus 155 | 155 Vireo gilvus 156 | 156 Vireo griseus 157 | 157 Vireo flavifrons 158 | 158 Setophaga castanea 159 | 159 Mniotilta varia 160 | 160 Setophaga caerulescens 161 | 161 Vermivora cyanoptera 162 | 162 Cardellina canadensis 163 | 163 Setophaga tigrina 164 | 164 Setophaga cerulea 165 | 165 Setophaga pensylvanica 166 | 166 Vermivora chrysoptera 167 | 167 Setophaga citrina 168 | 168 Geothlypis formosa 169 | 169 Setophaga magnolia 170 | 170 Geothlypis philadelphia 171 | 171 Setophaga coronata 172 | 172 Leiothlypis ruficapilla 173 | 173 Leiothlypis celata 174 | 174 Setophaga palmarum 175 | 175 Setophaga pinus 176 | 176 Setophaga discolor 177 | 177 Protonotaria citrea 178 | 178 Limnothlypis swainsonii 179 | 179 Leiothlypis peregrina 180 | 180 Cardellina pusilla 181 | 181 Helmitheros vermivorum 182 | 182 Setophaga aestiva 183 | 183 Parkesia noveboracensis 184 | 184 Parkesia motacilla 185 | 185 Bombycilla garrulus 186 | 186 Bombycilla cedrorum 187 | 187 Picoides dorsalis 188 | 188 Dryocopus pileatus 189 | 189 Melanerpes carolinus 190 | 190 Leuconotopicus borealis 191 | 191 Melanerpes erythrocephalus 192 | 192 Dryobates pubescens 193 | 193 Thryomanes bewickii 194 | 194 Campylorhynchus brunneicapillus 195 | 195 Thryothorus ludovicianus 196 | 196 Troglodytes aedon 197 | 197 Cistothorus palustris 198 | 198 Salpinctes obsoletus 199 | 199 Troglodytes hiemalis 200 | 200 Geothlypis trichas 201 | 201 Vermivora 202 | 202 Oceanites + Diomedeidae 203 | 203 Diomedeidae 204 | 204 Procellariidae 205 | 205 Laniidae 206 | 206 Lanius 207 | 207 Spizella 208 | 208 Podicipedoidea 209 | 209 Podicipedidae 210 | 210 Dendropicini 211 | 211 Melanerpes 212 | 212 Leuconotopicus 213 | 213 Picoides 214 | 214 Dryobates 215 | 215 Phalacrocoracinae 216 | 216 Phalacrocorax 217 | 217 Ceryle 218 | 218 Helmitheros 219 | 219 Gaviinae 220 | 220 Gavia 221 | 221 Salpinctes 222 | 222 Vireo 223 | 223 Stercorariidae 224 | 224 Stercorariinae 225 | 225 Aethia 226 | 226 Pelecaninae 227 | 227 Pelecanus 228 | 228 Myiarchus 229 | 229 Colibri 230 | 230 Passeriformes 231 | 231 Tyranni 232 | 232 Passeri 233 | 233 Coccyzinae 234 | 234 Coccyzus 235 | 235 Alcedinidae 236 | 236 Halcyoninae 237 | 237 Cerylinae 238 | 238 Tyrannoidea 239 | 239 Merginus 240 | 240 Alcidae 241 | 241 Alcinae 242 | 242 Fraterculinae 243 | 243 Procellariinae 244 | 244 Cardinalidae 245 | 245 Passerina 246 | 246 Cardinalis 247 | 247 Pheucticus 248 | 248 Piranga 249 | 249 Pipilo 250 | 250 Corvidae 251 | 251 Corvus 252 | 252 Aphelocoma 253 | 253 Cyanocorax 254 | 254 Cyanocitta 255 | 255 Nucifraga 256 | 256 Pici 257 | 257 Picidae 258 | 258 Suliformes 259 | 259 Fregatoidea 260 | 260 Suloidea 261 | 261 Thalassarche eremita + Phoebetria 262 | 262 Phoebetria 263 | 263 Sternula 264 | 264 Amphispiza 265 | 265 Tyrannus 266 | 266 Galloanserae 267 | 267 Anseriformes 268 | 268 Fulmarus 269 | 269 Archilochus 270 | 270 Carduelis 271 | 271 Alaudidae 272 | 272 Eremophila 273 | 273 Haemorhous 274 | 274 Laridae 275 | 275 Sterninae 276 | 276 Larinae 277 | 277 Fregatidae 278 | 278 Sturnella 279 | 279 Lari 280 | 280 Diomedea exulans + Phoebastria 281 | 281 Pelecaniformes 282 | 282 Pelecanidae + Balaenicipitidae 283 | 283 Hirundinidae 284 | 284 Riparia 285 | 285 Petrochelidon 286 | 286 Hirundo 287 | 287 Tachycineta 288 | 288 Megaceryle 289 | 289 Sterna 290 | 290 Trochiliformes 291 | 291 Trochili 292 | 292 Anas 293 | 293 Lophodytes 294 | 294 Phoebastria 295 | 295 Muscicapoidea 296 | 296 Bombycillidae 297 | 297 Sturnidae 298 | 298 Mimidae 299 | 299 Icteria 300 | 300 Limnothlypis 301 | 301 Campylorhynchus 302 | 302 Caprimulgiformes 303 | 303 Caprimulgi 304 | 304 Fratercula 305 | 305 Cuculi 306 | 306 Cuculidae 307 | 307 Anthus 308 | 308 Bombycilla 309 | 309 Caprimulgidae 310 | 310 Xanthocephalus 311 | 311 Cerorhinca 312 | 312 Neomorphinae 313 | 313 Troglodytidae 314 | 314 Cistothorus 315 | 315 Troglodytes 316 | 316 Thryomanes 317 | 317 Thryothorus 318 | 318 Fregatinae 319 | 319 Cepphus 320 | 320 Ailuroedus 321 | 321 Picini 322 | 322 Colaptes 323 | 323 Dryocopus 324 | 324 Passeroidea 325 | 325 Icteridae 326 | 326 Fringillidae 327 | 327 Sittidae 328 | 328 Passeridae 329 | 329 Motacillidae 330 | 330 Icteriidae 331 | 331 Passerellidae 332 | 332 Parulidae 333 | 333 Menuroidea 334 | 334 Ptilonorhynchidae 335 | 335 Lamprotornis 336 | 336 Dumetella 337 | 337 Sitta 338 | 338 Crotophaga 339 | 339 Zonotrichia 340 | 340 Quiscalus 341 | 341 Cardellina 342 | 342 Oreoscoptes 343 | 343 Mimus 344 | 344 Toxostoma 345 | 345 Halcyon 346 | 346 Trochilidae 347 | 347 Trochilinae 348 | 348 Telluraves 349 | 349 Coraciiformes 350 | 350 Piciformes 351 | 351 Icterus 352 | 352 Hydroprogne 353 | 353 Cuculiformes 354 | 354 Pyrocephalus 355 | 355 Leucosticte 356 | 356 Euphagus 357 | 357 Seiurus 358 | 358 Certhiidae 359 | 359 Certhia 360 | 360 Corvoidea 361 | 361 Certhioidea 362 | 362 Sylvioidea 363 | 363 Podicipediformes 364 | 364 Gaviidae 365 | 365 Mniotilta 366 | 366 Charadriiformes 367 | 367 Alcae 368 | 368 Molothrus 369 | 369 Junco 370 | 370 Chlidonias 371 | 371 Anatoidea 372 | 372 Crotophaginae 373 | 373 Hesperiphona 374 | 374 Alcedines 375 | 375 Podilymbinae 376 | 376 Podiceps cristatus + Aechmophorus 377 | 377 Anatinae 378 | 378 Pinicola 379 | 379 Gavii 380 | 380 Procellariiformes 381 | 381 Empidonax 382 | 382 Pooecetes 383 | 383 Passerculus 384 | 384 Ammodramus 385 | 385 Melospiza 386 | 386 Spizelloides 387 | 387 Passerella 388 | 388 Larus 389 | 389 Pagophila 390 | 390 Rissa 391 | 391 Protonotaria 392 | 392 Stercorarius 393 | 393 Pelecanidae 394 | 394 Selasphorus 395 | 395 Calypte 396 | 396 Phalacrocoracidae 397 | 397 Leiothlypis 398 | 398 Tyrannidae 399 | 399 Caprimulgus 400 | 400 Anatidae 401 | 401 Merginae 402 | 402 Aechmophorus 403 | 403 Podiceps 404 | 404 Cypselomorphae 405 | 405 Setophaga 406 | 406 Agelaius 407 | 407 Contopus 408 | 408 Geothlypis 409 | 409 Thalasseus 410 | 410 Passer 411 | 411 Chloroceryle 412 | 412 Caprimulginae 413 | 413 Vireonidae 414 | 414 Spinus 415 | 415 Aequorlitornithes 416 | 416 Gaviiformes 417 | 417 Podilymbus 418 | 418 Parkesia 419 | 419 Dolichonyx 420 | 420 Aves 421 | 421 Columbaves 422 | -------------------------------------------------------------------------------- /CUB-Hierarchy/classes_flat.txt: -------------------------------------------------------------------------------- 1 | 1 Phoebastria nigripes 2 | 2 Phoebastria immutabilis 3 | 3 Phoebetria fusca 4 | 4 Crotophaga sulcirostris 5 | 5 Aethia cristatella 6 | 6 Aethia pusilla 7 | 7 Aethia psittacula 8 | 8 Cerorhinca monocerata 9 | 9 Euphagus cyanocephalus 10 | 10 Agelaius phoeniceus 11 | 11 Euphagus carolinus 12 | 12 Xanthocephalus xanthocephalus 13 | 13 Dolichonyx oryzivorus 14 | 14 Passerina cyanea 15 | 15 Passerina amoena 16 | 16 Passerina ciris 17 | 17 Cardinalis cardinalis 18 | 18 Ailuroedus melanotis 19 | 19 Dumetella carolinensis 20 | 20 Icteria virens 21 | 21 Pipilo erythrophthalmus 22 | 22 Caprimulgus carolinensis 23 | 23 Phalacrocorax penicillatus 24 | 24 Phalacrocorax urile 25 | 25 Phalacrocorax pelagicus 26 | 26 Molothrus aeneus 27 | 27 Molothrus bonariensis 28 | 28 Certhia americana 29 | 29 Corvus brachyrhynchos 30 | 30 Corvus ossifragus 31 | 31 Coccyzus erythropthalmus 32 | 32 Coccyzus minor 33 | 33 Coccyzus americanus 34 | 34 Leucosticte tephrocotis 35 | 35 Haemorhous purpureus 36 | 36 Colaptes auratus 37 | 37 Empidonax virescens 38 | 38 Myiarchus crinitus 39 | 39 Empidonax minimus 40 | 40 Contopus cooperi 41 | 41 Tyrannus forficatus 42 | 42 Pyrocephalus obscurus 43 | 43 Empidonax flaviventris 44 | 44 Fregata 45 | 45 Fulmarus glacialis 46 | 46 Anas strepera 47 | 47 Spinus tristis 48 | 48 Carduelis carduelis 49 | 49 Quiscalus major 50 | 50 Podiceps nigricollis 51 | 51 Podiceps auritus 52 | 52 Podilymbus podiceps 53 | 53 Aechmophorus occidentalis 54 | 54 Passerina caerulea 55 | 55 Hesperiphona vespertina 56 | 56 Pinicola enucleator 57 | 57 Pheucticus ludovicianus 58 | 58 Cepphus columba 59 | 59 Larus californicus 60 | 60 Larus glaucescens 61 | 61 Larus heermanni 62 | 62 Larus argentatus 63 | 63 Pagophila eburnea 64 | 64 Larus delawarensis 65 | 65 Larus schistisagus 66 | 66 Larus occidentalis 67 | 67 Calypte anna 68 | 68 Archilochus colubris 69 | 69 Selasphorus rufus 70 | 70 Colibri thalassinus 71 | 71 Stercorarius longicaudus 72 | 72 Stercorarius pomarinus 73 | 73 Cyanocitta cristata 74 | 74 Aphelocoma coerulescens 75 | 75 Cyanocorax luxuosus 76 | 76 Junco hyemalis 77 | 77 Tyrannus melancholicus 78 | 78 Tyrannus dominicensis 79 | 79 Megaceryle alcyon 80 | 80 Chloroceryle americana 81 | 81 Ceryle rudis 82 | 82 Megaceryle torquata 83 | 83 Halcyon smyrnensis 84 | 84 Rissa brevirostris 85 | 85 Eremophila alpestris 86 | 86 Gavia pacifica 87 | 87 Anas platyrhynchos 88 | 88 Sturnella neglecta 89 | 89 Lophodytes cucullatus 90 | 90 Mergus serrator 91 | 91 Mimus polyglottos 92 | 92 Chordeiles 93 | 93 Nucifraga columbiana 94 | 94 Sitta carolinensis 95 | 95 Icterus galbula 96 | 96 Icterus cucullatus 97 | 97 Icterus spurius 98 | 98 Icterus parisorum 99 | 99 Seiurus aurocapilla 100 | 100 Pelecanus occidentalis 101 | 101 Pelecanus onocrotalus 102 | 102 Contopus sordidulus 103 | 103 Sayornis 104 | 104 Anthus rubescens 105 | 105 Caprimulgus vociferus 106 | 106 Fratercula corniculata 107 | 107 Corvus corax 108 | 108 Corvus albicollis 109 | 109 Setophaga ruticilla 110 | 110 Geococcyx 111 | 111 Lanius ludovicianus 112 | 112 Lanius excubitor 113 | 113 Ammodramus bairdii 114 | 114 Amphispiza bilineata 115 | 115 Spizella breweri 116 | 116 Spizella passerina 117 | 117 Spizella pallida 118 | 118 Passer domesticus 119 | 119 Spizella pusilla 120 | 120 Passerella iliaca 121 | 121 Ammodramus savannarum 122 | 122 Zonotrichia querula 123 | 123 Ammodramus henslowii 124 | 124 Ammodramus leconteii 125 | 125 Melospiza lincolnii 126 | 126 Ammodramus nelsoni 127 | 127 Passerculus sandwichensis 128 | 128 Ammodramus maritimus 129 | 129 Melospiza melodia 130 | 130 Spizelloides arborea 131 | 131 Pooecetes gramineus 132 | 132 Zonotrichia leucophrys 133 | 133 Zonotrichia albicollis 134 | 134 Lamprotornis nitens 135 | 135 Riparia riparia 136 | 136 Hirundo rustica 137 | 137 Petrochelidon pyrrhonota 138 | 138 Tachycineta bicolor 139 | 139 Piranga olivacea 140 | 140 Piranga rubra 141 | 141 Sterna paradisaea 142 | 142 Chlidonias niger 143 | 143 Hydroprogne caspia 144 | 144 Sterna hirundo 145 | 145 Thalasseus elegans 146 | 146 Sterna forsteri 147 | 147 Sternula antillarum 148 | 148 Pipilo chlorurus 149 | 149 Toxostoma rufum 150 | 150 Oreoscoptes montanus 151 | 151 Vireo atricapilla 152 | 152 Vireo solitarius 153 | 153 Vireo philadelphicus 154 | 154 Vireo olivaceus 155 | 155 Vireo gilvus 156 | 156 Vireo griseus 157 | 157 Vireo flavifrons 158 | 158 Setophaga castanea 159 | 159 Mniotilta varia 160 | 160 Setophaga caerulescens 161 | 161 Vermivora cyanoptera 162 | 162 Cardellina canadensis 163 | 163 Setophaga tigrina 164 | 164 Setophaga cerulea 165 | 165 Setophaga pensylvanica 166 | 166 Vermivora chrysoptera 167 | 167 Setophaga citrina 168 | 168 Geothlypis formosa 169 | 169 Setophaga magnolia 170 | 170 Geothlypis philadelphia 171 | 171 Setophaga coronata 172 | 172 Leiothlypis ruficapilla 173 | 173 Leiothlypis celata 174 | 174 Setophaga palmarum 175 | 175 Setophaga pinus 176 | 176 Setophaga discolor 177 | 177 Protonotaria citrea 178 | 178 Limnothlypis swainsonii 179 | 179 Leiothlypis peregrina 180 | 180 Cardellina pusilla 181 | 181 Helmitheros vermivorum 182 | 182 Setophaga aestiva 183 | 183 Parkesia noveboracensis 184 | 184 Parkesia motacilla 185 | 185 Bombycilla garrulus 186 | 186 Bombycilla cedrorum 187 | 187 Picoides dorsalis 188 | 188 Dryocopus pileatus 189 | 189 Melanerpes carolinus 190 | 190 Leuconotopicus borealis 191 | 191 Melanerpes erythrocephalus 192 | 192 Dryobates pubescens 193 | 193 Thryomanes bewickii 194 | 194 Campylorhynchus brunneicapillus 195 | 195 Thryothorus ludovicianus 196 | 196 Troglodytes aedon 197 | 197 Cistothorus palustris 198 | 198 Salpinctes obsoletus 199 | 199 Troglodytes hiemalis 200 | 200 Geothlypis trichas 201 | 201 Amphispiza 202 | 202 Cyanocorax 203 | 203 Mimus 204 | 204 Selasphorus 205 | 205 Caprimulgus 206 | 206 Laridae 207 | 207 Pagophila 208 | 208 Thalasseus 209 | 209 Chlidonias 210 | 210 Rissa 211 | 211 Sternula 212 | 212 Hydroprogne 213 | 213 Larus 214 | 214 Sterna 215 | 215 Podicipedidae 216 | 216 Aechmophorus 217 | 217 Podilymbus 218 | 218 Podiceps 219 | 219 Picoides 220 | 220 Mniotilta 221 | 221 Cerorhinca 222 | 222 Oreoscoptes 223 | 223 Phoebastria 224 | 224 Anseriformes 225 | 225 Anatidae 226 | 226 Caprimulgiformes 227 | 227 Caprimulgidae 228 | 228 Archilochus 229 | 229 Phoebetria 230 | 230 Molothrus 231 | 231 Passer 232 | 232 Piranga 233 | 233 Passerculus 234 | 234 Riparia 235 | 235 Melospiza 236 | 236 Tyrannus 237 | 237 Parulidae 238 | 238 Helmitheros 239 | 239 Leiothlypis 240 | 240 Geothlypis 241 | 241 Seiurus 242 | 242 Setophaga 243 | 243 Vermivora 244 | 244 Protonotaria 245 | 245 Cardellina 246 | 246 Limnothlypis 247 | 247 Parkesia 248 | 248 Lanius 249 | 249 Calypte 250 | 250 Phalacrocorax 251 | 251 Megaceryle 252 | 252 Ailuroedus 253 | 253 Trochilidae 254 | 254 Colibri 255 | 255 Certhiidae 256 | 256 Certhia 257 | 257 Icteridae 258 | 258 Sturnella 259 | 259 Dolichonyx 260 | 260 Xanthocephalus 261 | 261 Icterus 262 | 262 Agelaius 263 | 263 Quiscalus 264 | 264 Euphagus 265 | 265 Trochiliformes 266 | 266 Cardinalidae 267 | 267 Pheucticus 268 | 268 Passerina 269 | 269 Cardinalis 270 | 270 Sittidae 271 | 271 Sitta 272 | 272 Coraciiformes 273 | 273 Alcedinidae 274 | 274 Hirundinidae 275 | 275 Tachycineta 276 | 276 Hirundo 277 | 277 Petrochelidon 278 | 278 Hesperiphona 279 | 279 Carduelis 280 | 280 Passerellidae 281 | 281 Spizelloides 282 | 282 Spizella 283 | 283 Junco 284 | 284 Pipilo 285 | 285 Ammodramus 286 | 286 Pooecetes 287 | 287 Passerella 288 | 288 Zonotrichia 289 | 289 Gaviiformes 290 | 290 Gaviidae 291 | 291 Aphelocoma 292 | 292 Empidonax 293 | 293 Merginae 294 | 294 Fulmarus 295 | 295 Vireo 296 | 296 Passeriformes 297 | 297 Motacillidae 298 | 298 Corvidae 299 | 299 Alaudidae 300 | 300 Tyrannidae 301 | 301 Fringillidae 302 | 302 Ptilonorhynchidae 303 | 303 Bombycillidae 304 | 304 Icteriidae 305 | 305 Troglodytidae 306 | 306 Laniidae 307 | 307 Vireonidae 308 | 308 Passeridae 309 | 309 Mimidae 310 | 310 Sturnidae 311 | 311 Salpinctes 312 | 312 Pyrocephalus 313 | 313 Suliformes 314 | 314 Fregatidae 315 | 315 Phalacrocoracidae 316 | 316 Dryocopus 317 | 317 Fratercula 318 | 318 Dryobates 319 | 319 Eremophila 320 | 320 Toxostoma 321 | 321 Dumetella 322 | 322 Procellariiformes 323 | 323 Procellariidae 324 | 324 Diomedeidae 325 | 325 Icteria 326 | 326 Troglodytes 327 | 327 Thryomanes 328 | 328 Anthus 329 | 329 Crotophaga 330 | 330 Haemorhous 331 | 331 Bombycilla 332 | 332 Pinicola 333 | 333 Corvus 334 | 334 Lophodytes 335 | 335 Halcyon 336 | 336 Spinus 337 | 337 Leucosticte 338 | 338 Pelecanus 339 | 339 Anas 340 | 340 Lamprotornis 341 | 341 Cistothorus 342 | 342 Alcidae 343 | 343 Cepphus 344 | 344 Aethia 345 | 345 Pelecanidae 346 | 346 Podicipediformes 347 | 347 Picidae 348 | 348 Colaptes 349 | 349 Melanerpes 350 | 350 Leuconotopicus 351 | 351 Chloroceryle 352 | 352 Ceryle 353 | 353 Piciformes 354 | 354 Contopus 355 | 355 Myiarchus 356 | 356 Pelecaniformes 357 | 357 Campylorhynchus 358 | 358 Stercorariidae 359 | 359 Stercorarius 360 | 360 Thryothorus 361 | 361 Coccyzus 362 | 362 Cyanocitta 363 | 363 Nucifraga 364 | 364 Gavia 365 | 365 Cuculidae 366 | 366 Charadriiformes 367 | 367 Aves 368 | 368 Cuculiformes 369 | -------------------------------------------------------------------------------- /CUB-Hierarchy/classes_wikispecies-hierarchy.txt: -------------------------------------------------------------------------------- 1 | 1 Phoebastria nigripes 2 | 2 Phoebastria immutabilis 3 | 3 Phoebetria fusca 4 | 4 Crotophaga sulcirostris 5 | 5 Aethia cristatella 6 | 6 Aethia pusilla 7 | 7 Aethia psittacula 8 | 8 Cerorhinca monocerata 9 | 9 Euphagus cyanocephalus 10 | 10 Agelaius phoeniceus 11 | 11 Euphagus carolinus 12 | 12 Xanthocephalus xanthocephalus 13 | 13 Dolichonyx oryzivorus 14 | 14 Passerina cyanea 15 | 15 Passerina amoena 16 | 16 Passerina ciris 17 | 17 Cardinalis cardinalis 18 | 18 Ailuroedus melanotis 19 | 19 Dumetella carolinensis 20 | 20 Icteria virens 21 | 21 Pipilo erythrophthalmus 22 | 22 Caprimulgus carolinensis 23 | 23 Phalacrocorax penicillatus 24 | 24 Phalacrocorax urile 25 | 25 Phalacrocorax pelagicus 26 | 26 Molothrus aeneus 27 | 27 Molothrus bonariensis 28 | 28 Certhia americana 29 | 29 Corvus brachyrhynchos 30 | 30 Corvus ossifragus 31 | 31 Coccyzus erythropthalmus 32 | 32 Coccyzus minor 33 | 33 Coccyzus americanus 34 | 34 Leucosticte tephrocotis 35 | 35 Haemorhous purpureus 36 | 36 Colaptes auratus 37 | 37 Empidonax virescens 38 | 38 Myiarchus crinitus 39 | 39 Empidonax minimus 40 | 40 Contopus cooperi 41 | 41 Tyrannus forficatus 42 | 42 Pyrocephalus obscurus 43 | 43 Empidonax flaviventris 44 | 44 Fregata 45 | 45 Fulmarus glacialis 46 | 46 Anas strepera 47 | 47 Spinus tristis 48 | 48 Carduelis carduelis 49 | 49 Quiscalus major 50 | 50 Podiceps nigricollis 51 | 51 Podiceps auritus 52 | 52 Podilymbus podiceps 53 | 53 Aechmophorus occidentalis 54 | 54 Passerina caerulea 55 | 55 Hesperiphona vespertina 56 | 56 Pinicola enucleator 57 | 57 Pheucticus ludovicianus 58 | 58 Cepphus columba 59 | 59 Larus californicus 60 | 60 Larus glaucescens 61 | 61 Larus heermanni 62 | 62 Larus argentatus 63 | 63 Pagophila eburnea 64 | 64 Larus delawarensis 65 | 65 Larus schistisagus 66 | 66 Larus occidentalis 67 | 67 Calypte anna 68 | 68 Archilochus colubris 69 | 69 Selasphorus rufus 70 | 70 Colibri thalassinus 71 | 71 Stercorarius longicaudus 72 | 72 Stercorarius pomarinus 73 | 73 Cyanocitta cristata 74 | 74 Aphelocoma coerulescens 75 | 75 Cyanocorax luxuosus 76 | 76 Junco hyemalis 77 | 77 Tyrannus melancholicus 78 | 78 Tyrannus dominicensis 79 | 79 Megaceryle alcyon 80 | 80 Chloroceryle americana 81 | 81 Ceryle rudis 82 | 82 Megaceryle torquata 83 | 83 Halcyon smyrnensis 84 | 84 Rissa brevirostris 85 | 85 Eremophila alpestris 86 | 86 Gavia pacifica 87 | 87 Anas platyrhynchos 88 | 88 Sturnella neglecta 89 | 89 Lophodytes cucullatus 90 | 90 Mergus serrator 91 | 91 Mimus polyglottos 92 | 92 Chordeiles 93 | 93 Nucifraga columbiana 94 | 94 Sitta carolinensis 95 | 95 Icterus galbula 96 | 96 Icterus cucullatus 97 | 97 Icterus spurius 98 | 98 Icterus parisorum 99 | 99 Seiurus aurocapilla 100 | 100 Pelecanus occidentalis 101 | 101 Pelecanus onocrotalus 102 | 102 Contopus sordidulus 103 | 103 Sayornis 104 | 104 Anthus rubescens 105 | 105 Caprimulgus vociferus 106 | 106 Fratercula corniculata 107 | 107 Corvus corax 108 | 108 Corvus albicollis 109 | 109 Setophaga ruticilla 110 | 110 Geococcyx 111 | 111 Lanius ludovicianus 112 | 112 Lanius excubitor 113 | 113 Ammodramus bairdii 114 | 114 Amphispiza bilineata 115 | 115 Spizella breweri 116 | 116 Spizella passerina 117 | 117 Spizella pallida 118 | 118 Passer domesticus 119 | 119 Spizella pusilla 120 | 120 Passerella iliaca 121 | 121 Ammodramus savannarum 122 | 122 Zonotrichia querula 123 | 123 Ammodramus henslowii 124 | 124 Ammodramus leconteii 125 | 125 Melospiza lincolnii 126 | 126 Ammodramus nelsoni 127 | 127 Passerculus sandwichensis 128 | 128 Ammodramus maritimus 129 | 129 Melospiza melodia 130 | 130 Spizelloides arborea 131 | 131 Pooecetes gramineus 132 | 132 Zonotrichia leucophrys 133 | 133 Zonotrichia albicollis 134 | 134 Lamprotornis nitens 135 | 135 Riparia riparia 136 | 136 Hirundo rustica 137 | 137 Petrochelidon pyrrhonota 138 | 138 Tachycineta bicolor 139 | 139 Piranga olivacea 140 | 140 Piranga rubra 141 | 141 Sterna paradisaea 142 | 142 Chlidonias niger 143 | 143 Hydroprogne caspia 144 | 144 Sterna hirundo 145 | 145 Thalasseus elegans 146 | 146 Sterna forsteri 147 | 147 Sternula antillarum 148 | 148 Pipilo chlorurus 149 | 149 Toxostoma rufum 150 | 150 Oreoscoptes montanus 151 | 151 Vireo atricapilla 152 | 152 Vireo solitarius 153 | 153 Vireo philadelphicus 154 | 154 Vireo olivaceus 155 | 155 Vireo gilvus 156 | 156 Vireo griseus 157 | 157 Vireo flavifrons 158 | 158 Setophaga castanea 159 | 159 Mniotilta varia 160 | 160 Setophaga caerulescens 161 | 161 Vermivora cyanoptera 162 | 162 Cardellina canadensis 163 | 163 Setophaga tigrina 164 | 164 Setophaga cerulea 165 | 165 Setophaga pensylvanica 166 | 166 Vermivora chrysoptera 167 | 167 Setophaga citrina 168 | 168 Geothlypis formosa 169 | 169 Setophaga magnolia 170 | 170 Geothlypis philadelphia 171 | 171 Setophaga coronata 172 | 172 Leiothlypis ruficapilla 173 | 173 Leiothlypis celata 174 | 174 Setophaga palmarum 175 | 175 Setophaga pinus 176 | 176 Setophaga discolor 177 | 177 Protonotaria citrea 178 | 178 Limnothlypis swainsonii 179 | 179 Leiothlypis peregrina 180 | 180 Cardellina pusilla 181 | 181 Helmitheros vermivorum 182 | 182 Setophaga aestiva 183 | 183 Parkesia noveboracensis 184 | 184 Parkesia motacilla 185 | 185 Bombycilla garrulus 186 | 186 Bombycilla cedrorum 187 | 187 Picoides dorsalis 188 | 188 Dryocopus pileatus 189 | 189 Melanerpes carolinus 190 | 190 Leuconotopicus borealis 191 | 191 Melanerpes erythrocephalus 192 | 192 Dryobates pubescens 193 | 193 Thryomanes bewickii 194 | 194 Campylorhynchus brunneicapillus 195 | 195 Thryothorus ludovicianus 196 | 196 Troglodytes aedon 197 | 197 Cistothorus palustris 198 | 198 Salpinctes obsoletus 199 | 199 Troglodytes hiemalis 200 | 200 Geothlypis trichas 201 | 201 Cuculiformes 202 | 202 Cuculidae 203 | 203 Tyrannidae 204 | 204 Pyrocephalus 205 | 205 Tyrannus 206 | 206 Empidonax 207 | 207 Contopus 208 | 208 Myiarchus 209 | 209 Campylorhynchus 210 | 210 Gaviidae 211 | 211 Gavia 212 | 212 Colibri 213 | 213 Dolichonyx 214 | 214 Cardellina 215 | 215 Sturnella 216 | 216 Picoides 217 | 217 Certhia 218 | 218 Vermivora 219 | 219 Diomedeidae 220 | 220 Phoebastria 221 | 221 Phoebetria 222 | 222 Ptilonorhynchidae 223 | 223 Ailuroedus 224 | 224 Podicipediformes 225 | 225 Podicipedidae 226 | 226 Vireonidae 227 | 227 Vireo 228 | 228 Coraciiformes 229 | 229 Alcedinidae 230 | 230 Halcyon 231 | 231 Pelecanidae 232 | 232 Pelecanus 233 | 233 Motacillidae 234 | 234 Anthus 235 | 235 Sittidae 236 | 236 Sitta 237 | 237 Corvoidea 238 | 238 Laniidae 239 | 239 Corvidae 240 | 240 Molothrus 241 | 241 Passerina 242 | 242 Fratercula 243 | 243 Aves 244 | 244 Procellariiformes 245 | 245 Passeriformes 246 | 246 Anseriformes 247 | 247 Caprimulgiformes 248 | 248 Charadriiformes 249 | 249 Trochiliformes 250 | 250 Piciformes 251 | 251 Gaviiformes 252 | 252 Suliformes 253 | 253 Pelecaniformes 254 | 254 Passeroidea 255 | 255 Cardinalidae 256 | 256 Alaudidae 257 | 257 Parulidae 258 | 258 Passeridae 259 | 259 Icteridae 260 | 260 Fringillidae 261 | 261 Icteriidae 262 | 262 Passerellidae 263 | 263 Carduelis 264 | 264 Rissa 265 | 265 Riparia 266 | 266 Coccyzus 267 | 267 Calypte 268 | 268 Trochilidae 269 | 269 Fregatidae 270 | 270 Phalacrocoracidae 271 | 271 Thalasseus 272 | 272 Cepphus 273 | 273 Picidae 274 | 274 Euphagus 275 | 275 Troglodytes 276 | 276 Salpinctes 277 | 277 Corvus 278 | 278 Nucifraga 279 | 279 Cyanocorax 280 | 280 Cyanocitta 281 | 281 Aphelocoma 282 | 282 Podiceps 283 | 283 Pagophila 284 | 284 Amphispiza 285 | 285 Ceryle 286 | 286 Hesperiphona 287 | 287 Chloroceryle 288 | 288 Cistothorus 289 | 289 Caprimulginae 290 | 290 Caprimulgus 291 | 291 Crotophaga 292 | 292 Passer 293 | 293 Icteria 294 | 294 Hydroprogne 295 | 295 Pinicola 296 | 296 Megaceryle 297 | 297 Spizelloides 298 | 298 Melospiza 299 | 299 Passerella 300 | 300 Ammodramus 301 | 301 Junco 302 | 302 Passerculus 303 | 303 Spizella 304 | 304 Pooecetes 305 | 305 Pipilo 306 | 306 Zonotrichia 307 | 307 Setophaga 308 | 308 Menuroidea 309 | 309 Passeri 310 | 310 Sylvioidea 311 | 311 Certhioidea 312 | 312 Muscicapoidea 313 | 313 Laridae 314 | 314 Larinae 315 | 315 Sterninae 316 | 316 Helmitheros 317 | 317 Seiurus 318 | 318 Aethia 319 | 319 Hirundinidae 320 | 320 Alcae 321 | 321 Alcidae 322 | 322 Troglodytidae 323 | 323 Thryothorus 324 | 324 Thryomanes 325 | 325 Petrochelidon 326 | 326 Podilymbus 327 | 327 Dryocopus 328 | 328 Sterna 329 | 329 Anatidae 330 | 330 Protonotaria 331 | 331 Xanthocephalus 332 | 332 Certhiidae 333 | 333 Colaptes 334 | 334 Tyranni 335 | 335 Halcyoninae 336 | 336 Eremophila 337 | 337 Piranga 338 | 338 Cardinalis 339 | 339 Pheucticus 340 | 340 Mniotilta 341 | 341 Bombycillidae 342 | 342 Bombycilla 343 | 343 Larus 344 | 344 Toxostoma 345 | 345 Procellariidae 346 | 346 Fulmarus 347 | 347 Lamprotornis 348 | 348 Stercorariidae 349 | 349 Stercorarius 350 | 350 Tachycineta 351 | 351 Chlidonias 352 | 352 Sternula 353 | 353 Cerylinae 354 | 354 Sturnidae 355 | 355 Limnothlypis 356 | 356 Geothlypis 357 | 357 Parkesia 358 | 358 Leiothlypis 359 | 359 Agelaius 360 | 360 Icterus 361 | 361 Quiscalus 362 | 362 Leucosticte 363 | 363 Lanius 364 | 364 Spinus 365 | 365 Caprimulgidae 366 | 366 Phalacrocorax 367 | 367 Anas 368 | 368 Dumetella 369 | 369 Oreoscoptes 370 | 370 Cerorhinca 371 | 371 Lari 372 | 372 Melanerpes 373 | 373 Dryobates 374 | 374 Leuconotopicus 375 | 375 Archilochus 376 | 376 Selasphorus 377 | 377 Hirundo 378 | 378 Merginae 379 | 379 Lophodytes 380 | 380 Aechmophorus 381 | 381 Mimus 382 | 382 Haemorhous 383 | 383 Mimidae 384 | -------------------------------------------------------------------------------- /CUB-Hierarchy/classes_wikispecies.txt: -------------------------------------------------------------------------------- 1 | 1 Phoebastria nigripes 2 | 2 Phoebastria immutabilis 3 | 3 Phoebetria fusca 4 | 4 Crotophaga sulcirostris 5 | 5 Aethia cristatella 6 | 6 Aethia pusilla 7 | 7 Aethia psittacula 8 | 8 Cerorhinca monocerata 9 | 9 Euphagus cyanocephalus 10 | 10 Agelaius phoeniceus 11 | 11 Euphagus carolinus 12 | 12 Xanthocephalus xanthocephalus 13 | 13 Dolichonyx oryzivorus 14 | 14 Passerina cyanea 15 | 15 Passerina amoena 16 | 16 Passerina ciris 17 | 17 Cardinalis cardinalis 18 | 18 Ailuroedus melanotis 19 | 19 Dumetella carolinensis 20 | 20 Icteria virens 21 | 21 Pipilo erythrophthalmus 22 | 22 Caprimulgus carolinensis 23 | 23 Phalacrocorax penicillatus 24 | 24 Phalacrocorax urile 25 | 25 Phalacrocorax pelagicus 26 | 26 Molothrus aeneus 27 | 27 Molothrus bonariensis 28 | 28 Certhia americana 29 | 29 Corvus brachyrhynchos 30 | 30 Corvus ossifragus 31 | 31 Coccyzus erythropthalmus 32 | 32 Coccyzus minor 33 | 33 Coccyzus americanus 34 | 34 Leucosticte tephrocotis 35 | 35 Haemorhous purpureus 36 | 36 Colaptes auratus 37 | 37 Empidonax virescens 38 | 38 Myiarchus crinitus 39 | 39 Empidonax minimus 40 | 40 Contopus cooperi 41 | 41 Tyrannus forficatus 42 | 42 Pyrocephalus obscurus 43 | 43 Empidonax flaviventris 44 | 44 Fregata 45 | 45 Fulmarus glacialis 46 | 46 Anas strepera 47 | 47 Spinus tristis 48 | 48 Carduelis carduelis 49 | 49 Quiscalus major 50 | 50 Podiceps nigricollis 51 | 51 Podiceps auritus 52 | 52 Podilymbus podiceps 53 | 53 Aechmophorus occidentalis 54 | 54 Passerina caerulea 55 | 55 Hesperiphona vespertina 56 | 56 Pinicola enucleator 57 | 57 Pheucticus ludovicianus 58 | 58 Cepphus columba 59 | 59 Larus californicus 60 | 60 Larus glaucescens 61 | 61 Larus heermanni 62 | 62 Larus argentatus 63 | 63 Pagophila eburnea 64 | 64 Larus delawarensis 65 | 65 Larus schistisagus 66 | 66 Larus occidentalis 67 | 67 Calypte anna 68 | 68 Archilochus colubris 69 | 69 Selasphorus rufus 70 | 70 Colibri thalassinus 71 | 71 Stercorarius longicaudus 72 | 72 Stercorarius pomarinus 73 | 73 Cyanocitta cristata 74 | 74 Aphelocoma coerulescens 75 | 75 Cyanocorax luxuosus 76 | 76 Junco hyemalis 77 | 77 Tyrannus melancholicus 78 | 78 Tyrannus dominicensis 79 | 79 Megaceryle alcyon 80 | 80 Chloroceryle americana 81 | 81 Ceryle rudis 82 | 82 Megaceryle torquata 83 | 83 Halcyon smyrnensis 84 | 84 Rissa brevirostris 85 | 85 Eremophila alpestris 86 | 86 Gavia pacifica 87 | 87 Anas platyrhynchos 88 | 88 Sturnella neglecta 89 | 89 Lophodytes cucullatus 90 | 90 Mergus serrator 91 | 91 Mimus polyglottos 92 | 92 Chordeiles 93 | 93 Nucifraga columbiana 94 | 94 Sitta carolinensis 95 | 95 Icterus galbula 96 | 96 Icterus cucullatus 97 | 97 Icterus spurius 98 | 98 Icterus parisorum 99 | 99 Seiurus aurocapilla 100 | 100 Pelecanus occidentalis 101 | 101 Pelecanus onocrotalus 102 | 102 Contopus sordidulus 103 | 103 Sayornis 104 | 104 Anthus rubescens 105 | 105 Caprimulgus vociferus 106 | 106 Fratercula corniculata 107 | 107 Corvus corax 108 | 108 Corvus albicollis 109 | 109 Setophaga ruticilla 110 | 110 Geococcyx 111 | 111 Lanius ludovicianus 112 | 112 Lanius excubitor 113 | 113 Ammodramus bairdii 114 | 114 Amphispiza bilineata 115 | 115 Spizella breweri 116 | 116 Spizella passerina 117 | 117 Spizella pallida 118 | 118 Passer domesticus 119 | 119 Spizella pusilla 120 | 120 Passerella iliaca 121 | 121 Ammodramus savannarum 122 | 122 Zonotrichia querula 123 | 123 Ammodramus henslowii 124 | 124 Ammodramus leconteii 125 | 125 Melospiza lincolnii 126 | 126 Ammodramus nelsoni 127 | 127 Passerculus sandwichensis 128 | 128 Ammodramus maritimus 129 | 129 Melospiza melodia 130 | 130 Spizelloides arborea 131 | 131 Pooecetes gramineus 132 | 132 Zonotrichia leucophrys 133 | 133 Zonotrichia albicollis 134 | 134 Lamprotornis nitens 135 | 135 Riparia riparia 136 | 136 Hirundo rustica 137 | 137 Petrochelidon pyrrhonota 138 | 138 Tachycineta bicolor 139 | 139 Piranga olivacea 140 | 140 Piranga rubra 141 | 141 Sterna paradisaea 142 | 142 Chlidonias niger 143 | 143 Hydroprogne caspia 144 | 144 Sterna hirundo 145 | 145 Thalasseus elegans 146 | 146 Sterna forsteri 147 | 147 Sternula antillarum 148 | 148 Pipilo chlorurus 149 | 149 Toxostoma rufum 150 | 150 Oreoscoptes montanus 151 | 151 Vireo atricapilla 152 | 152 Vireo solitarius 153 | 153 Vireo philadelphicus 154 | 154 Vireo olivaceus 155 | 155 Vireo gilvus 156 | 156 Vireo griseus 157 | 157 Vireo flavifrons 158 | 158 Setophaga castanea 159 | 159 Mniotilta varia 160 | 160 Setophaga caerulescens 161 | 161 Vermivora cyanoptera 162 | 162 Cardellina canadensis 163 | 163 Setophaga tigrina 164 | 164 Setophaga cerulea 165 | 165 Setophaga pensylvanica 166 | 166 Vermivora chrysoptera 167 | 167 Setophaga citrina 168 | 168 Geothlypis formosa 169 | 169 Setophaga magnolia 170 | 170 Geothlypis philadelphia 171 | 171 Setophaga coronata 172 | 172 Leiothlypis ruficapilla 173 | 173 Leiothlypis celata 174 | 174 Setophaga palmarum 175 | 175 Setophaga pinus 176 | 176 Setophaga discolor 177 | 177 Protonotaria citrea 178 | 178 Limnothlypis swainsonii 179 | 179 Leiothlypis peregrina 180 | 180 Cardellina pusilla 181 | 181 Helmitheros vermivorum 182 | 182 Setophaga aestiva 183 | 183 Parkesia noveboracensis 184 | 184 Parkesia motacilla 185 | 185 Bombycilla garrulus 186 | 186 Bombycilla cedrorum 187 | 187 Picoides dorsalis 188 | 188 Dryocopus pileatus 189 | 189 Melanerpes carolinus 190 | 190 Leuconotopicus borealis 191 | 191 Melanerpes erythrocephalus 192 | 192 Dryobates pubescens 193 | 193 Thryomanes bewickii 194 | 194 Campylorhynchus brunneicapillus 195 | 195 Thryothorus ludovicianus 196 | 196 Troglodytes aedon 197 | 197 Cistothorus palustris 198 | 198 Salpinctes obsoletus 199 | 199 Troglodytes hiemalis 200 | 200 Geothlypis trichas 201 | -------------------------------------------------------------------------------- /CUB-Hierarchy/cub_balanced.parent-child.txt: -------------------------------------------------------------------------------- 1 | 201 161 2 | 201 166 3 | 202 203 4 | 202 204 5 | 203 261 6 | 203 280 7 | 204 243 8 | 205 206 9 | 206 111 10 | 206 112 11 | 207 115 12 | 207 116 13 | 207 117 14 | 207 119 15 | 208 209 16 | 209 375 17 | 209 376 18 | 210 211 19 | 210 212 20 | 210 213 21 | 210 214 22 | 211 189 23 | 211 191 24 | 212 190 25 | 213 187 26 | 214 192 27 | 215 216 28 | 216 25 29 | 216 23 30 | 216 24 31 | 217 81 32 | 218 181 33 | 219 220 34 | 220 86 35 | 221 198 36 | 222 151 37 | 222 152 38 | 222 153 39 | 222 154 40 | 222 155 41 | 222 156 42 | 222 157 43 | 223 224 44 | 224 392 45 | 225 5 46 | 225 6 47 | 225 7 48 | 226 227 49 | 227 100 50 | 227 101 51 | 228 38 52 | 229 70 53 | 230 231 54 | 230 232 55 | 231 238 56 | 232 324 57 | 232 295 58 | 232 360 59 | 232 361 60 | 232 362 61 | 232 333 62 | 233 234 63 | 234 33 64 | 234 31 65 | 234 32 66 | 235 236 67 | 235 237 68 | 236 345 69 | 237 217 70 | 237 411 71 | 237 288 72 | 238 398 73 | 239 90 74 | 240 241 75 | 240 242 76 | 241 319 77 | 242 225 78 | 242 311 79 | 242 304 80 | 243 268 81 | 244 245 82 | 244 246 83 | 244 247 84 | 244 248 85 | 245 54 86 | 245 14 87 | 245 15 88 | 245 16 89 | 246 17 90 | 247 57 91 | 248 139 92 | 248 140 93 | 249 148 94 | 249 21 95 | 250 251 96 | 250 252 97 | 250 253 98 | 250 254 99 | 250 255 100 | 251 107 101 | 251 108 102 | 251 29 103 | 251 30 104 | 252 74 105 | 253 75 106 | 254 73 107 | 255 93 108 | 256 257 109 | 257 321 110 | 257 210 111 | 258 259 112 | 258 260 113 | 259 277 114 | 260 396 115 | 261 262 116 | 262 3 117 | 263 147 118 | 264 114 119 | 265 41 120 | 265 77 121 | 265 78 122 | 266 267 123 | 267 371 124 | 268 45 125 | 269 68 126 | 270 48 127 | 271 272 128 | 272 85 129 | 273 35 130 | 274 275 131 | 274 276 132 | 275 289 133 | 275 370 134 | 275 409 135 | 275 263 136 | 275 352 137 | 276 388 138 | 276 389 139 | 276 390 140 | 277 318 141 | 278 88 142 | 279 274 143 | 279 223 144 | 280 294 145 | 281 282 146 | 282 393 147 | 283 284 148 | 283 285 149 | 283 286 150 | 283 287 151 | 284 135 152 | 285 137 153 | 286 136 154 | 287 138 155 | 288 82 156 | 288 79 157 | 289 146 158 | 289 141 159 | 289 144 160 | 290 291 161 | 291 346 162 | 292 46 163 | 292 87 164 | 293 89 165 | 294 1 166 | 294 2 167 | 295 297 168 | 295 298 169 | 295 296 170 | 296 308 171 | 297 335 172 | 298 344 173 | 298 342 174 | 298 343 175 | 298 336 176 | 299 20 177 | 300 178 178 | 301 194 179 | 302 303 180 | 303 309 181 | 304 106 182 | 305 306 183 | 306 233 184 | 306 372 185 | 306 312 186 | 307 104 187 | 308 185 188 | 308 186 189 | 309 412 190 | 310 12 191 | 311 8 192 | 312 110 193 | 313 301 194 | 313 317 195 | 313 314 196 | 313 315 197 | 313 316 198 | 313 221 199 | 314 197 200 | 315 196 201 | 315 199 202 | 316 193 203 | 317 195 204 | 318 44 205 | 319 58 206 | 320 18 207 | 321 322 208 | 321 323 209 | 322 36 210 | 323 188 211 | 324 325 212 | 324 326 213 | 324 327 214 | 324 328 215 | 324 329 216 | 324 330 217 | 324 331 218 | 324 332 219 | 324 271 220 | 324 244 221 | 325 419 222 | 325 356 223 | 325 368 224 | 325 340 225 | 325 278 226 | 325 406 227 | 325 310 228 | 325 351 229 | 326 355 230 | 326 270 231 | 326 273 232 | 326 373 233 | 326 378 234 | 326 414 235 | 327 337 236 | 328 410 237 | 329 307 238 | 330 299 239 | 331 385 240 | 331 386 241 | 331 387 242 | 331 264 243 | 331 207 244 | 331 369 245 | 331 339 246 | 331 249 247 | 331 382 248 | 331 383 249 | 331 384 250 | 332 418 251 | 332 357 252 | 332 391 253 | 332 201 254 | 332 300 255 | 332 397 256 | 332 365 257 | 332 405 258 | 332 341 259 | 332 408 260 | 332 218 261 | 333 334 262 | 334 320 263 | 335 134 264 | 336 19 265 | 337 94 266 | 338 4 267 | 339 122 268 | 339 132 269 | 339 133 270 | 340 49 271 | 341 162 272 | 341 180 273 | 342 150 274 | 343 91 275 | 344 149 276 | 345 83 277 | 346 347 278 | 347 394 279 | 347 395 280 | 347 269 281 | 347 229 282 | 348 350 283 | 348 349 284 | 348 230 285 | 349 374 286 | 350 256 287 | 351 97 288 | 351 98 289 | 351 95 290 | 351 96 291 | 352 143 292 | 353 305 293 | 354 42 294 | 355 34 295 | 356 9 296 | 356 11 297 | 357 99 298 | 358 359 299 | 359 28 300 | 360 250 301 | 360 205 302 | 360 413 303 | 361 313 304 | 361 358 305 | 362 283 306 | 363 208 307 | 364 219 308 | 365 159 309 | 366 367 310 | 366 279 311 | 367 240 312 | 368 26 313 | 368 27 314 | 369 76 315 | 370 142 316 | 371 400 317 | 372 338 318 | 373 55 319 | 374 235 320 | 375 417 321 | 376 402 322 | 376 403 323 | 377 292 324 | 378 56 325 | 379 364 326 | 380 202 327 | 381 43 328 | 381 37 329 | 381 39 330 | 382 131 331 | 383 127 332 | 384 113 333 | 384 121 334 | 384 123 335 | 384 124 336 | 384 126 337 | 384 128 338 | 385 129 339 | 385 125 340 | 386 130 341 | 387 120 342 | 388 65 343 | 388 66 344 | 388 59 345 | 388 60 346 | 388 61 347 | 388 62 348 | 388 64 349 | 389 63 350 | 390 84 351 | 391 177 352 | 392 71 353 | 392 72 354 | 393 226 355 | 394 69 356 | 395 67 357 | 396 215 358 | 397 179 359 | 397 172 360 | 397 173 361 | 398 354 362 | 398 228 363 | 398 103 364 | 398 265 365 | 398 407 366 | 398 381 367 | 399 105 368 | 399 22 369 | 400 377 370 | 400 401 371 | 401 293 372 | 401 239 373 | 402 53 374 | 403 50 375 | 403 51 376 | 404 290 377 | 404 302 378 | 405 163 379 | 405 164 380 | 405 165 381 | 405 167 382 | 405 169 383 | 405 171 384 | 405 109 385 | 405 174 386 | 405 175 387 | 405 176 388 | 405 182 389 | 405 158 390 | 405 160 391 | 406 10 392 | 407 102 393 | 407 40 394 | 408 170 395 | 408 168 396 | 408 200 397 | 409 145 398 | 410 118 399 | 411 80 400 | 412 92 401 | 412 399 402 | 413 222 403 | 414 47 404 | 415 258 405 | 415 363 406 | 415 366 407 | 415 281 408 | 415 380 409 | 415 416 410 | 416 379 411 | 417 52 412 | 418 183 413 | 418 184 414 | 419 13 415 | 420 266 416 | 420 348 417 | 420 404 418 | 420 421 419 | 420 415 420 | 421 353 421 | -------------------------------------------------------------------------------- /CUB-Hierarchy/cub_flat.parent-child.txt: -------------------------------------------------------------------------------- 1 | 352 81 2 | 244 177 3 | 245 162 4 | 245 180 5 | 202 75 6 | 203 91 7 | 205 105 8 | 205 22 9 | 207 63 10 | 206 207 11 | 206 208 12 | 206 209 13 | 206 210 14 | 206 211 15 | 206 212 16 | 206 213 17 | 206 214 18 | 209 142 19 | 210 84 20 | 211 147 21 | 213 65 22 | 213 66 23 | 213 59 24 | 213 60 25 | 213 61 26 | 213 62 27 | 213 64 28 | 214 146 29 | 214 141 30 | 214 144 31 | 216 53 32 | 217 52 33 | 218 50 34 | 218 51 35 | 208 145 36 | 221 8 37 | 224 225 38 | 225 339 39 | 225 293 40 | 225 334 41 | 226 227 42 | 227 92 43 | 227 205 44 | 228 68 45 | 229 3 46 | 231 118 47 | 233 127 48 | 235 129 49 | 235 125 50 | 236 41 51 | 236 77 52 | 236 78 53 | 237 238 54 | 237 239 55 | 237 240 56 | 237 241 57 | 237 242 58 | 237 243 59 | 237 244 60 | 237 245 61 | 237 246 62 | 237 247 63 | 237 220 64 | 238 181 65 | 239 179 66 | 239 172 67 | 239 173 68 | 240 170 69 | 240 200 70 | 240 168 71 | 241 99 72 | 242 163 73 | 242 164 74 | 242 165 75 | 242 167 76 | 242 169 77 | 242 171 78 | 242 109 79 | 242 174 80 | 242 175 81 | 242 176 82 | 242 182 83 | 242 158 84 | 242 160 85 | 243 161 86 | 243 166 87 | 246 178 88 | 247 183 89 | 247 184 90 | 249 67 91 | 250 25 92 | 250 23 93 | 250 24 94 | 252 18 95 | 253 249 96 | 253 204 97 | 253 254 98 | 253 228 99 | 255 256 100 | 256 28 101 | 258 88 102 | 259 13 103 | 260 12 104 | 215 217 105 | 215 218 106 | 215 216 107 | 263 49 108 | 264 9 109 | 264 11 110 | 265 253 111 | 266 267 112 | 266 268 113 | 266 269 114 | 266 232 115 | 267 57 116 | 268 54 117 | 268 14 118 | 268 15 119 | 268 16 120 | 269 17 121 | 271 94 122 | 272 273 123 | 273 335 124 | 273 251 125 | 273 351 126 | 273 352 127 | 275 138 128 | 276 136 129 | 277 137 130 | 280 233 131 | 280 201 132 | 280 235 133 | 280 281 134 | 280 282 135 | 280 283 136 | 280 284 137 | 280 285 138 | 280 286 139 | 280 287 140 | 280 288 141 | 281 130 142 | 282 115 143 | 282 116 144 | 282 117 145 | 282 119 146 | 283 76 147 | 284 148 148 | 284 21 149 | 285 113 150 | 285 121 151 | 285 123 152 | 285 124 153 | 285 126 154 | 285 128 155 | 286 131 156 | 287 120 157 | 288 122 158 | 288 132 159 | 288 133 160 | 290 364 161 | 291 74 162 | 220 159 163 | 295 151 164 | 295 152 165 | 295 153 166 | 295 154 167 | 295 155 168 | 295 156 169 | 295 157 170 | 296 257 171 | 296 297 172 | 296 266 173 | 296 298 174 | 296 299 175 | 296 300 176 | 296 270 177 | 296 301 178 | 296 302 179 | 296 303 180 | 296 237 181 | 296 304 182 | 296 305 183 | 296 306 184 | 296 307 185 | 296 308 186 | 296 280 187 | 296 274 188 | 296 309 189 | 296 310 190 | 296 255 191 | 297 328 192 | 298 202 193 | 298 291 194 | 298 333 195 | 298 362 196 | 298 363 197 | 299 319 198 | 300 354 199 | 300 355 200 | 300 292 201 | 300 103 202 | 300 236 203 | 300 312 204 | 301 330 205 | 301 332 206 | 301 336 207 | 301 337 208 | 301 278 209 | 301 279 210 | 302 252 211 | 303 331 212 | 304 325 213 | 305 357 214 | 305 326 215 | 305 327 216 | 305 360 217 | 305 341 218 | 305 311 219 | 306 248 220 | 307 295 221 | 308 231 222 | 309 321 223 | 309 203 224 | 309 222 225 | 309 320 226 | 310 340 227 | 311 198 228 | 312 42 229 | 313 314 230 | 313 315 231 | 314 44 232 | 315 250 233 | 316 188 234 | 317 106 235 | 318 192 236 | 319 85 237 | 320 149 238 | 321 19 239 | 322 323 240 | 322 324 241 | 323 294 242 | 324 229 243 | 324 223 244 | 325 20 245 | 326 196 246 | 326 199 247 | 327 193 248 | 328 104 249 | 329 4 250 | 330 35 251 | 331 185 252 | 331 186 253 | 332 56 254 | 333 107 255 | 333 108 256 | 333 29 257 | 333 30 258 | 334 89 259 | 335 83 260 | 336 47 261 | 337 34 262 | 338 100 263 | 338 101 264 | 339 46 265 | 339 87 266 | 340 134 267 | 341 197 268 | 342 221 269 | 342 344 270 | 342 343 271 | 342 317 272 | 343 58 273 | 344 5 274 | 344 6 275 | 344 7 276 | 345 338 277 | 346 215 278 | 347 318 279 | 347 316 280 | 347 219 281 | 347 348 282 | 347 349 283 | 347 350 284 | 348 36 285 | 349 189 286 | 349 191 287 | 350 190 288 | 351 80 289 | 230 26 290 | 230 27 291 | 353 347 292 | 354 102 293 | 354 40 294 | 355 38 295 | 356 345 296 | 357 194 297 | 358 359 298 | 359 71 299 | 359 72 300 | 360 195 301 | 361 33 302 | 361 31 303 | 361 32 304 | 362 73 305 | 363 93 306 | 232 139 307 | 232 140 308 | 365 361 309 | 365 329 310 | 365 110 311 | 366 206 312 | 366 358 313 | 366 342 314 | 367 353 315 | 367 322 316 | 367 289 317 | 367 356 318 | 367 226 319 | 367 296 320 | 367 265 321 | 367 366 322 | 367 272 323 | 367 368 324 | 367 313 325 | 367 346 326 | 367 224 327 | 368 365 328 | 270 271 329 | 222 150 330 | 248 111 331 | 248 112 332 | 223 1 333 | 223 2 334 | 261 97 335 | 261 98 336 | 261 95 337 | 261 96 338 | 262 10 339 | 257 258 340 | 257 259 341 | 257 260 342 | 257 261 343 | 257 262 344 | 257 230 345 | 257 263 346 | 257 264 347 | 274 234 348 | 274 275 349 | 274 276 350 | 274 277 351 | 251 82 352 | 251 79 353 | 254 70 354 | 279 48 355 | 364 86 356 | 289 290 357 | 292 43 358 | 292 37 359 | 292 39 360 | 293 90 361 | 294 45 362 | 278 55 363 | 201 114 364 | 204 69 365 | 212 143 366 | 234 135 367 | 219 187 368 | -------------------------------------------------------------------------------- /CUB-Hierarchy/cub_wikispecies.parent-child.txt: -------------------------------------------------------------------------------- 1 | 274 9 2 | 274 11 3 | 376 69 4 | 233 234 5 | 364 47 6 | 267 67 7 | 202 266 8 | 202 291 9 | 202 110 10 | 203 103 11 | 203 204 12 | 203 205 13 | 203 206 14 | 203 207 15 | 203 208 16 | 204 42 17 | 205 41 18 | 205 77 19 | 205 78 20 | 206 43 21 | 206 37 22 | 206 39 23 | 207 102 24 | 207 40 25 | 208 38 26 | 209 194 27 | 210 211 28 | 211 86 29 | 212 70 30 | 213 13 31 | 216 187 32 | 217 28 33 | 218 161 34 | 218 166 35 | 220 1 36 | 220 2 37 | 221 3 38 | 222 223 39 | 223 18 40 | 225 282 41 | 225 380 42 | 225 326 43 | 226 227 44 | 227 151 45 | 227 152 46 | 227 153 47 | 227 154 48 | 227 155 49 | 227 156 50 | 227 157 51 | 229 353 52 | 229 335 53 | 230 83 54 | 234 104 55 | 236 94 56 | 237 226 57 | 237 238 58 | 237 239 59 | 238 363 60 | 239 281 61 | 239 277 62 | 239 278 63 | 239 279 64 | 239 280 65 | 382 35 66 | 241 54 67 | 241 14 68 | 241 15 69 | 241 16 70 | 242 106 71 | 243 228 72 | 243 201 73 | 243 244 74 | 243 245 75 | 243 246 76 | 243 247 77 | 243 248 78 | 243 249 79 | 243 250 80 | 243 251 81 | 243 252 82 | 243 253 83 | 243 224 84 | 244 345 85 | 244 219 86 | 245 309 87 | 245 334 88 | 246 329 89 | 247 365 90 | 248 371 91 | 248 320 92 | 316 181 93 | 251 210 94 | 253 231 95 | 254 257 96 | 254 258 97 | 254 259 98 | 254 260 99 | 254 261 100 | 254 262 101 | 254 233 102 | 254 235 103 | 254 255 104 | 254 256 105 | 255 337 106 | 255 338 107 | 255 339 108 | 255 241 109 | 214 162 110 | 214 180 111 | 257 355 112 | 257 356 113 | 257 357 114 | 257 358 115 | 257 330 116 | 257 307 117 | 257 340 118 | 257 214 119 | 257 218 120 | 257 316 121 | 257 317 122 | 258 292 123 | 259 359 124 | 259 360 125 | 259 361 126 | 259 331 127 | 259 240 128 | 259 274 129 | 259 213 130 | 259 215 131 | 260 295 132 | 260 263 133 | 260 362 134 | 260 364 135 | 260 286 136 | 260 382 137 | 261 293 138 | 215 88 139 | 263 48 140 | 264 84 141 | 266 33 142 | 266 31 143 | 266 32 144 | 268 267 145 | 268 212 146 | 268 375 147 | 268 376 148 | 269 44 149 | 270 366 150 | 271 145 151 | 272 58 152 | 273 327 153 | 273 333 154 | 273 372 155 | 273 373 156 | 273 374 157 | 273 216 158 | 275 196 159 | 275 199 160 | 276 198 161 | 277 107 162 | 277 108 163 | 277 29 164 | 277 30 165 | 278 93 166 | 279 75 167 | 280 73 168 | 281 74 169 | 283 63 170 | 285 81 171 | 287 80 172 | 289 290 173 | 289 92 174 | 290 105 175 | 290 22 176 | 291 4 177 | 292 118 178 | 293 20 179 | 294 143 180 | 295 56 181 | 296 82 182 | 296 79 183 | 297 130 184 | 298 129 185 | 298 125 186 | 299 120 187 | 300 113 188 | 300 121 189 | 300 123 190 | 300 124 191 | 300 126 192 | 300 128 193 | 301 76 194 | 302 127 195 | 303 115 196 | 303 116 197 | 303 117 198 | 303 119 199 | 304 131 200 | 305 148 201 | 305 21 202 | 306 122 203 | 306 132 204 | 306 133 205 | 307 163 206 | 307 164 207 | 307 165 208 | 307 167 209 | 307 169 210 | 307 171 211 | 307 109 212 | 307 174 213 | 307 175 214 | 307 176 215 | 307 182 216 | 307 158 217 | 307 160 218 | 308 222 219 | 309 237 220 | 309 308 221 | 309 310 222 | 309 311 223 | 309 312 224 | 309 254 225 | 310 319 226 | 311 322 227 | 311 332 228 | 312 354 229 | 312 341 230 | 312 383 231 | 284 114 232 | 314 283 233 | 314 343 234 | 314 264 235 | 315 352 236 | 315 271 237 | 315 294 238 | 315 351 239 | 315 328 240 | 224 225 241 | 317 99 242 | 318 5 243 | 318 6 244 | 318 7 245 | 319 377 246 | 319 265 247 | 319 325 248 | 319 350 249 | 320 321 250 | 321 370 251 | 321 318 252 | 321 242 253 | 321 272 254 | 322 323 255 | 322 324 256 | 322 209 257 | 322 275 258 | 322 276 259 | 322 288 260 | 323 195 261 | 324 193 262 | 326 52 263 | 327 188 264 | 328 146 265 | 328 141 266 | 328 144 267 | 329 378 268 | 329 379 269 | 329 367 270 | 330 177 271 | 331 12 272 | 332 217 273 | 333 36 274 | 334 203 275 | 335 230 276 | 336 85 277 | 337 139 278 | 337 140 279 | 338 17 280 | 339 57 281 | 340 159 282 | 341 342 283 | 342 185 284 | 342 186 285 | 343 65 286 | 343 66 287 | 343 59 288 | 343 60 289 | 343 61 290 | 343 62 291 | 343 64 292 | 344 149 293 | 345 346 294 | 346 45 295 | 347 134 296 | 348 349 297 | 349 71 298 | 349 72 299 | 350 138 300 | 351 142 301 | 352 147 302 | 353 285 303 | 353 287 304 | 353 296 305 | 354 347 306 | 355 178 307 | 356 170 308 | 356 200 309 | 356 168 310 | 357 183 311 | 357 184 312 | 231 232 313 | 359 10 314 | 360 97 315 | 360 98 316 | 360 95 317 | 360 96 318 | 361 49 319 | 362 34 320 | 363 111 321 | 363 112 322 | 232 100 323 | 232 101 324 | 365 289 325 | 366 25 326 | 366 23 327 | 366 24 328 | 367 46 329 | 367 87 330 | 368 19 331 | 369 150 332 | 370 8 333 | 371 313 334 | 371 348 335 | 372 189 336 | 372 191 337 | 373 192 338 | 374 190 339 | 375 68 340 | 252 269 341 | 252 270 342 | 377 136 343 | 378 90 344 | 379 89 345 | 380 53 346 | 381 91 347 | 235 236 348 | 383 369 349 | 383 381 350 | 383 344 351 | 383 368 352 | 219 220 353 | 219 221 354 | 240 26 355 | 240 27 356 | 249 268 357 | 250 273 358 | 358 179 359 | 358 172 360 | 358 173 361 | 256 336 362 | 262 297 363 | 262 298 364 | 262 299 365 | 262 300 366 | 262 301 367 | 262 302 368 | 262 303 369 | 262 304 370 | 262 305 371 | 262 306 372 | 262 284 373 | 282 50 374 | 282 51 375 | 228 229 376 | 286 55 377 | 265 135 378 | 288 197 379 | 313 314 380 | 313 315 381 | 201 202 382 | 325 137 383 | -------------------------------------------------------------------------------- /CUB-Hierarchy/encode_hierarchy.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import argparse 3 | import pickle 4 | 5 | 6 | 7 | def read_hierarchy(filename): 8 | 9 | hierarchy = {} 10 | stack = [] 11 | last_node = None 12 | 13 | with open(filename) as f: 14 | for li, l in enumerate(f, start = 1): 15 | l = l.strip() 16 | if l != '': 17 | 18 | orig_node_name = l.lstrip('- ') 19 | node_name = orig_node_name.rstrip(' ?') 20 | parens_pos = node_name.find('(') 21 | if parens_pos > 0: 22 | node_name = node_name[:parens_pos-1] 23 | if node_name in hierarchy: 24 | raise RuntimeError('Duplicate node name: {} (at line {})'.format(node_name, li)) 25 | 26 | node_level = max(0, len(l) - len(orig_node_name) - 1) 27 | if node_level % 2 != 0: 28 | raise RuntimeError('Incorrect indentation at line {}: {}'.format(li, l)) 29 | node_level //= 2 30 | if node_level > len(stack) + 1: 31 | raise RuntimeError('Unexpectedly deep indentation at line {}: {}'.format(li, l)) 32 | 33 | if node_level > len(stack): 34 | if last_node is None: 35 | raise RuntimeError('First line must not be indented.') 36 | stack.append(last_node) 37 | elif node_level < len(stack): 38 | stack = stack[:node_level] 39 | 40 | hierarchy[node_name] = set() 41 | if len(stack) > 0: 42 | hierarchy[stack[-1]].add(node_name) 43 | last_node = node_name 44 | 45 | return hierarchy 46 | 47 | 48 | def encode_class_names(hierarchy, initial_labels): 49 | 50 | class_names = [lbl for lbl in initial_labels] 51 | class_ind = { lbl : i for i, lbl in enumerate(class_names) } 52 | 53 | hierarchy_names = list(hierarchy.keys()) 54 | for name in hierarchy_names: 55 | 56 | if name in class_ind: 57 | ind = class_ind[name] 58 | else: 59 | ind = len(class_names) 60 | class_ind[name] = ind 61 | class_names.append(name) 62 | 63 | encoded_children = set() 64 | for child in hierarchy[name]: 65 | if child in class_ind: 66 | encoded_children.add(class_ind[child]) 67 | else: 68 | encoded_children.add(len(class_names)) 69 | class_ind[child] = len(class_names) 70 | class_names.append(child) 71 | 72 | hierarchy[ind] = encoded_children 73 | del hierarchy[name] 74 | 75 | return hierarchy, class_names 76 | 77 | 78 | def save_hierarchy(hierarchy, filename): 79 | 80 | with open(filename, 'w') as f: 81 | for parent, children in hierarchy.items(): 82 | for child in children: 83 | f.write('{} {}\n'.format(parent+1, child+1)) 84 | 85 | 86 | def plot_hierarchy(hierarchy, filename): 87 | 88 | import pydot 89 | 90 | graph = pydot.Dot(graph_type = 'digraph', rankdir = 'LR') 91 | nodes = { name : pydot.Node(name, style = 'filled', fillcolor = '#ffffff' if len(children) == 0 else '#eaeaea') for name, children in hierarchy.items() } 92 | for node in nodes.values(): 93 | graph.add_node(node) 94 | 95 | for parent, children in hierarchy.items(): 96 | for child in children: 97 | graph.add_edge(pydot.Edge(nodes[parent], nodes[child])) 98 | 99 | graph.write_svg(filename, prog = 'dot') 100 | 101 | 102 | 103 | if __name__ == '__main__': 104 | 105 | parser = argparse.ArgumentParser( 106 | description='Translates a hierarchy given in indented tree-form into a list of parent-child tuples.', 107 | formatter_class=argparse.ArgumentDefaultsHelpFormatter 108 | ) 109 | parser.add_argument('hierarchy_file', type=str, help='The input file specifying the hierarchy in indented tree format.') 110 | parser.add_argument('class_names', type=str, default=None, 111 | help='Path to a text file associating CUB labels (1-200) with the names of their nodes in the hierarchy. These labels will be maintained.') 112 | parser.add_argument('--out', type=str, default='cub.parent-child.txt', help='Output file containing parent-child tuples.') 113 | parser.add_argument('--out_names', type=str, default='class_names.txt', help='Output file associating numerical class labels with their original names.') 114 | parser.add_argument('--plot', type=str, default=None, help='If given, a plot of the hierarchy will be written to the specified file. Requires the pydot package.') 115 | args = parser.parse_args() 116 | 117 | if args.class_names: 118 | with open(args.class_names) as f: 119 | initial_labels = { int(lbl) : node_name for line in f if line.strip() != '' for lbl, node_name in [line.strip().split(maxsplit=1)] } 120 | else: 121 | initial_labels = {} 122 | 123 | hierarchy = read_hierarchy(args.hierarchy_file) 124 | if args.plot is not None: 125 | plot_hierarchy(hierarchy, args.plot) 126 | hierarchy, node_names = encode_class_names(hierarchy, (classname for _, classname in sorted(initial_labels.items()))) 127 | 128 | save_hierarchy(hierarchy, args.out) 129 | 130 | with open(args.out_names, 'w') as f: 131 | for ind, name in enumerate(node_names, 1): 132 | f.write('{} {}\n'.format(ind, name)) 133 | -------------------------------------------------------------------------------- /CUB-Hierarchy/hierarchy_flat.txt: -------------------------------------------------------------------------------- 1 | Aves 2 | 3 | -- Procellariiformes 4 | ---- Procellariidae 5 | ------ Fulmarus 6 | -------- Fulmarus glacialis 7 | ---- Diomedeidae 8 | ------ Phoebastria 9 | -------- Phoebastria nigripes 10 | -------- Phoebastria immutabilis 11 | ------ Phoebetria 12 | -------- Phoebetria fusca 13 | 14 | -- Cuculiformes 15 | ---- Cuculidae 16 | ------ Crotophaga 17 | -------- Crotophaga sulcirostris 18 | ------ Coccyzus 19 | -------- Coccyzus erythropthalmus 20 | -------- Coccyzus minor 21 | -------- Coccyzus americanus 22 | ------ Geococcyx 23 | 24 | -- Charadriiformes 25 | ---- Alcidae 26 | ------ Aethia 27 | -------- Aethia cristatella 28 | -------- Aethia pusilla 29 | -------- Aethia psittacula 30 | ------ Cerorhinca 31 | -------- Cerorhinca monocerata 32 | ------ Cepphus 33 | -------- Cepphus columba 34 | ------ Fratercula 35 | -------- Fratercula corniculata 36 | ---- Laridae 37 | ------ Larus 38 | -------- Larus californicus 39 | -------- Larus glaucescens 40 | -------- Larus heermanni 41 | -------- Larus argentatus 42 | -------- Larus delawarensis 43 | -------- Larus schistisagus 44 | -------- Larus occidentalis 45 | ------ Pagophila 46 | -------- Pagophila eburnea 47 | ------ Rissa 48 | -------- Rissa brevirostris 49 | ------ Sterna 50 | -------- Sterna paradisaea 51 | -------- Sterna hirundo 52 | -------- Sterna forsteri 53 | ------ Sternula 54 | -------- Sternula antillarum 55 | ------ Chlidonias 56 | -------- Chlidonias niger 57 | ------ Hydroprogne 58 | -------- Hydroprogne caspia 59 | ------ Thalasseus 60 | -------- Thalasseus elegans 61 | ---- Stercorariidae 62 | ------ Stercorarius 63 | -------- Stercorarius longicaudus 64 | -------- Stercorarius pomarinus 65 | 66 | -- Suliformes 67 | ---- Phalacrocoracidae 68 | ------ Phalacrocorax 69 | -------- Phalacrocorax penicillatus 70 | -------- Phalacrocorax urile 71 | -------- Phalacrocorax pelagicus 72 | ---- Fregatidae 73 | ------ Fregata 74 | 75 | -- Piciformes 76 | ---- Picidae 77 | ------ Colaptes 78 | -------- Colaptes auratus 79 | ------ Picoides 80 | -------- Picoides dorsalis 81 | ------ Dryocopus 82 | -------- Dryocopus pileatus 83 | ------ Dryobates 84 | -------- Dryobates pubescens 85 | ------ Melanerpes 86 | -------- Melanerpes carolinus 87 | -------- Melanerpes erythrocephalus 88 | ------ Leuconotopicus 89 | -------- Leuconotopicus borealis 90 | 91 | -- Anseriformes 92 | ---- Anatidae 93 | ------ Anas 94 | -------- Anas strepera 95 | -------- Anas platyrhynchos 96 | ------ Lophodytes 97 | -------- Lophodytes cucullatus 98 | ------ Merginae 99 | -------- Mergus serrator 100 | 101 | -- Podicipediformes 102 | ---- Podicipedidae 103 | ------ Podiceps 104 | -------- Podiceps nigricollis 105 | -------- Podiceps auritus 106 | ------ Podilymbus 107 | -------- Podilymbus podiceps 108 | ------ Aechmophorus 109 | -------- Aechmophorus occidentalis 110 | 111 | -- Trochiliformes 112 | ---- Trochilidae 113 | ------ Calypte 114 | -------- Calypte anna 115 | ------ Archilochus 116 | -------- Archilochus colubris 117 | ------ Selasphorus 118 | -------- Selasphorus rufus 119 | ------ Colibri 120 | -------- Colibri thalassinus 121 | 122 | -- Coraciiformes 123 | ---- Alcedinidae 124 | ------ Megaceryle 125 | -------- Megaceryle alcyon 126 | -------- Megaceryle torquata 127 | ------ Chloroceryle 128 | -------- Chloroceryle americana 129 | ------ Ceryle 130 | -------- Ceryle rudis 131 | ------ Halcyon 132 | -------- Halcyon smyrnensis 133 | 134 | -- Gaviiformes 135 | ---- Gaviidae 136 | ------ Gavia 137 | -------- Gavia pacifica 138 | 139 | -- Pelecaniformes 140 | ---- Pelecanidae 141 | ------ Pelecanus 142 | -------- Pelecanus occidentalis 143 | -------- Pelecanus onocrotalus 144 | 145 | -- Passeriformes 146 | ---- Icteridae 147 | ------ Euphagus 148 | -------- Euphagus cyanocephalus 149 | -------- Euphagus carolinus 150 | ------ Agelaius 151 | -------- Agelaius phoeniceus 152 | ------ Xanthocephalus 153 | -------- Xanthocephalus xanthocephalus 154 | ------ Dolichonyx 155 | -------- Dolichonyx oryzivorus 156 | ------ Molothrus 157 | -------- Molothrus aeneus 158 | -------- Molothrus bonariensis 159 | ------ Quiscalus 160 | -------- Quiscalus major 161 | ------ Sturnella 162 | -------- Sturnella neglecta 163 | ------ Icterus 164 | -------- Icterus galbula 165 | -------- Icterus cucullatus 166 | -------- Icterus spurius 167 | -------- Icterus parisorum 168 | ---- Icteriidae 169 | ------ Icteria 170 | -------- Icteria virens 171 | ---- Cardinalidae 172 | ------ Passerina 173 | -------- Passerina cyanea 174 | -------- Passerina amoena 175 | -------- Passerina ciris 176 | -------- Passerina caerulea 177 | ------ Cardinalis 178 | -------- Cardinalis cardinalis 179 | ------ Pheucticus 180 | -------- Pheucticus ludovicianus 181 | ------ Piranga 182 | -------- Piranga olivacea 183 | -------- Piranga rubra 184 | ---- Passerellidae 185 | ------ Passerella 186 | -------- Passerella iliaca 187 | ------ Passerculus 188 | -------- Passerculus sandwichensis 189 | ------ Pipilo 190 | -------- Pipilo erythrophthalmus 191 | -------- Pipilo chlorurus 192 | ------ Junco 193 | -------- Junco hyemalis 194 | ------ Ammodramus 195 | -------- Ammodramus bairdii 196 | -------- Ammodramus savannarum 197 | -------- Ammodramus henslowii 198 | -------- Ammodramus leconteii 199 | -------- Ammodramus nelsoni 200 | -------- Ammodramus maritimus 201 | ------ Amphispiza 202 | -------- Amphispiza bilineata 203 | ------ Spizella 204 | -------- Spizella breweri 205 | -------- Spizella passerina 206 | -------- Spizella pallida 207 | -------- Spizella pusilla 208 | ------ Spizelloides 209 | -------- Spizelloides arborea 210 | ------ Melospiza 211 | -------- Melospiza lincolnii 212 | -------- Melospiza melodia 213 | ------ Zonotrichia 214 | -------- Zonotrichia querula 215 | -------- Zonotrichia leucophrys 216 | -------- Zonotrichia albicollis 217 | ------ Pooecetes 218 | -------- Pooecetes gramineus 219 | ---- Passeridae 220 | ------ Passer 221 | -------- Passer domesticus 222 | ---- Fringillidae 223 | ------ Leucosticte 224 | -------- Leucosticte tephrocotis 225 | ------ Haemorhous 226 | -------- Haemorhous purpureus 227 | ------ Spinus 228 | -------- Spinus tristis 229 | ------ Carduelis 230 | -------- Carduelis carduelis 231 | ------ Hesperiphona 232 | -------- Hesperiphona vespertina 233 | ------ Pinicola 234 | -------- Pinicola enucleator 235 | ---- Alaudidae 236 | ------ Eremophila 237 | -------- Eremophila alpestris 238 | ---- Sittidae 239 | ------ Sitta 240 | -------- Sitta carolinensis 241 | ---- Parulidae 242 | ------ Seiurus 243 | -------- Seiurus aurocapilla 244 | ------ Setophaga 245 | -------- Setophaga ruticilla 246 | -------- Setophaga castanea 247 | -------- Setophaga caerulescens 248 | -------- Setophaga tigrina 249 | -------- Setophaga cerulea 250 | -------- Setophaga pensylvanica 251 | -------- Setophaga citrina 252 | -------- Setophaga magnolia 253 | -------- Setophaga coronata 254 | -------- Setophaga palmarum 255 | -------- Setophaga discolor 256 | -------- Setophaga aestiva 257 | -------- Setophaga pinus 258 | ------ Mniotilta 259 | -------- Mniotilta varia 260 | ------ Vermivora 261 | -------- Vermivora cyanoptera 262 | -------- Vermivora chrysoptera 263 | ------ Cardellina 264 | -------- Cardellina canadensis 265 | -------- Cardellina pusilla 266 | ------ Geothlypis 267 | -------- Geothlypis formosa 268 | -------- Geothlypis philadelphia 269 | -------- Geothlypis trichas 270 | ------ Leiothlypis 271 | -------- Leiothlypis ruficapilla 272 | -------- Leiothlypis celata 273 | -------- Leiothlypis peregrina 274 | ------ Protonotaria 275 | -------- Protonotaria citrea 276 | ------ Limnothlypis 277 | -------- Limnothlypis swainsonii 278 | ------ Helmitheros 279 | -------- Helmitheros vermivorum 280 | ------ Parkesia 281 | -------- Parkesia noveboracensis 282 | -------- Parkesia motacilla 283 | ---- Motacillidae 284 | ------ Anthus 285 | -------- Anthus rubescens 286 | ---- Ptilonorhynchidae 287 | ------ Ailuroedus 288 | -------- Ailuroedus melanotis 289 | ---- Mimidae 290 | ------ Mimus 291 | -------- Mimus polyglottos 292 | ------ Dumetella 293 | -------- Dumetella carolinensis 294 | ------ Toxostoma 295 | -------- Toxostoma rufum 296 | ------ Oreoscoptes 297 | -------- Oreoscoptes montanus 298 | ---- Sturnidae 299 | ------ Lamprotornis 300 | -------- Lamprotornis nitens 301 | ---- Bombycillidae 302 | ------ Bombycilla 303 | -------- Bombycilla garrulus 304 | -------- Bombycilla cedrorum 305 | ---- Certhiidae 306 | ------ Certhia 307 | -------- Certhia americana 308 | ---- Troglodytidae 309 | ------ Thryomanes 310 | -------- Thryomanes bewickii 311 | ------ Campylorhynchus 312 | -------- Campylorhynchus brunneicapillus 313 | ------ Thryothorus 314 | -------- Thryothorus ludovicianus 315 | ------ Troglodytes 316 | -------- Troglodytes aedon 317 | -------- Troglodytes hiemalis 318 | ------ Cistothorus 319 | -------- Cistothorus palustris 320 | ------ Salpinctes 321 | -------- Salpinctes obsoletus 322 | ---- Corvidae 323 | ------ Corvus 324 | -------- Corvus brachyrhynchos 325 | -------- Corvus ossifragus 326 | -------- Corvus corax 327 | -------- Corvus albicollis 328 | ------ Cyanocitta 329 | -------- Cyanocitta cristata 330 | ------ Cyanocorax 331 | -------- Cyanocorax luxuosus 332 | ------ Aphelocoma 333 | -------- Aphelocoma coerulescens 334 | ------ Nucifraga 335 | -------- Nucifraga columbiana 336 | ---- Laniidae 337 | ------ Lanius 338 | -------- Lanius ludovicianus 339 | -------- Lanius excubitor 340 | ---- Vireonidae 341 | ------ Vireo 342 | -------- Vireo atricapilla 343 | -------- Vireo solitarius 344 | -------- Vireo philadelphicus 345 | -------- Vireo olivaceus 346 | -------- Vireo gilvus 347 | -------- Vireo griseus 348 | -------- Vireo flavifrons 349 | ---- Hirundinidae 350 | ------ Hirundo 351 | -------- Hirundo rustica 352 | ------ Riparia 353 | -------- Riparia riparia 354 | ------ Petrochelidon 355 | -------- Petrochelidon pyrrhonota 356 | ------ Tachycineta 357 | -------- Tachycineta bicolor 358 | ---- Tyrannidae 359 | ------ Empidonax 360 | -------- Empidonax virescens 361 | -------- Empidonax minimus 362 | -------- Empidonax flaviventris 363 | ------ Myiarchus 364 | -------- Myiarchus crinitus 365 | ------ Contopus 366 | -------- Contopus cooperi 367 | -------- Contopus sordidulus 368 | ------ Tyrannus 369 | -------- Tyrannus forficatus 370 | -------- Tyrannus melancholicus 371 | -------- Tyrannus dominicensis 372 | ------ Pyrocephalus 373 | -------- Pyrocephalus obscurus 374 | ------ Sayornis 375 | 376 | -- Caprimulgiformes 377 | ---- Caprimulgidae 378 | ------ Caprimulgus 379 | -------- Caprimulgus carolinensis 380 | -------- Caprimulgus vociferus 381 | ------ Chordeiles -------------------------------------------------------------------------------- /Cifar-Hierarchy/cifar.parent-child.txt: -------------------------------------------------------------------------------- 1 | 100 53 2 | 101 83 3 | 103 0 4 | 103 57 5 | 104 105 6 | 104 106 7 | 105 154 8 | 105 139 9 | 106 72 10 | 106 117 11 | 107 80 12 | 107 50 13 | 107 4 14 | 107 36 15 | 107 63 16 | 108 112 17 | 108 109 18 | 108 110 19 | 108 111 20 | 110 129 21 | 110 130 22 | 111 49 23 | 111 60 24 | 111 71 25 | 111 23 26 | 112 51 27 | 112 101 28 | 112 102 29 | 114 75 30 | 114 55 31 | 115 116 32 | 115 84 33 | 115 5 34 | 115 94 35 | 118 35 36 | 118 11 37 | 119 68 38 | 120 17 39 | 120 12 40 | 120 159 41 | 121 41 42 | 122 40 43 | 122 22 44 | 122 87 45 | 122 86 46 | 122 39 47 | 123 69 48 | 123 135 49 | 124 16 50 | 124 28 51 | 124 61 52 | 124 151 53 | 125 88 54 | 125 42 55 | 125 43 56 | 126 31 57 | 127 1 58 | 127 91 59 | 130 141 60 | 130 150 61 | 131 62 62 | 131 82 63 | 131 54 64 | 132 136 65 | 132 33 66 | 133 131 67 | 133 92 68 | 133 70 69 | 134 98 70 | 134 46 71 | 135 8 72 | 135 161 73 | 135 156 74 | 135 113 75 | 136 96 76 | 136 56 77 | 136 59 78 | 136 52 79 | 136 47 80 | 137 19 81 | 137 15 82 | 139 73 83 | 139 67 84 | 140 97 85 | 140 34 86 | 141 104 87 | 141 145 88 | 141 144 89 | 141 142 90 | 141 143 91 | 142 160 92 | 142 99 93 | 142 77 94 | 109 115 95 | 109 119 96 | 109 120 97 | 109 121 98 | 109 122 99 | 109 123 100 | 109 124 101 | 144 128 102 | 144 137 103 | 144 107 104 | 144 147 105 | 144 149 106 | 144 158 107 | 144 126 108 | 145 152 109 | 145 138 110 | 146 18 111 | 146 14 112 | 147 148 113 | 147 114 114 | 147 3 115 | 147 140 116 | 147 125 117 | 148 66 118 | 149 21 119 | 150 2 120 | 150 118 121 | 150 134 122 | 151 9 123 | 151 10 124 | 152 27 125 | 152 44 126 | 152 29 127 | 152 78 128 | 153 32 129 | 154 153 130 | 154 127 131 | 155 64 132 | 155 38 133 | 156 48 134 | 156 89 135 | 156 58 136 | 157 24 137 | 157 146 138 | 157 6 139 | 157 7 140 | 158 74 141 | 159 76 142 | 159 37 143 | 160 162 144 | 160 157 145 | 160 79 146 | 161 81 147 | 161 90 148 | 161 13 149 | 162 26 150 | 162 45 151 | 113 85 152 | 116 25 153 | 116 20 154 | 117 30 155 | 117 95 156 | 128 65 157 | 129 132 158 | 129 133 159 | 138 93 160 | 143 155 161 | 102 100 162 | 102 103 163 | -------------------------------------------------------------------------------- /Cifar-Hierarchy/class_names.txt: -------------------------------------------------------------------------------- 1 | 0 apple 2 | 1 aquarium_fish 3 | 2 baby 4 | 3 bear 5 | 4 beaver 6 | 5 bed 7 | 6 bee 8 | 7 beetle 9 | 8 bicycle 10 | 9 bottle 11 | 10 bowl 12 | 11 boy 13 | 12 bridge 14 | 13 bus 15 | 14 butterfly 16 | 15 camel 17 | 16 can 18 | 17 castle 19 | 18 caterpillar 20 | 19 cattle 21 | 20 chair 22 | 21 chimpanzee 23 | 22 clock 24 | 23 cloud 25 | 24 cockroach 26 | 25 couch 27 | 26 crab 28 | 27 crocodile 29 | 28 cup 30 | 29 dinosaur 31 | 30 dolphin 32 | 31 elephant 33 | 32 flatfish 34 | 33 forest 35 | 34 fox 36 | 35 girl 37 | 36 hamster 38 | 37 house 39 | 38 kangaroo 40 | 39 keyboard 41 | 40 lamp 42 | 41 lawn_mower 43 | 42 leopard 44 | 43 lion 45 | 44 lizard 46 | 45 lobster 47 | 46 man 48 | 47 maple_tree 49 | 48 motorcycle 50 | 49 mountain 51 | 50 mouse 52 | 51 mushroom 53 | 52 oak_tree 54 | 53 orange 55 | 54 orchid 56 | 55 otter 57 | 56 palm_tree 58 | 57 pear 59 | 58 pickup_truck 60 | 59 pine_tree 61 | 60 plain 62 | 61 plate 63 | 62 poppy 64 | 63 porcupine 65 | 64 possum 66 | 65 rabbit 67 | 66 raccoon 68 | 67 ray 69 | 68 road 70 | 69 rocket 71 | 70 rose 72 | 71 sea 73 | 72 seal 74 | 73 shark 75 | 74 shrew 76 | 75 skunk 77 | 76 skyscraper 78 | 77 snail 79 | 78 snake 80 | 79 spider 81 | 80 squirrel 82 | 81 streetcar 83 | 82 sunflower 84 | 83 sweet_pepper 85 | 84 table 86 | 85 tank 87 | 86 telephone 88 | 87 television 89 | 88 tiger 90 | 89 tractor 91 | 90 train 92 | 91 trout 93 | 92 tulip 94 | 93 turtle 95 | 94 wardrobe 96 | 95 whale 97 | 96 willow_tree 98 | 97 wolf 99 | 98 woman 100 | 99 worm 101 | 100 citrus 102 | 101 vegetable 103 | 102 fruit 104 | 103 pome 105 | 104 aquatic_animal 106 | 105 fish 107 | 106 aquatic_mammal 108 | 107 rodent 109 | 108 entity 110 | 109 artifact 111 | 110 organism 112 | 111 natural_scenes 113 | 112 food 114 | 113 military_vehicle 115 | 114 musteline_mammal 116 | 115 furniture 117 | 116 seat 118 | 117 cetacean 119 | 118 child 120 | 119 way 121 | 120 structure 122 | 121 tool 123 | 122 device 124 | 123 vehicle 125 | 124 container 126 | 125 feline 127 | 126 pachyderm 128 | 127 soft-finned_fish 129 | 128 lagomorph 130 | 129 vegetation 131 | 130 living 132 | 131 flower 133 | 132 wooden 134 | 133 blooming 135 | 134 adult 136 | 135 wheeled_vehicle 137 | 136 tree 138 | 137 ungulate 139 | 138 anapsid 140 | 139 cartilaginous_fish 141 | 140 canine 142 | 141 animal 143 | 142 invertebrate 144 | 143 metatherian 145 | 144 placental 146 | 145 reptile 147 | 146 lepidopterous 148 | 147 carnivore 149 | 148 procyonid 150 | 149 primate 151 | 150 people 152 | 151 vessel 153 | 152 diapsid 154 | 153 spiny-finned_fish 155 | 154 bony_fish 156 | 155 marsupial 157 | 156 motor_vehicle 158 | 157 insect 159 | 158 insectivore 160 | 159 building 161 | 160 anthropod 162 | 161 public_transport 163 | 162 crustacean 164 | -------------------------------------------------------------------------------- /Cifar-Hierarchy/encode_hierarchy.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import argparse 3 | import pickle 4 | 5 | 6 | 7 | def read_hierarchy(filename): 8 | 9 | hierarchy = {} 10 | stack = [] 11 | last_node = None 12 | 13 | with open(filename) as f: 14 | for li, l in enumerate(f, start = 1): 15 | l = l.strip() 16 | if l != '': 17 | 18 | node_name = l.lstrip('- ') 19 | if node_name in hierarchy: 20 | raise RuntimeError('Duplicate node name: {} (at line {})'.format(node_name, li)) 21 | 22 | node_level = max(0, len(l) - len(node_name) - 1) 23 | if node_level % 2 != 0: 24 | raise RuntimeError('Incorrect indentation at line {}: {}'.format(li, l)) 25 | node_level //= 2 26 | if node_level > len(stack) + 1: 27 | raise RuntimeError('Unexpectedly deep indentation at line {}: {}'.format(li, l)) 28 | 29 | if node_level > len(stack): 30 | if last_node is None: 31 | raise RuntimeError('First line must not be indented.') 32 | stack.append(last_node) 33 | elif node_level < len(stack): 34 | stack = stack[:node_level] 35 | 36 | hierarchy[node_name] = set() 37 | if len(stack) > 0: 38 | hierarchy[stack[-1]].add(node_name) 39 | last_node = node_name 40 | 41 | return hierarchy 42 | 43 | 44 | def encode_class_names(hierarchy, initial_labels): 45 | 46 | class_names = [lbl for lbl in initial_labels] 47 | class_ind = { lbl : i for i, lbl in enumerate(class_names) } 48 | 49 | hierarchy_names = list(hierarchy.keys()) 50 | for name in hierarchy_names: 51 | 52 | if name in class_ind: 53 | ind = class_ind[name] 54 | else: 55 | ind = len(class_names) 56 | class_ind[name] = ind 57 | class_names.append(name) 58 | 59 | encoded_children = set() 60 | for child in hierarchy[name]: 61 | if child in class_ind: 62 | encoded_children.add(class_ind[child]) 63 | else: 64 | encoded_children.add(len(class_names)) 65 | class_ind[child] = len(class_names) 66 | class_names.append(child) 67 | 68 | hierarchy[ind] = encoded_children 69 | del hierarchy[name] 70 | 71 | return hierarchy, class_names 72 | 73 | 74 | def save_hierarchy(hierarchy, filename): 75 | 76 | with open(filename, 'w') as f: 77 | for parent, children in hierarchy.items(): 78 | for child in children: 79 | f.write('{} {}\n'.format(parent, child)) 80 | 81 | 82 | def plot_hierarchy(hierarchy, filename): 83 | 84 | import pydot 85 | 86 | graph = pydot.Dot(graph_type = 'digraph', rankdir = 'LR') 87 | nodes = { name : pydot.Node(name, style = 'filled', fillcolor = '#ffffff' if len(children) == 0 else '#eaeaea') for name, children in hierarchy.items() } 88 | for node in nodes.values(): 89 | graph.add_node(node) 90 | 91 | for parent, children in hierarchy.items(): 92 | for child in children: 93 | graph.add_edge(pydot.Edge(nodes[parent], nodes[child])) 94 | 95 | graph.write_svg(filename, prog = 'dot') 96 | 97 | 98 | 99 | if __name__ == '__main__': 100 | 101 | parser = argparse.ArgumentParser( 102 | description='Translates a hierarchy given in indented tree-form into a list of parent-child tuples.', 103 | formatter_class=argparse.ArgumentDefaultsHelpFormatter 104 | ) 105 | parser.add_argument('hierarchy_file', type=str, help='The input file specifying the hierarchy in indented tree format.') 106 | parser.add_argument('meta_file', type=str, help='Path to the meta pickle file from CIFAR-100.') 107 | parser.add_argument('--out', type=str, default='cifar.parent-child.txt', help='Output file containing parent-child tuples.') 108 | parser.add_argument('--out_names', type=str, default='class_names.txt', help='Output file associating numerical class labels with their original names.') 109 | parser.add_argument('--plot', type=str, default=None, help='If given, a plot of the hierarchy will be written to the specified file. Requires the pydot package.') 110 | args = parser.parse_args() 111 | 112 | with open(args.meta_file, 'rb') as meta_pickle: 113 | meta = pickle.load(meta_pickle, encoding = 'bytes') 114 | 115 | hierarchy = read_hierarchy(args.hierarchy_file) 116 | if args.plot is not None: 117 | plot_hierarchy(hierarchy, args.plot) 118 | hierarchy, node_names = encode_class_names(hierarchy, [lbl.decode() for lbl in meta[b'fine_label_names']]) 119 | 120 | save_hierarchy(hierarchy, args.out) 121 | 122 | with open(args.out_names, 'w') as f: 123 | for ind, name in enumerate(node_names): 124 | f.write('{} {}\n'.format(ind, name)) 125 | -------------------------------------------------------------------------------- /Cifar-Hierarchy/graph_wordnet.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cvjena/semantic-embeddings/0d4177422bafbba685fb6a0f976675864f31e09f/Cifar-Hierarchy/graph_wordnet.pdf -------------------------------------------------------------------------------- /Cifar-Hierarchy/hierarchy.txt: -------------------------------------------------------------------------------- 1 | entity 2 | -- natural_scenes 3 | ---- mountain 4 | ---- plain 5 | ---- sea 6 | ---- cloud 7 | -- organism 8 | ---- living 9 | ------ animal 10 | -------- placental 11 | ---------- carnivore 12 | ------------ bear 13 | ------------ musteline_mammal 14 | -------------- otter 15 | -------------- skunk 16 | ------------ procyonid 17 | -------------- raccoon 18 | ------------ canine 19 | -------------- wolf 20 | -------------- fox 21 | ------------ feline 22 | -------------- leopard 23 | -------------- tiger 24 | -------------- lion 25 | ---------- rodent 26 | ------------ beaver 27 | ------------ squirrel 28 | ------------ hamster 29 | ------------ mouse 30 | ------------ porcupine 31 | ---------- lagomorph 32 | ------------ rabbit 33 | ---------- insectivore 34 | ------------ shrew 35 | ---------- pachyderm 36 | ------------ elephant 37 | ---------- ungulate 38 | ------------ camel 39 | ------------ cattle 40 | ---------- primate 41 | ------------ chimpanzee 42 | -------- metatherian 43 | ---------- marsupial 44 | ------------ possum 45 | ------------ kangaroo 46 | -------- aquatic_animal 47 | ---------- aquatic_mammal 48 | ------------ seal 49 | ------------ cetacean 50 | -------------- whale 51 | -------------- dolphin 52 | ---------- fish 53 | ------------ bony_fish 54 | -------------- soft-finned_fish 55 | ---------------- trout 56 | ---------------- aquarium_fish 57 | -------------- spiny-finned_fish 58 | ---------------- flatfish 59 | ------------ cartilaginous_fish 60 | -------------- shark 61 | -------------- ray 62 | -------- reptile 63 | ---------- anapsid 64 | ------------ turtle 65 | ---------- diapsid 66 | ------------ dinosaur 67 | ------------ snake 68 | ------------ crocodile 69 | ------------ lizard 70 | -------- invertebrate 71 | ---------- snail 72 | ---------- worm 73 | ---------- anthropod 74 | ------------ spider 75 | ------------ insect 76 | -------------- beetle 77 | -------------- bee 78 | -------------- cockroach 79 | -------------- lepidopterous 80 | ---------------- butterfly 81 | ---------------- caterpillar 82 | ------------ crustacean 83 | -------------- crab 84 | -------------- lobster 85 | ------ people 86 | -------- baby 87 | -------- child 88 | ---------- girl 89 | ---------- boy 90 | -------- adult 91 | ---------- woman 92 | ---------- man 93 | ---- vegetation 94 | ------ blooming 95 | -------- flower 96 | ---------- poppy 97 | ---------- sunflower 98 | ---------- orchid 99 | -------- tulip 100 | -------- rose 101 | ------ wooden 102 | -------- forest 103 | -------- tree 104 | ---------- palm_tree 105 | ---------- oak_tree 106 | ---------- maple_tree 107 | ---------- pine_tree 108 | ---------- willow_tree 109 | -- food 110 | ---- mushroom 111 | ---- vegetable 112 | ------ sweet_pepper 113 | ---- fruit 114 | ------ citrus 115 | -------- orange 116 | ------ pome 117 | -------- apple 118 | -------- pear 119 | -- artifact 120 | ---- way 121 | ------ road 122 | ---- structure 123 | ------ bridge 124 | ------ castle 125 | ------ building 126 | -------- house 127 | -------- skyscraper 128 | ---- furniture 129 | ------ bed 130 | ------ table 131 | ------ wardrobe 132 | ------ seat 133 | -------- chair 134 | -------- couch 135 | ---- device 136 | ------ lamp 137 | ------ clock 138 | ------ television 139 | ------ telephone 140 | ------ keyboard 141 | ---- tool 142 | ------ lawn_mower 143 | ---- container 144 | ------ can 145 | ------ cup 146 | ------ plate 147 | ------ vessel 148 | -------- bottle 149 | -------- bowl 150 | ---- vehicle 151 | ------ rocket 152 | ------ wheeled_vehicle 153 | -------- bicycle 154 | -------- military_vehicle 155 | ---------- tank 156 | -------- public_transport 157 | ---------- bus 158 | ---------- streetcar 159 | ---------- train 160 | -------- motor_vehicle 161 | ---------- motorcycle 162 | ---------- pickup_truck 163 | ---------- tractor 164 | -------------------------------------------------------------------------------- /CosineLoss.md: -------------------------------------------------------------------------------- 1 | # Deep Learning on Small Datasets without Pre-Training using Cosine Loss 2 | 3 | This document explains how the code in this repository can be used to produce the results reported in the following paper: 4 | 5 | > [**Deep Learning on Small Datasets without Pre-Training using Cosine Loss.**][1] 6 | > Björn Barz and Joachim Denzler. 7 | > IEEE Winter Conference on Applications of Computer Vision (WACV), 2020. 8 | 9 | 10 | ## 1. Results 11 | 12 | According to Table 2 in the paper: 13 | 14 | | Loss Function | CUB | NAB | Cars | Flowers | MIT 67 Scenes | CIFAR-100 | 15 | |---------------------------------|----------:|----------:|----------:|----------:|--------------:|----------:| 16 | | cross entropy | 51.9% | 59.4% | 78.2% | 67.3% | 44.3% | 77.0% | 17 | | cross entropy + label smoothing | 55.9% | 68.3% | 78.1% | 66.8% | 38.7% | **77.5%** | 18 | | cosine loss | 67.6% | 71.7% | 84.3% | **71.1%** | 51.5% | 75.3% | 19 | | cosine loss + cross entropy | **68.0%** | **71.9%** | **85.0%** | 70.6% | **52.7%** | 76.4% | 20 | 21 | 22 | ## 2. Requirements 23 | 24 | - Python >= 3.5 25 | - numpy 26 | - numexpr 27 | - keras >= 2.2.0 28 | - tensorflow (we used v1.8) 29 | - sklearn 30 | - scipy 31 | - pillow 32 | 33 | 34 | ## 3. Datasets 35 | 36 | The following datasets have been used in the paper: 37 | 38 | - [Caltech UCSD Birds-200-2011][4] (CUB) 39 | - [North American Birds][3] (NAB-large) 40 | - [Stanford Cars][5] (Cars) 41 | - [Oxford Flowers-102][6] (Flowers) 42 | - [MIT 67 Indoor Scenes][7] (MIT67Scenes) 43 | - [CIFAR-100][2] (CIFAR-100) 44 | 45 | The names in parentheses specify the dataset names that can be passed to the scripts mentioned below. 46 | 47 | 48 | ## 4. Training with different loss functions 49 | 50 | In the following exemplary python script calls, replace `$DS` with the name of the dataset (see above), 51 | `$DSROOT` with the path to that dataset, and `$LR` with the maximum learning rate for SGDR. 52 | 53 | To save the model after training has completed, add `--model_dump` followed by the filename where the model definition and weights should be written to. 54 | 55 | ### 4.1 Softmax + Cross Entropy 56 | 57 | ```shell 58 | python learn_classifier.py \ 59 | --dataset $DS --data_root $DSROOT --sgdr_max_lr $LR \ 60 | --architecture resnet-50 --batch_size 96 \ 61 | --gpus 4 --read_workers 16 --queue_size 32 --gpu_merge 62 | ``` 63 | 64 | For label smoothing, add `--label_smoothing 0.1`. 65 | 66 | ### 4.2 Cosine Loss 67 | 68 | ```shell 69 | python learn_image_embeddings.py \ 70 | --dataset $DS --data_root $DSROOT --sgdr_max_lr $LR \ 71 | --embedding onehot --architecture resnet-50 --batch_size 96 \ 72 | --gpus 4 --read_workers 16 --queue_size 32 --gpu_merge 73 | ``` 74 | 75 | For the combined cosine + cross-entropy loss, add `--cls_weight 0.1`. 76 | 77 | To use semantic embeddings instead of one-hot vectors, pass a path to one of the embedding files in the [`embeddings`](embeddings/) directory to `--embedding` instead of `onehot`. 78 | 79 | ### 4.3 CIFAR-100 80 | 81 | For the CIFAR-100 dataset, use the following parameters: 82 | 83 | ```shell 84 | python learn_classifier.py \ 85 | --dataset CIFAR-100 --data_root $DSROOT --sgdr_max_lr $LR \ 86 | --architecture resnet-110-wfc --batch_size 100 87 | 88 | python learn_image_embeddings.py \ 89 | --dataset CIFAR-100 --data_root $DSROOT --sgdr_max_lr $LR \ 90 | --embedding onehot --architecture resnet-110-wfc --batch_size 100 91 | ``` 92 | 93 | ### 4.4 Determining the best performance across different learning rates 94 | 95 | For each dataset and loss function, we fine-tuned the learning rate individually by wrapping the training script calls into a bash loop like the following (here shown for training with the cosine loss on CIFAR-100 as an example): 96 | 97 | ```shell 98 | for LR in 2.5 1.0 0.5 0.1 0.05 0.01 0.005 0.001; do 99 | echo $LR 100 | python learn_image_embeddings.py \ 101 | --dataset CIFAR-100 --data_root $DSROOT --sgdr_max_lr $LR \ 102 | --embedding onehot --architecture resnet-110-wfc --batch_size 100 \ 103 | 2>/dev/null | grep -oP "val_(prob_)?acc: \K([0-9.]+)" | sort -n | tail -n 1 104 | done 105 | ``` 106 | 107 | The following table lists the values for `--sgdr_max_lr` that led to the best results. 108 | 109 | | Loss | CUB | NAB | Cars | Flowers | MIT 67 Scenes | CIFAR-100 | 110 | |----------------------------------------|------:|------:|-----:|--------:|--------------:|----------:| 111 | | cross entropy | 0.05 | 0.05 | 1.0 | 1.0 | 0.05 | 0.1 | 112 | | cross entropy + label smoothing | 0.05 | 0.1 | 1.0 | 0.1 | 1.0 | 0.1 | 113 | | cosine loss (one-hot) | 0.5 | 0.5 | 1.0 | 0.5 | 2.5 | 0.05 | 114 | | cosine loss + cross entropy (one-hot) | 0.5 | 0.5 | 0.5 | 0.5 | 2.5 | 0.1 | 115 | 116 | 117 | ## 5. Sub-sampling CUB 118 | 119 | To experiment with differently sized variants of the CUB dataset, download the [modified image list files][8] and unzip the obtained archive into the root directory of your CUB dataset. 120 | For training, specify the dataset name as `CUB-subX`, where `X` is the number of samples per class. 121 | 122 | ![Performance comparison for differently sub-sampled variants of the CUB dataset](https://user-images.githubusercontent.com/7915048/51765373-d67bb600-20d7-11e9-85a9-ec6f28cef39b.png) 123 | 124 | 125 | 126 | [1]: https://arxiv.org/pdf/1901.09054 127 | [2]: https://www.cs.toronto.edu/~kriz/cifar.html 128 | [3]: http://dl.allaboutbirds.org/nabirds 129 | [4]: http://www.vision.caltech.edu/visipedia/CUB-200-2011.html 130 | [5]: https://ai.stanford.edu/~jkrause/cars/car_dataset.html 131 | [6]: http://www.robots.ox.ac.uk/~vgg/data/flowers/102/index.html 132 | [7]: http://web.mit.edu/torralba/www/indoor.html 133 | [8]: https://github.com/cvjena/semantic-embeddings/releases/download/v1.2.0/cub-subsampled-splits.zip 134 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Björn Barz 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /clr_callback.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from keras.callbacks import Callback 3 | from keras import backend as K 4 | 5 | 6 | class CyclicLR(Callback): 7 | """This callback implements a cyclical learning rate policy (CLR). 8 | The method cycles the learning rate between two boundaries with 9 | some constant frequency, as detailed in this paper (https://arxiv.org/abs/1506.01186). 10 | The amplitude of the cycle can be scaled on a per-iteration or 11 | per-cycle basis. 12 | This class has three built-in policies, as put forth in the paper. 13 | "triangular": 14 | A basic triangular cycle w/ no amplitude scaling. 15 | "triangular2": 16 | A basic triangular cycle that scales initial amplitude by half each cycle. 17 | "exp_range": 18 | A cycle that scales initial amplitude by gamma**(cycle iterations) at each 19 | cycle iteration. 20 | For more detail, please see paper. 21 | 22 | # Example 23 | ```python 24 | clr = CyclicLR(base_lr=0.001, max_lr=0.006, 25 | step_size=2000., mode='triangular') 26 | model.fit(X_train, Y_train, callbacks=[clr]) 27 | ``` 28 | 29 | Class also supports custom scaling functions: 30 | ```python 31 | clr_fn = lambda x: 0.5*(1+np.sin(x*np.pi/2.)) 32 | clr = CyclicLR(base_lr=0.001, max_lr=0.006, 33 | step_size=2000., scale_fn=clr_fn, 34 | scale_mode='cycle') 35 | model.fit(X_train, Y_train, callbacks=[clr]) 36 | ``` 37 | # Arguments 38 | base_lr: initial learning rate which is the 39 | lower boundary in the cycle. 40 | max_lr: upper boundary in the cycle. Functionally, 41 | it defines the cycle amplitude (max_lr - base_lr). 42 | The lr at any cycle is the sum of base_lr 43 | and some scaling of the amplitude; therefore 44 | max_lr may not actually be reached depending on 45 | scaling function. 46 | step_size: number of training iterations per 47 | half cycle. Authors suggest setting step_size 48 | 2-8 x training iterations in epoch. 49 | mode: one of {triangular, triangular2, exp_range}. 50 | Default 'triangular'. 51 | Values correspond to policies detailed above. 52 | If scale_fn is not None, this argument is ignored. 53 | gamma: constant in 'exp_range' scaling function: 54 | gamma**(cycle iterations) 55 | scale_fn: Custom scaling policy defined by a single 56 | argument lambda function, where 57 | 0 <= scale_fn(x) <= 1 for all x >= 0. 58 | mode paramater is ignored 59 | scale_mode: {'cycle', 'iterations'}. 60 | Defines whether scale_fn is evaluated on 61 | cycle number or cycle iterations (training 62 | iterations since start of cycle). Default is 'cycle'. 63 | """ 64 | 65 | def __init__(self, base_lr=0.001, max_lr=0.006, step_size=2000., mode='triangular', 66 | gamma=1., scale_fn=None, scale_mode='cycle'): 67 | super(CyclicLR, self).__init__() 68 | 69 | self.base_lr = base_lr 70 | self.max_lr = max_lr 71 | self.step_size = step_size 72 | self.mode = mode 73 | self.gamma = gamma 74 | if scale_fn == None: 75 | if self.mode == 'triangular': 76 | self.scale_fn = lambda x: 1. 77 | self.scale_mode = 'cycle' 78 | elif self.mode == 'triangular2': 79 | self.scale_fn = lambda x: 1/(2.**(x-1)) 80 | self.scale_mode = 'cycle' 81 | elif self.mode == 'exp_range': 82 | self.scale_fn = lambda x: gamma**(x) 83 | self.scale_mode = 'iterations' 84 | else: 85 | self.scale_fn = scale_fn 86 | self.scale_mode = scale_mode 87 | self.clr_iterations = 0. 88 | self.trn_iterations = 0. 89 | self.history = {} 90 | 91 | self._reset() 92 | 93 | def _reset(self, new_base_lr=None, new_max_lr=None, 94 | new_step_size=None): 95 | """Resets cycle iterations. 96 | Optional boundary/step size adjustment. 97 | """ 98 | if new_base_lr != None: 99 | self.base_lr = new_base_lr 100 | if new_max_lr != None: 101 | self.max_lr = new_max_lr 102 | if new_step_size != None: 103 | self.step_size = new_step_size 104 | self.clr_iterations = 0. 105 | 106 | def clr(self): 107 | cycle = np.floor(1+self.clr_iterations/(2*self.step_size)) 108 | x = np.abs(self.clr_iterations/self.step_size - 2*cycle + 1) 109 | if self.scale_mode == 'cycle': 110 | return self.base_lr + (self.max_lr-self.base_lr)*np.maximum(0, (1-x))*self.scale_fn(cycle) 111 | else: 112 | return self.base_lr + (self.max_lr-self.base_lr)*np.maximum(0, (1-x))*self.scale_fn(self.clr_iterations) 113 | 114 | def on_train_begin(self, logs={}): 115 | logs = logs or {} 116 | 117 | if self.clr_iterations == 0: 118 | K.set_value(self.model.optimizer.lr, self.base_lr) 119 | else: 120 | K.set_value(self.model.optimizer.lr, self.clr()) 121 | 122 | def on_batch_end(self, epoch, logs=None): 123 | 124 | logs = logs or {} 125 | self.trn_iterations += 1 126 | self.clr_iterations += 1 127 | K.set_value(self.model.optimizer.lr, self.clr()) 128 | 129 | self.history.setdefault('lr', []).append(K.get_value(self.model.optimizer.lr)) 130 | self.history.setdefault('iterations', []).append(self.trn_iterations) 131 | 132 | for k, v in logs.items(): 133 | self.history.setdefault(k, []).append(v) 134 | 135 | 136 | 137 | 138 | -------------------------------------------------------------------------------- /datasets/__init__.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | 4 | CAFFE_MEAN = [123.68, 116.779, 103.939] 5 | CAFFE_STD = [1., 1., 1.] 6 | 7 | IMAGENET_MEAN = [122.65435242, 116.6545058, 103.99789959] 8 | IMAGENET_STD = [71.40583196, 69.56888997, 73.0440314] 9 | 10 | 11 | from .cifar import CifarGenerator 12 | from .ilsvrc import ILSVRCGenerator 13 | from .nab import NABGenerator 14 | from .cars import CarsGenerator 15 | from .flowers import FlowersGenerator 16 | from .inat import INatGenerator 17 | from .subdirectory import SubDirectoryGenerator 18 | 19 | 20 | 21 | def get_data_generator(dataset, data_root, classes = None): 22 | """ Shortcut for creating a data generator with default settings. 23 | 24 | # Arguments: 25 | 26 | - dataset: The name of the dataset. Possible values are: 27 | 28 | - "cifar-10" 29 | - "cifar-100" 30 | - "cifar-100-a" (first 50 classes of cifar-100) 31 | - "cifar-100-b" (last 50 classes of cifar-100) 32 | - "ilsvrc" 33 | - "nab" 34 | - "nab-large" 35 | - "cub" 36 | - "cars" 37 | - "flowers" 38 | - "mit67scenes" 39 | - "inat" / "inat2018" (optionally followed by an underscore and the name of a super-category) 40 | - "inat2019" 41 | - "UCMLU" 42 | - "RESISC45" 43 | 44 | To all dataset names except CIFAR, you may append one of the following suffixes: 45 | 46 | - "-ilsvrcmean": use ImageNet statistics for pre-processing 47 | - "-caffe": Caffe-style pre-processing (BGR instead of RGB, ImageNet mean, no standard deviation) 48 | 49 | For NAB and iNaturalist, the suffix "-large" may be appended to set the default image size to 512 pixels 50 | and the crop size to 448x448. 51 | 52 | - data_root: Root directory of the dataset. 53 | 54 | - classes: Optionally, a list of classes to be included. If not given, all available classes will be used. 55 | 56 | # Returns: 57 | a data generator object 58 | """ 59 | 60 | dataset = dataset.lower() 61 | 62 | if dataset.startswith('inat2018'): 63 | dataset = 'inat' + dataset[8:] 64 | 65 | kwargs = {} 66 | if dataset.endswith('-ilsvrcmean'): 67 | kwargs['mean'] = IMAGENET_MEAN 68 | kwargs['std'] = IMAGENET_STD 69 | dataset = dataset[:-11] 70 | elif dataset.endswith('-caffe'): 71 | kwargs['mean'] = CAFFE_MEAN 72 | kwargs['std'] = CAFFE_STD 73 | kwargs['color_mode'] = 'bgr' 74 | dataset = dataset[:-6] 75 | if dataset.endswith('-large'): 76 | kwargs['cropsize'] = (448, 448) 77 | kwargs['default_target_size'] = 512 78 | dataset = dataset[:-6] 79 | 80 | if dataset == 'cifar-10': 81 | 82 | return CifarGenerator(data_root, classes, reenumerate = True, cifar10 = True, 83 | train_generator_kwargs = { 'horizontal_flip' : True, 'width_shift_range' : 0.15, 'height_shift_range' : 0.15, 'zoom_range' : 0.25 }) 84 | 85 | elif dataset == 'cifar-100': 86 | 87 | return CifarGenerator(data_root, classes, reenumerate = True) 88 | 89 | elif dataset.startswith('cifar-100-a'): 90 | 91 | return CifarGenerator(data_root, np.arange(50), reenumerate = dataset.endswith('-consec')) 92 | 93 | elif dataset.startswith('cifar-100-b'): 94 | 95 | return CifarGenerator(data_root, np.arange(50, 100), reenumerate = dataset.endswith('-consec')) 96 | 97 | elif dataset == 'ilsvrc': 98 | 99 | return ILSVRCGenerator(data_root, classes, **kwargs) 100 | 101 | elif dataset == 'nab': 102 | 103 | if ('default_target_size' not in kwargs) and ('randzoom_range' not in kwargs): 104 | kwargs['randzoom_range'] = (256, 480) 105 | return NABGenerator(data_root, classes, 'images', **kwargs) 106 | 107 | elif (dataset == 'cub') or dataset.startswith('cub-sub'): 108 | 109 | if 'mean' not in kwargs: 110 | kwargs['mean'] = [123.82988033, 127.35116805, 110.25606303] 111 | if 'std' not in kwargs: 112 | kwargs['std'] = [59.2230949, 58.0736071, 67.80251684] 113 | if dataset.startswith('cub-sub'): 114 | samples_per_class = int(dataset[7:]) 115 | kwargs['split_file'] = 'train_test_split_{}.txt'.format(samples_per_class) 116 | kwargs['train_repeats'] = 30 // samples_per_class 117 | return NABGenerator(data_root, classes, 'images', cropsize = (448, 448), default_target_size = 512, randzoom_range = None, **kwargs) 118 | 119 | elif dataset == 'cars': 120 | 121 | return CarsGenerator(data_root, classes, **kwargs) 122 | 123 | elif dataset == 'flowers': 124 | 125 | return FlowersGenerator(data_root, classes, **kwargs) 126 | 127 | elif (dataset == 'inat') or dataset.startswith('inat_'): 128 | 129 | supercategory = dataset[5:] if dataset.startswith('inat_') else None 130 | if ('default_target_size' not in kwargs) and ('randzoom_range' not in kwargs): 131 | kwargs['randzoom_range'] = (256, 480) 132 | return INatGenerator(data_root, supercategory=supercategory, **kwargs) 133 | 134 | elif dataset == 'inat2019': 135 | 136 | if ('mean' not in kwargs) and ('std' not in kwargs): 137 | kwargs['mean'] = [115.77492586, 120.84414891, 93.51744386] 138 | kwargs['std'] = [60.46127213, 58.63136496, 63.5872299] 139 | if ('default_target_size' not in kwargs) and ('randzoom_range' not in kwargs): 140 | kwargs['randzoom_range'] = (256, 480) 141 | return INatGenerator(data_root, 'train2019.json', 'val2019.json', **kwargs) 142 | 143 | elif dataset == 'mit67scenes': 144 | 145 | if ('mean' not in kwargs) and ('std' not in kwargs): 146 | kwargs['mean'] = [124.62788179, 110.01028625, 94.95780545] 147 | kwargs['std'] = [68.56923599, 66.86607736, 67.35944349] 148 | return SubDirectoryGenerator(data_root, classes, img_dir='Images', train_list='TrainImages.txt', test_list='TestImages.txt', **kwargs) 149 | 150 | elif dataset == 'ucmlu': 151 | 152 | if ('mean' not in kwargs) and ('std' not in kwargs): 153 | kwargs['mean'] = [122.65409223, 124.40230701, 114.25659171] 154 | kwargs['std'] = [55.74499679, 51.65585669, 50.16527551] 155 | return SubDirectoryGenerator(data_root, classes, **kwargs) 156 | 157 | elif dataset == 'resisc45': 158 | 159 | if ('mean' not in kwargs) and ('std' not in kwargs): 160 | kwargs['mean'] = [94.17769482, 97.40967803, 87.80359702] 161 | kwargs['std'] = [51.92246172, 47.22081475, 47.07685676] 162 | return SubDirectoryGenerator(data_root, classes, **kwargs) 163 | 164 | else: 165 | 166 | raise ValueError('Unknown dataset: {}'.format(dataset)) 167 | -------------------------------------------------------------------------------- /datasets/cars.py: -------------------------------------------------------------------------------- 1 | import os 2 | import scipy.io 3 | 4 | from .common import FileDatasetGenerator 5 | 6 | 7 | 8 | class CarsGenerator(FileDatasetGenerator): 9 | 10 | def __init__(self, root_dir, classes = None, annotation_file = 'cars_annos.mat', 11 | cropsize = (448, 448), default_target_size = 512, randzoom_range = None, distort_colors = False, 12 | randerase_prob = 0.5, randerase_params = { 'sl' : 0.02, 'sh' : 0.3, 'r1' : 0.3, 'r2' : 1./0.3 }, 13 | mean = [120.03730636, 117.33780928, 116.0130335], std = [75.40415763, 75.15394251, 77.28286728], color_mode = "rgb"): 14 | """ Stanford-Cars data generator. 15 | 16 | The dataset can be obtained here: 17 | https://ai.stanford.edu/~jkrause/cars/car_dataset.html 18 | 19 | This data generator was designed to work with the merged training+test version of the dataset 20 | (because labels are not available for the stand-alone test data). 21 | 22 | 23 | # Arguments: 24 | 25 | - root_dir: Root directory of the Stanford-Cars dataset, containing the image directory and the annotations file. 26 | 27 | - classes: List of classes to restrict the dataset to. New numeric labels will be assigned to these classes in ascending order. 28 | If set to `None`, all available classes will be used and enumerated in ascending order. 29 | Note that the classes in Stanford-Cars are enumerated beginning with 1, while we will begin with 0. 30 | 31 | - annotation_file: Name of a MATLAB file (relative to `root_dir`) that contains a structured array called `annotations`, which has 32 | at least the following attributes: 33 | - 'relative_im_path': paths of the images in the dataset, relative to `root_dir` (not to the location of the annotations file!). 34 | - 'class': class labels for all images, 35 | - 'test': indicators whether each image belongs to the training (0) or the test set (1). 36 | 37 | - cropsize: Tuple with width and height of crops extracted from the images. 38 | 39 | - default_target_size: Int or tuple of ints. Specifies the default target size which images will be resized to (before cropping) 40 | if not specified differently in calls to `flow_train/test` or `train/test_sequence`. 41 | If a single int is given, it specifies the size of the smaller side of the image and the aspect ratio will be retained. 42 | If set to -1, the image won't be resized. 43 | 44 | - randzoom_range: Tuple with minimum and maximum size of the smaller image dimension for random scale augmentation. 45 | May either be given as integer specifying absolute pixel values or float specifying the relative scale of the image. 46 | If set to `None`, no scale augmentation will be performed. 47 | 48 | - distort_colors: Boolean specifying whether to apply color distortions as data augmentation. 49 | 50 | - randerase_prob: Probability for random erasing. 51 | 52 | - randerase_params: Random erasing parameters (see Zhong et al. (2017): "Random erasing data augmentation."). 53 | 54 | - mean: Channel-wise image mean for normalization (in "RGB" order). If set to `None`, mean and standard deviation will be computed from the images. 55 | 56 | - std: Channel-wise standard deviation for normalization (in "RGB" order). If set to `None`, standard deviation will be computed from the images. 57 | 58 | - color_mode: Image color mode, either "rgb" or "bgr". 59 | """ 60 | 61 | super(CarsGenerator, self).__init__(root_dir, cropsize = cropsize, default_target_size = default_target_size, randzoom_range = randzoom_range, 62 | distort_colors = distort_colors, randerase_prob = randerase_prob, randerase_params = randerase_params, color_mode = color_mode) 63 | 64 | # Read annotations 65 | self.annotation_file = annotation_file if os.path.isabs(annotation_file) else os.path.join(self.root_dir, annotation_file) 66 | self._annotations = scipy.io.loadmat(self.annotation_file, squeeze_me=True)['annotations'] 67 | 68 | # Determine set of classes 69 | self.classes = classes if classes is not None else sorted(set(self._annotations['class'])) 70 | self.class_indices = dict(zip(self.classes, range(len(self.classes)))) 71 | 72 | # Read image information 73 | for sample in self._annotations: 74 | if sample['class'] in self.class_indices: 75 | fn = sample['relative_im_path'] if os.path.isabs(sample['relative_im_path']) else os.path.join(self.root_dir, sample['relative_im_path']) 76 | if sample['test']: 77 | self.test_img_files.append(fn) 78 | self._test_labels.append(self.class_indices[sample['class']]) 79 | else: 80 | self.train_img_files.append(fn) 81 | self._train_labels.append(self.class_indices[sample['class']]) 82 | 83 | print('Found {} training and {} validation images from {} classes.'.format(self.num_train, self.num_test, self.num_classes)) 84 | 85 | # Compute mean and standard deviation 86 | self._compute_stats(mean, std) -------------------------------------------------------------------------------- /datasets/cifar.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import pickle 3 | import os 4 | 5 | from .common import TinyDatasetGenerator 6 | 7 | 8 | 9 | class CifarGenerator(TinyDatasetGenerator): 10 | """ Data generator for CIFAR-10 and CIFAR-100. """ 11 | 12 | def __init__(self, root_dir, classes = None, reenumerate = False, cifar10 = False, **kwargs): 13 | """ Data generator for CIFAR-10 and CIFAR-100. 14 | 15 | # Arguments: 16 | 17 | - root_dir: Root directory of the dataset. 18 | 19 | - classes: List of classes to restrict the dataset to. 20 | If set to `None`, all available classes will be used. 21 | 22 | - reenumerate: If true, the classes given in `classes` will be re-enumerated in ascending order, beginning from 0. 23 | 24 | - cifar10: Set this to True for CIFAR-10 and to False for CIFAR-100. 25 | 26 | Further keyword arguments such as `generator_kwargs` and `train_generator_kwargs` will be 27 | forwarded to the constructor of `TinyDatasetGenerator`. 28 | """ 29 | 30 | self.root_dir = root_dir 31 | 32 | # Load dataset 33 | if cifar10: 34 | X_train, y_train = [], [] 35 | for i in range(1, 6): 36 | with open(os.path.join(self.root_dir, 'data_batch_{}'.format(i)), 'rb') as pf: 37 | dump = pickle.load(pf, encoding='bytes') 38 | X_train.append(dump[b'data' if b'data' in dump else 'data'].astype(np.float32)) 39 | y_train += dump[b'labels' if b'labels' in dump else 'labels'] 40 | del dump 41 | X_train = np.concatenate(X_train) 42 | else: 43 | with open(os.path.join(self.root_dir, 'train'), 'rb') as pf: 44 | dump = pickle.load(pf, encoding='bytes') 45 | X_train = dump[b'data' if b'data' in dump else 'data'].astype(np.float32) 46 | y_train = dump[b'fine_labels' if b'fine_labels' in dump else 'fine_labels'] 47 | del dump 48 | 49 | with open(os.path.join(self.root_dir, 'test_batch' if cifar10 else 'test'), 'rb') as pf: 50 | dump = pickle.load(pf, encoding='bytes') 51 | X_test = dump[b'data' if b'data' in dump else 'data'].astype(np.float32) 52 | if cifar10: 53 | y_test = dump[b'labels' if b'labels' in dump else 'labels'] 54 | else: 55 | y_test = dump[b'fine_labels' if b'fine_labels' in dump else 'fine_labels'] 56 | del dump 57 | 58 | # Restrict labels to the given classes and re-enumerate them 59 | if classes is not None: 60 | 61 | sel_train = np.array([lbl in classes for lbl in y_train]) 62 | sel_test = np.array([lbl in classes for lbl in y_test]) 63 | X_train = X_train[sel_train] 64 | y_train = [lbl for lbl, sel in zip(y_train, sel_train) if sel] 65 | X_test = X_test[sel_test] 66 | y_test = [lbl for lbl, sel in zip(y_test, sel_test) if sel] 67 | 68 | self.classes = classes 69 | if reenumerate: 70 | self.class_indices = dict(zip(self.classes, range(len(self.classes)))) 71 | y_train = [self.class_indices[lbl] for lbl in y_train] 72 | y_test = [self.class_indices[lbl] for lbl in y_test] 73 | 74 | else: 75 | 76 | self.classes = np.arange(max(y_train) + 1) 77 | self.class_indices = dict(zip(self.classes, self.classes)) 78 | 79 | # Reshape data to images 80 | X_train = X_train.reshape(-1, 3, 32, 32).transpose((0, 2, 3, 1)) 81 | X_test = X_test.reshape(-1, 3, 32, 32).transpose((0, 2, 3, 1)) 82 | 83 | # Call parent constructor 84 | super(CifarGenerator, self).__init__(X_train, X_test, y_train, y_test, **kwargs) 85 | -------------------------------------------------------------------------------- /datasets/flowers.py: -------------------------------------------------------------------------------- 1 | import os 2 | import scipy.io 3 | 4 | from .common import FileDatasetGenerator 5 | 6 | 7 | 8 | class FlowersGenerator(FileDatasetGenerator): 9 | 10 | def __init__(self, root_dir, classes = None, img_dir = 'jpg', label_file = 'imagelabels.mat', split_file = 'setid.mat', 11 | train_splits = ['trnid', 'valid'], test_splits = ['tstid'], 12 | cropsize = (448, 448), default_target_size = 512, randzoom_range = None, distort_colors = False, 13 | randerase_prob = 0.5, randerase_params = { 'sl' : 0.02, 'sh' : 0.3, 'r1' : 0.3, 'r2' : 1./0.3 }, 14 | mean = [110.7799141, 97.65648664, 75.32889973], std = [74.90387818, 62.70218863, 69.7656359], color_mode = "rgb"): 15 | """ Flowers-102 data generator. 16 | 17 | The dataset can be obtained here: 18 | http://www.robots.ox.ac.uk/~vgg/data/flowers/ 19 | 20 | 21 | # Arguments: 22 | 23 | - root_dir: Root directory of the Oxford Flowers-102 dataset, containing the image directory and the annotation files. 24 | 25 | - classes: List of classes to restrict the dataset to. New numeric labels will be assigned to these classes in ascending order. 26 | If set to `None`, all available classes will be used and enumerated in ascending order. 27 | Note that the classes in Flowers-102 are enumerated beginning with 1, while we will begin with 0. 28 | 29 | - img_dir: Name of the sub-directory of `root_dir` that contains the images, named like 'image_#####.jpg', where '#####' is the 30 | 5-digit ID of the image. 31 | 32 | - label_file: Name of a MATLAB file (relative to `root_dir`) that contains an array called 'labels' with class labels for each image. 33 | 34 | - split_file: Name of a MATLAB file (relative to `root_dir`) that containing named arrays of image IDs (counting from 1) defining a 35 | split of the dataset. 36 | 37 | - train_splits: List with the names of the arrays in `split_file` which should be concatenated to obtain the list of training image IDs. 38 | 39 | - test_splits: List with the names of the arrays in `split_file` which should be concatenated to obtain the list of test image IDs. 40 | 41 | - cropsize: Tuple with width and height of crops extracted from the images. 42 | 43 | - default_target_size: Int or tuple of ints. Specifies the default target size which images will be resized to (before cropping) 44 | if not specified differently in calls to `flow_train/test` or `train/test_sequence`. 45 | If a single int is given, it specifies the size of the smaller side of the image and the aspect ratio will be retained. 46 | If set to -1, the image won't be resized. 47 | 48 | - randzoom_range: Tuple with minimum and maximum size of the smaller image dimension for random scale augmentation. 49 | May either be given as integer specifying absolute pixel values or float specifying the relative scale of the image. 50 | If set to `None`, no scale augmentation will be performed. 51 | 52 | - distort_colors: Boolean specifying whether to apply color distortions as data augmentation. 53 | 54 | - randerase_prob: Probability for random erasing. 55 | 56 | - randerase_params: Random erasing parameters (see Zhong et al. (2017): "Random erasing data augmentation."). 57 | 58 | - mean: Channel-wise image mean for normalization (in "RGB" order). If set to `None`, mean and standard deviation will be computed from the images. 59 | 60 | - std: Channel-wise standard deviation for normalization (in "RGB" order). If set to `None`, standard deviation will be computed from the images. 61 | 62 | - color_mode: Image color mode, either "rgb" or "bgr". 63 | """ 64 | 65 | super(FlowersGenerator, self).__init__(root_dir, cropsize = cropsize, default_target_size = default_target_size, randzoom_range = randzoom_range, 66 | distort_colors=distort_colors, colordistort_params={ 'hue_delta' : 0.0, 'saturation_range' : (0.8, 1.2) }, 67 | randerase_prob = randerase_prob, randerase_params = randerase_params, color_mode = color_mode) 68 | self.img_dir = img_dir if os.path.isabs(img_dir) else os.path.join(self.root_dir, img_dir) 69 | self.label_file = label_file if os.path.isabs(label_file) else os.path.join(self.root_dir, label_file) 70 | self.split_file = split_file if os.path.isabs(split_file) else os.path.join(self.root_dir, split_file) 71 | 72 | # Read annotations 73 | img_labels = scipy.io.loadmat(self.label_file, squeeze_me=True)['labels'] 74 | splits = scipy.io.loadmat(self.split_file, squeeze_me=True) 75 | 76 | # Determine set of classes 77 | self.classes = classes if classes is not None else sorted(set(img_labels)) 78 | self.class_indices = dict(zip(self.classes, range(len(self.classes)))) 79 | 80 | # Compose image lists 81 | for split_name in train_splits: 82 | for i in splits[split_name]: 83 | self.train_img_files.append(os.path.join(self.img_dir, 'image_{:05d}.jpg'.format(i))) 84 | self._train_labels.append(self.class_indices[img_labels[i-1]]) 85 | for split_name in test_splits: 86 | for i in splits[split_name]: 87 | self.test_img_files.append(os.path.join(self.img_dir, 'image_{:05d}.jpg'.format(i))) 88 | self._test_labels.append(self.class_indices[img_labels[i-1]]) 89 | print('Found {} training and {} validation images from {} classes.'.format(self.num_train, self.num_test, self.num_classes)) 90 | 91 | # Compute mean and standard deviation 92 | self._compute_stats(mean, std) -------------------------------------------------------------------------------- /datasets/ilsvrc.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | try: 4 | from keras.preprocessing.image import list_pictures 5 | except ImportError: 6 | import keras 7 | from keras_preprocessing.image import list_pictures 8 | 9 | from . import IMAGENET_MEAN, IMAGENET_STD 10 | from .common import FileDatasetGenerator 11 | 12 | 13 | 14 | class ILSVRCGenerator(FileDatasetGenerator): 15 | 16 | def __init__(self, root_dir, classes = None, mean = IMAGENET_MEAN, std = IMAGENET_STD, color_mode = "rgb"): 17 | """ ILSVRC data generator. 18 | 19 | # Arguments: 20 | 21 | - root_dir: Root directory of the ILSVRC dataset, containing directories "ILSVRC2012_img_train" and "ILSVRC2012_img_val", both containing 22 | sub-directories with names of synsets and the images for each synset in the corresponding sub-directories. 23 | 24 | - classes: List of synsets to restrict the dataset to. Numeric labels will be assigned to these synsets in ascending order. 25 | If set to `None`, all available synsets will be used and enumerated in the lexicographical order. 26 | 27 | - mean: Channel-wise image mean for normalization (in "RGB" order). If set to `None`, mean and standard deviation will be computed from the images. 28 | 29 | - std: Channel-wise standard deviation for normalization (in "RGB" order). If set to `None`, standard deviation will be computed from the images. 30 | 31 | - color_mode: Image color mode, either "rgb" or "bgr". 32 | """ 33 | 34 | super(ILSVRCGenerator, self).__init__(root_dir, default_target_size = 256, randzoom_range = (256, 480), color_mode = color_mode) 35 | self.train_dir = os.path.join(self.root_dir, 'ILSVRC2012_img_train') 36 | self.test_dir = os.path.join(self.root_dir, 'ILSVRC2012_img_val') 37 | 38 | # Search for classes 39 | if classes is None: 40 | classes = [] 41 | for subdir in sorted(os.listdir(self.train_dir)): 42 | if os.path.isdir(os.path.join(self.train_dir, subdir)): 43 | classes.append(subdir) 44 | self.classes = classes 45 | self.class_indices = dict(zip(self.classes, range(len(self.classes)))) 46 | 47 | # Search for images 48 | for lbl, subdir in enumerate(self.classes): 49 | cls_files = sorted(list_pictures(os.path.join(self.train_dir, subdir), 'jpeg')) 50 | self.train_img_files += cls_files 51 | self._train_labels += [lbl] * len(cls_files) 52 | cls_files = sorted(list_pictures(os.path.join(self.test_dir, subdir), 'jpeg')) 53 | self.test_img_files += cls_files 54 | self._test_labels += [lbl] * len(cls_files) 55 | print('Found {} training and {} validation images from {} classes.'.format(self.num_train, self.num_test, self.num_classes)) 56 | 57 | # Compute mean and standard deviation 58 | self._compute_stats(mean, std) 59 | -------------------------------------------------------------------------------- /datasets/inat.py: -------------------------------------------------------------------------------- 1 | import json 2 | import os 3 | 4 | from .common import FileDatasetGenerator 5 | 6 | 7 | # Pre-computed mean and standard deviation for all super-categories 8 | SUPERCATEGORY_STATS = { 9 | None : ([119.99310088, 122.86333725, 102.38318464], [60.83471124, 59.33123704, 65.92057842]), 10 | 'actinopterygii' : ([95.60659929, 109.21340134, 99.53273934], [62.64981594, 56.77583425, 57.79043402]), 11 | 'amphibia' : ([120.38820316, 112.09448704, 93.57291079], [64.38971069, 60.88945117, 60.689195]), 12 | 'animalia' : ([117.86148813, 112.27558493, 100.76823038], [65.10786879, 60.9941875, 61.3212783]), 13 | 'arachnida' : ([123.05328454, 123.11786486, 99.49669769], [62.10607939, 59.69295922, 64.12102046]), 14 | 'aves' : ([125.68554284, 131.58931007, 123.51576605], [56.91926625, 57.04151665, 67.97284604]), 15 | 'bacteria' : ([130.44253929, 118.58949652, 100.64353881], [63.52655078, 61.3866035, 62.52496727]), 16 | 'chromista' : ([126.63609004, 120.30744082, 103.69842308], [61.3142875, 60.35121831, 64.33445667]), 17 | 'fungi' : ([105.4904181, 98.20844854, 81.95195412], [66.43803547, 63.26916273, 61.75505097]), 18 | 'insecta' : ([126.79141945, 126.55725101, 94.4626541], [62.46710552, 59.70656548, 64.38703598]), 19 | 'mammalia' : ([119.32537707, 119.28610021, 105.22655576], [60.25561291, 58.86410094, 60.85549787]), 20 | 'mollusca' : ([119.15865454, 107.82338741, 93.65438902], [65.54171188, 62.00986655, 62.64830566]), 21 | 'plantae' : ([109.4558912, 115.78290918, 84.83970548], [60.36177593, 59.17162815, 60.81183456]), 22 | 'protozoa' : ([99.4855571, 90.12976005, 71.67906874], [69.23439903, 63.83415135, 59.1059619]), 23 | 'reptilia' : ([126.42469824, 119.44987437, 103.84680809], [63.4749642, 60.19704406, 60.20556052]), 24 | } 25 | 26 | 27 | class INatGenerator(FileDatasetGenerator): 28 | 29 | def __init__(self, root_dir, train_file='train2018.json', val_file='val2018.json', supercategory=None, 30 | cropsize = (224, 224), default_target_size = 256, 31 | mean=None, std=None, 32 | *args, **kwargs): 33 | """ Data generator for iNaturalist. 34 | 35 | The data can be obtained here: 36 | https://github.com/visipedia/inat_comp/tree/2018 37 | 38 | # Arguments: 39 | 40 | - root_dir: Root directory of the iNaturalist 2018 dataset, containing the files `train2018.json` and `val2018.json`. 41 | 42 | - train_file: Name of the JSON file containing training image metadata (relative to `root_dir`). 43 | 44 | - val_file: Name of the JSON file containing validation image metadata (relative to `root_dir`). 45 | 46 | - supercategory: Can be used to restrict the dataset to classes from a given super-category (for iNaturalist 2018 only). 47 | Available super-categories are: 48 | 'actinopterygii', 'amphibia', 'animalia', 'arachnida', 'aves', 'bacteria', 'chromista', 'fungi', 'insecta', 49 | 'mammalia', 'mollusca', 'plantae', 'protozoa', 'reptilia'. 50 | 51 | - cropsize: Tuple with width and height of crops extracted from the images. 52 | 53 | - default_target_size: Int or tuple of ints. Specifies the default target size which images will be resized to (before cropping) 54 | if not specified differently in calls to `flow_train/test` or `train/test_sequence`. 55 | If a single int is given, it specifies the size of the smaller side of the image and the aspect ratio will be retained. 56 | If set to -1, the image won't be resized. 57 | 58 | - mean: Channel-wise image mean for normalization (in "RGB" order). If set to `None`, mean and standard deviation will be computed from the images. 59 | 60 | - std: Channel-wise standard deviation for normalization (in "RGB" order). If set to `None`, standard deviation will be computed from the images. 61 | 62 | Remaining arguments will be passed through to the constructor of `FileDatasetGenerator`. 63 | """ 64 | 65 | super(INatGenerator, self).__init__(root_dir, cropsize=cropsize, default_target_size=default_target_size, *args, **kwargs) 66 | 67 | train_file = train_file if os.path.isabs(train_file) else os.path.join(root_dir, train_file) 68 | test_file = val_file if os.path.isabs(val_file) else os.path.join(root_dir, val_file) 69 | 70 | self.train_tuples, class_count, class_mapping = self.get_tuples_for_supercategory( 71 | train_file, 72 | root_dir, 73 | supercategory=supercategory 74 | ) 75 | self.test_tuples, class_count, _ = self.get_tuples_for_supercategory( 76 | test_file, 77 | root_dir, 78 | supercategory=supercategory 79 | ) 80 | 81 | self._train_labels, self.train_img_files = zip(*self.train_tuples) 82 | self._test_labels, self.test_img_files = zip(*self.test_tuples) 83 | 84 | # Set classes 85 | self.classes = [c for c, idx in sorted(class_mapping.items(), key=lambda t: t[1])] 86 | self.class_indices = class_mapping 87 | 88 | print('Found {} training and {} validation images from {} classes.'.format(len(self.train_tuples), len(self.test_tuples), class_count)) 89 | 90 | # Compute mean and standard deviation 91 | if (mean is None) and (std is None) and (supercategory in SUPERCATEGORY_STATS): 92 | mean, std = SUPERCATEGORY_STATS[supercategory] 93 | self._compute_stats(mean, std) 94 | 95 | 96 | def get_tuples_for_supercategory(self, fname, image_folder, supercategory=None): 97 | """ 98 | Collects the names of the images defined in the provided dataset file and their corresponding class and returns 99 | them in a list of tuples. 100 | 101 | :param fname: The path to the dataset file. 102 | :param image_folder: The folder containing the dataset and images in subfolders. 103 | :param supercategory: The name of the supercategory to use. Possible values are { Chromista, Insecta, Mammalia, 104 | Arachnida, Aves, Plantae, Fungi, Bacteria, Animalia, Reptilia, Mollusca, Actinopterygii, Protozoa, Amphibia }. 105 | :return:A list of tuples for each image like [(, ), ...]. 106 | """ 107 | 108 | if supercategory is not None: 109 | supercategory = supercategory.lower() 110 | 111 | with open(fname, "r") as f: 112 | data = json.loads(f.read()) 113 | 114 | id_to_image = { image["id"]: image for image in data["images"] } 115 | id_to_category = { category["id"]: category for category in data["categories"] if (supercategory is None) or (category["supercategory"].lower() == supercategory) } 116 | 117 | # Create a mapping from the old category ids to new ones that start at 0 118 | category_id_old_to_new = {id_old: id_new for id_new, id_old in enumerate(sorted(id_to_category.keys()))} 119 | 120 | # Create a class mapping from the string categories to the new ids 121 | class_mapping = {id_to_category[id_old]["name"]: id_new for id_new, id_old in enumerate(sorted(id_to_category.keys()))} 122 | 123 | valid_annotations = [] 124 | 125 | for annotation in data["annotations"]: 126 | image_id, category_id = annotation["image_id"], annotation["category_id"] 127 | 128 | # Check, if category is in supercategory (id should be in id_to_category dict) 129 | if category_id in id_to_category: 130 | filename_abs = os.path.abspath(os.path.join(image_folder, id_to_image[image_id]["file_name"])) 131 | 132 | valid_annotations.append((category_id_old_to_new[category_id], filename_abs)) 133 | 134 | return valid_annotations, len(category_id_old_to_new), class_mapping 135 | -------------------------------------------------------------------------------- /datasets/nab.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from .common import FileDatasetGenerator, DataSequence 4 | 5 | 6 | 7 | class NABGenerator(FileDatasetGenerator): 8 | 9 | def __init__(self, root_dir, classes = None, img_dir = 'images', img_list_file = 'images.txt', split_file = 'train_test_split.txt', label_file = 'image_class_labels.txt', 10 | cropsize = (224, 224), default_target_size = 256, randzoom_range = None, distort_colors = False, 11 | randerase_prob = 0.5, randerase_params = { 'sl' : 0.02, 'sh' : 0.3, 'r1' : 0.3, 'r2' : 1./0.3 }, 12 | mean = [125.30513277, 129.66606421, 118.45121113], std = [57.0045467, 56.70059436, 68.44430446], color_mode = "rgb", train_repeats = 1): 13 | """ NABirds and CUB-200-2011 data generator. 14 | 15 | # Arguments: 16 | 17 | - root_dir: Root directory of the NAB/CUB dataset, containing the files `images.txt`, `image_class_labels.txt`, and `train_test_split.txt`. 18 | 19 | - classes: List of classes to restrict the dataset to. Numeric labels will be assigned to these classes in ascending order. 20 | If set to `None`, all available classes will be used and enumerated in ascending order. 21 | 22 | - img_dir: Name of the sub-directory of `root_dir` that contains the images in further sub-directories named by their class label. 23 | 24 | - img_list_file: Name of a file (relative to `root_dir`) that contains tuples of image IDs and their filenames, separated by white-spaces, one tuple per line. 25 | 26 | - split_file: Name of a file (relative to `root_dir`) that specifies the training/test split as tuples of image IDs and either "1" (for training) 27 | or "0" (for test) images. 28 | 29 | - label_file: Name of a file (relative to `root_dir`) that specifies the class labels for each image as tuples of image IDs and class labels, one per line, 30 | separated by white-spaces. 31 | 32 | - cropsize: Tuple with width and height of crops extracted from the images. 33 | 34 | - default_target_size: Int or tuple of ints. Specifies the default target size which images will be resized to (before cropping) 35 | if not specified differently in calls to `flow_train/test` or `train/test_sequence`. 36 | If a single int is given, it specifies the size of the smaller side of the image and the aspect ratio will be retained. 37 | If set to -1, the image won't be resized. 38 | 39 | - randzoom_range: Tuple with minimum and maximum size of the smaller image dimension for random scale augmentation. 40 | May either be given as integer specifying absolute pixel values or float specifying the relative scale of the image. 41 | If set to `None`, no scale augmentation will be performed. 42 | 43 | - distort_colors: Boolean specifying whether to apply color distortions as data augmentation. 44 | 45 | - randerase_prob: Probability for random erasing. 46 | 47 | - randerase_params: Random erasing parameters (see Zhong et al. (2017): "Random erasing data augmentation."). 48 | 49 | - mean: Channel-wise image mean for normalization (in "RGB" order). If set to `None`, mean and standard deviation will be computed from the images. 50 | 51 | - std: Channel-wise standard deviation for normalization (in "RGB" order). If set to `None`, standard deviation will be computed from the images. 52 | 53 | - color_mode: Image color mode, either "rgb" or "bgr". 54 | 55 | - train_repeats: Number of repeats of the training data per epoch. If this was set to 3, for example, a single epoch would actually comprise 3 epochs. 56 | Works only with `train_sequence()`, not with `flow_train()`. 57 | """ 58 | 59 | super(NABGenerator, self).__init__(root_dir, cropsize = cropsize, default_target_size = default_target_size, randzoom_range = randzoom_range, 60 | distort_colors=distort_colors, colordistort_params={ 'hue_delta' : 0.0, 'saturation_range' : (0.8, 1.2) }, 61 | randerase_prob = randerase_prob, randerase_params = randerase_params, color_mode = color_mode) 62 | self.imgs_dir = os.path.join(root_dir, img_dir) 63 | self.img_list_file = os.path.join(root_dir, img_list_file) 64 | self.label_file = os.path.join(root_dir, label_file) 65 | self.split_file = os.path.join(root_dir, split_file) 66 | self.train_repeats = train_repeats 67 | 68 | # Read train/test split information 69 | with open(self.split_file) as f: 70 | is_train = { img_id : (flag != '0') for l in f if l.strip() != '' for img_id, flag in [l.strip().split()] } 71 | 72 | # Read labels 73 | with open(self.label_file) as f: 74 | img_labels = { img_id : int(lbl) for l in f if l.strip() != '' for img_id, lbl in [l.strip().split()] } 75 | self.classes = classes if classes is not None else sorted(set(img_labels.values())) 76 | self.class_indices = dict(zip(self.classes, range(len(self.classes)))) 77 | 78 | # Search for images 79 | with open(self.img_list_file) as f: 80 | for l in f: 81 | if l.strip() != '': 82 | img_id, fn = l.strip().split() 83 | if (img_id in is_train) and (img_labels[img_id] in self.class_indices): 84 | if is_train[img_id]: 85 | self.train_img_files.append(os.path.join(self.imgs_dir, fn)) 86 | self._train_labels.append(self.class_indices[img_labels[img_id]]) 87 | else: 88 | self.test_img_files.append(os.path.join(self.imgs_dir, fn)) 89 | self._test_labels.append(self.class_indices[img_labels[img_id]]) 90 | print('Found {} training and {} validation images from {} classes.'.format(self.num_train, self.num_test, self.num_classes)) 91 | 92 | # Compute mean and standard deviation 93 | self._compute_stats(mean, std) 94 | 95 | 96 | def train_sequence(self, batch_size = 32, shuffle = True, target_size = None, augment = True, batch_transform = None, batch_transform_kwargs = {}): 97 | 98 | return DataSequence(self, self.train_img_files, self._train_labels, 99 | batch_size=batch_size, shuffle=shuffle, 100 | target_size=target_size, normalize=True, hflip=augment, vflip=False, colordistort=self.distort_colors and augment, 101 | randzoom=augment, randrot=augment, cropsize=self.cropsize, randcrop=augment, randerase=augment, 102 | repeats=self.train_repeats, 103 | batch_transform=batch_transform, batch_transform_kwargs=batch_transform_kwargs) 104 | -------------------------------------------------------------------------------- /datasets/subdirectory.py: -------------------------------------------------------------------------------- 1 | import os 2 | from glob import glob 3 | 4 | from .common import FileDatasetGenerator 5 | 6 | 7 | 8 | class SubDirectoryGenerator(FileDatasetGenerator): 9 | 10 | def __init__(self, root_dir, classes = None, img_dir = '.', train_list = 'train.txt', test_list = 'test.txt', 11 | cropsize = (224, 224), default_target_size = 256, randzoom_range = None, randerase_prob = 0.5, randerase_params = { 'sl' : 0.02, 'sh' : 0.3, 'r1' : 0.3, 'r2' : 1./0.3 }, 12 | mean = None, std = None, color_mode = "rgb"): 13 | """ Data generator for images organized in sub-directories. 14 | 15 | This generator expects all images belonging to a class to be placed in a sub-directory named after that class. 16 | For splitting the dataset into a training and a validation partition, two files can be provided that list the 17 | images belonging to each partition. 18 | 19 | 20 | # Arguments: 21 | 22 | - root_dir: Root directory of the dataset, containing the images for each class in separate sub-directories. 23 | 24 | - classes: List of classes to restrict the dataset to. New numeric labels will be assigned to these classes in ascending order. 25 | If set to `None`, all available classes will be used and enumerated in ascending order. 26 | 27 | - img_dir: Directory (relative to root_dir) containing the images for each class in separate sub-directories. 28 | 29 | - train_list: Name of a text file (relative to root_dir) listing all training images (relative to img_dir), one per line. 30 | 31 | - test_list: Name of a text file (relative to root_dir) listing all validation images (relative to img_dir), one per line. 32 | 33 | - cropsize: Tuple with width and height of crops extracted from the images. 34 | 35 | - default_target_size: Int or tuple of ints. Specifies the default target size which images will be resized to (before cropping) 36 | if not specified differently in calls to `flow_train/test` or `train/test_sequence`. 37 | If a single int is given, it specifies the size of the smaller side of the image and the aspect ratio will be retained. 38 | If set to -1, the image won't be resized. 39 | 40 | - randzoom_range: Tuple with minimum and maximum size of the smaller image dimension for random scale augmentation. 41 | May either be given as integer specifying absolute pixel values or float specifying the relative scale of the image. 42 | If set to `None`, no scale augmentation will be performed. 43 | 44 | - randerase_prob: Probability for random erasing. 45 | 46 | - randerase_params: Random erasing parameters (see Zhong et al. (2017): "Random erasing data augmentation."). 47 | 48 | - mean: Channel-wise image mean for normalization (in "RGB" order). If set to `None`, mean and standard deviation will be computed from the images. 49 | 50 | - std: Channel-wise standard deviation for normalization (in "RGB" order). If set to `None`, standard deviation will be computed from the images. 51 | 52 | - color_mode: Image color mode, either "rgb" or "bgr". 53 | """ 54 | 55 | super(SubDirectoryGenerator, self).__init__(root_dir, cropsize = cropsize, default_target_size = default_target_size, randzoom_range = randzoom_range, 56 | randerase_prob = randerase_prob, randerase_params = randerase_params, color_mode = color_mode) 57 | 58 | self.img_dir = img_dir if os.path.isabs(img_dir) else os.path.join(root_dir, img_dir) 59 | 60 | # Determine set of classes 61 | if classes is not None: 62 | self.classes = classes 63 | else: 64 | self.classes = sorted(os.path.basename(dirname) for dirname in glob(os.path.join(self.img_dir, '*')) if (not os.path.basename(dirname).startswith('.')) and os.path.isdir(dirname)) 65 | self.class_indices = dict(zip(self.classes, range(len(self.classes)))) 66 | 67 | # Search for images 68 | with open(train_list if os.path.isabs(train_list) else os.path.join(root_dir, train_list)) as f: 69 | for l in f: 70 | if l.strip() != '': 71 | classname = os.path.dirname(l.strip()) 72 | if classname in self.class_indices: 73 | self.train_img_files.append(os.path.join(self.img_dir, l.strip())) 74 | self._train_labels.append(self.class_indices[classname]) 75 | with open(test_list if os.path.isabs(test_list) else os.path.join(root_dir, test_list)) as f: 76 | for l in f: 77 | if l.strip() != '': 78 | classname = os.path.dirname(l.strip()) 79 | if classname in self.class_indices: 80 | self.test_img_files.append(os.path.join(self.img_dir, l.strip())) 81 | self._test_labels.append(self.class_indices[classname]) 82 | 83 | print('Found {} training and {} validation images from {} classes.'.format(self.num_train, self.num_test, self.num_classes)) 84 | 85 | # Compute mean and standard deviation 86 | self._compute_stats(mean, std) -------------------------------------------------------------------------------- /embeddings/cifar100.glove.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cvjena/semantic-embeddings/0d4177422bafbba685fb6a0f976675864f31e09f/embeddings/cifar100.glove.pickle -------------------------------------------------------------------------------- /embeddings/cifar100.unitsphere.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cvjena/semantic-embeddings/0d4177422bafbba685fb6a0f976675864f31e09f/embeddings/cifar100.unitsphere.pickle -------------------------------------------------------------------------------- /embeddings/cub_balanced.unitsphere.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cvjena/semantic-embeddings/0d4177422bafbba685fb6a0f976675864f31e09f/embeddings/cub_balanced.unitsphere.pickle -------------------------------------------------------------------------------- /embeddings/cub_flat.unitsphere.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cvjena/semantic-embeddings/0d4177422bafbba685fb6a0f976675864f31e09f/embeddings/cub_flat.unitsphere.pickle -------------------------------------------------------------------------------- /embeddings/cub_wikispecies.unitsphere.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cvjena/semantic-embeddings/0d4177422bafbba685fb6a0f976675864f31e09f/embeddings/cub_wikispecies.unitsphere.pickle -------------------------------------------------------------------------------- /embeddings/imagenet_mintree.unitsphere.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cvjena/semantic-embeddings/0d4177422bafbba685fb6a0f976675864f31e09f/embeddings/imagenet_mintree.unitsphere.pickle -------------------------------------------------------------------------------- /embeddings/inat.sim1024.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cvjena/semantic-embeddings/0d4177422bafbba685fb6a0f976675864f31e09f/embeddings/inat.sim1024.pickle -------------------------------------------------------------------------------- /embeddings/inat2019.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cvjena/semantic-embeddings/0d4177422bafbba685fb6a0f976675864f31e09f/embeddings/inat2019.pickle -------------------------------------------------------------------------------- /embeddings/nab.sim.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cvjena/semantic-embeddings/0d4177422bafbba685fb6a0f976675864f31e09f/embeddings/nab.sim.pickle -------------------------------------------------------------------------------- /embeddings/nab.sim128.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cvjena/semantic-embeddings/0d4177422bafbba685fb6a0f976675864f31e09f/embeddings/nab.sim128.pickle -------------------------------------------------------------------------------- /embeddings/nab.sim128_unnormed.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cvjena/semantic-embeddings/0d4177422bafbba685fb6a0f976675864f31e09f/embeddings/nab.sim128_unnormed.pickle -------------------------------------------------------------------------------- /embeddings/nab.sim16.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cvjena/semantic-embeddings/0d4177422bafbba685fb6a0f976675864f31e09f/embeddings/nab.sim16.pickle -------------------------------------------------------------------------------- /embeddings/nab.sim16_unnormed.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cvjena/semantic-embeddings/0d4177422bafbba685fb6a0f976675864f31e09f/embeddings/nab.sim16_unnormed.pickle -------------------------------------------------------------------------------- /embeddings/nab.sim256.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cvjena/semantic-embeddings/0d4177422bafbba685fb6a0f976675864f31e09f/embeddings/nab.sim256.pickle -------------------------------------------------------------------------------- /embeddings/nab.sim256_unnormed.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cvjena/semantic-embeddings/0d4177422bafbba685fb6a0f976675864f31e09f/embeddings/nab.sim256_unnormed.pickle -------------------------------------------------------------------------------- /embeddings/nab.sim32.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cvjena/semantic-embeddings/0d4177422bafbba685fb6a0f976675864f31e09f/embeddings/nab.sim32.pickle -------------------------------------------------------------------------------- /embeddings/nab.sim32_unnormed.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cvjena/semantic-embeddings/0d4177422bafbba685fb6a0f976675864f31e09f/embeddings/nab.sim32_unnormed.pickle -------------------------------------------------------------------------------- /embeddings/nab.sim64.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cvjena/semantic-embeddings/0d4177422bafbba685fb6a0f976675864f31e09f/embeddings/nab.sim64.pickle -------------------------------------------------------------------------------- /embeddings/nab.sim64_unnormed.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cvjena/semantic-embeddings/0d4177422bafbba685fb6a0f976675864f31e09f/embeddings/nab.sim64_unnormed.pickle -------------------------------------------------------------------------------- /embeddings/nab.sim8.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cvjena/semantic-embeddings/0d4177422bafbba685fb6a0f976675864f31e09f/embeddings/nab.sim8.pickle -------------------------------------------------------------------------------- /embeddings/nab.sim8_unnormed.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cvjena/semantic-embeddings/0d4177422bafbba685fb6a0f976675864f31e09f/embeddings/nab.sim8_unnormed.pickle -------------------------------------------------------------------------------- /embeddings/nab.unitsphere.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cvjena/semantic-embeddings/0d4177422bafbba685fb6a0f976675864f31e09f/embeddings/nab.unitsphere.pickle -------------------------------------------------------------------------------- /evaluate_retrieval.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import numexpr as ne 3 | 4 | import argparse, pickle, os.path 5 | from collections import OrderedDict 6 | 7 | from datasets import get_data_generator 8 | from class_hierarchy import ClassHierarchy 9 | 10 | try: 11 | from tqdm import tqdm 12 | except ImportError: 13 | def tqdm(it, **kwargs): 14 | return it 15 | 16 | 17 | 18 | METRICS = ['P@1 (WUP)', 'P@10 (WUP)', 'P@50 (WUP)', 'P@100 (WUP)', 'AHP (WUP)', 'P@1 (LCS_HEIGHT)', 'P@10 (LCS_HEIGHT)', 'P@50 (LCS_HEIGHT)', 'P@100 (LCS_HEIGHT)', 'AHP (LCS_HEIGHT)', 'AP'] 19 | 20 | 21 | 22 | def pairwise_retrieval(features, normalize = False, return_generator = True): 23 | """ Uses each image as query and retrieves its nearest neighbors. 24 | 25 | # Arguments: 26 | 27 | - features: Features for all images. Can be provided in the following ways: 28 | - 2-d numpy array with each row corresponding to a sample. 29 | - Dictionary mapping image IDs to feature vectors. 30 | - Path to a pickle file containing such a dictionary. 31 | 32 | - normalize: Whether to L2-normalize the features. 33 | 34 | - return_generator: If True, a generator will be returned instead of a dictionary. 35 | 36 | # Returns: 37 | If return_generator is True, a generator will be returned that yields tuples consisting 38 | of an image ID and an ordered list with the IDs of this image's nearest neighbors. 39 | If return_generator is False, a dictionary mapping IDs to such lists will be returned. 40 | """ 41 | 42 | # Convert feature list to numpy array 43 | if isinstance(features, str): 44 | with open(features, 'rb') as feat_dump: 45 | features = pickle.load(feat_dump) 46 | if isinstance(features, dict): 47 | if 'feat' in features: 48 | features = features['feat'] 49 | ind2id = np.array(list(features.keys())) 50 | features = np.stack(list(features.values())) 51 | if features.ndim > 2: 52 | raise ValueError('Feature matrix must be 2-dimensional. Actual shape: {}'.format(features.shape)) 53 | else: 54 | ind2id = None 55 | 56 | # Compute pairwise distances 57 | if normalize: 58 | features /= np.linalg.norm(features, axis = -1, keepdims = True) 59 | pdist = -np.dot(features, features.T) 60 | else: 61 | sqnorm = np.sum(features ** 2, axis = -1) 62 | pdist = ne.evaluate('A + B - 2 * C', { 'A' : sqnorm[:,None], 'B' : sqnorm[None,:], 'C' : np.dot(features, features.T) }) 63 | del sqnorm 64 | del features 65 | 66 | # Rank images 67 | ranking = np.argsort(pdist, axis = -1) 68 | del pdist 69 | if ind2id is not None: 70 | gen = ((ind2id[i], ind2id[ret].tolist()) for i, ret in enumerate(ranking)) 71 | else: 72 | gen = ((i, ret.tolist()) for i, ret in enumerate(ranking)) 73 | return gen if return_generator else dict(gen) 74 | 75 | 76 | def print_performance(perf, metrics = METRICS): 77 | 78 | print() 79 | 80 | # Print header 81 | max_name_len = max(len(lbl) for lbl in perf.keys()) 82 | print(' | '.join([' ' * max_name_len] + ['{:^6s}'.format(metric) for metric in metrics])) 83 | print('-' * (max_name_len + sum(3 + max(6, len(metric)) for metric in metrics))) 84 | 85 | # Print result rows 86 | for lbl, results in perf.items(): 87 | print('{:{}s} | {}'.format(lbl, max_name_len, ' | '.join('{:>{}.4f}'.format(results[metric], max(len(metric), 6)) for metric in metrics))) 88 | 89 | print() 90 | 91 | 92 | def write_performance(perf, csv_file, prec_type = 'LCS_HEIGHT'): 93 | 94 | with open(csv_file, 'w') as f: 95 | f.write('k;' + ';'.join(perf.keys()) + '\n') 96 | k = 1 97 | while True: 98 | try: 99 | f.write('{};{}\n'.format(k, ';'.join(str(res['P@{} ({})'.format(k, prec_type)]) for res in perf.values()))) 100 | k += 1 101 | except KeyError: 102 | break 103 | 104 | 105 | def plot_performance(perf, kmax = 100, prec_type = 'LCS_HEIGHT', clip_ahp = None): 106 | 107 | import matplotlib.pyplot as plt 108 | 109 | plt.figure() 110 | plt.xlabel('k') 111 | plt.ylabel('Hierarchical Precision') 112 | plt.xlim(0, kmax) 113 | plt.ylim(0, 1) 114 | plt.grid() 115 | 116 | min_prec = 1.0 117 | for lbl, metrics in perf.items(): 118 | precs = [metrics['P@{} ({})'.format(k, prec_type)] for k in range(1, kmax+1)] 119 | plt.plot(np.arange(1, kmax + 1), precs, label = lbl) 120 | min_prec = min(min_prec, min(precs)) 121 | 122 | min_prec = np.floor(min_prec * 20) / 20 123 | if min_prec >= 0.3: 124 | plt.ylim(min_prec, 1) 125 | 126 | plt.legend(fontsize = 'x-small') 127 | 128 | 129 | plt.figure() 130 | plt.xlabel('Mean Average Hierarchical Precision') 131 | plt.yticks([]) 132 | plt.grid(axis = 'x') 133 | 134 | for i, (lbl, metrics) in enumerate(perf.items()): 135 | mAHP = metrics['AHP{} ({})'.format('@{}'.format(clip_ahp) if clip_ahp else '', prec_type)] 136 | plt.barh(i + 0.5, mAHP, 0.8) 137 | plt.text(0.01, i + 0.5, lbl, verticalalignment = 'center', horizontalalignment = 'left', color = 'white', fontsize = 'small') 138 | plt.text(mAHP - 0.01, i + 0.5, '{:.1%}'.format(mAHP), verticalalignment = 'center', horizontalalignment = 'right', color = 'white') 139 | 140 | 141 | plt.show() 142 | 143 | 144 | def str2bool(v): 145 | 146 | if v.lower() in ('yes', 'true', 't', 'y', '1'): 147 | return True 148 | elif v.lower() in ('no', 'false', 'f', 'n', '0'): 149 | return False 150 | else: 151 | raise argparse.ArgumentTypeError('Boolean value expected.') 152 | 153 | 154 | 155 | if __name__ == '__main__': 156 | 157 | parser = argparse.ArgumentParser(description = 'Evaluates hierarchical precision of nearest neighbour search performed on different image embeddings.', formatter_class = argparse.ArgumentDefaultsHelpFormatter) 158 | arggroup = parser.add_argument_group('Dataset') 159 | arggroup.add_argument('--dataset', type = str, required = True, help = 'Training dataset. See README.md for a list of available datasets.') 160 | arggroup.add_argument('--data_root', type = str, required = True, help = 'Root directory of the dataset.') 161 | arggroup.add_argument('--hierarchy', type = str, required = True, help = 'Path to a file containing parent-child relationships (one per line).') 162 | arggroup.add_argument('--is_a', action = 'store_true', default = False, help = 'If given, --hierarchy is assumed to contain is-a instead of parent-child relationships.') 163 | arggroup.add_argument('--str_ids', action = 'store_true', default = False, help = 'If given, class IDs are treated as strings instead of integers.') 164 | arggroup.add_argument('--classes_from', type = str, default = None, help = 'Optionally, a path to a pickle dump containing a dictionary with item "ind2label" specifying the classes to be considered.') 165 | arggroup = parser.add_argument_group('Features') 166 | arggroup.add_argument('--feat', type = str, action = 'append', required = True, help = 'Pickle file containing a dictionary mapping image IDs to features.') 167 | arggroup.add_argument('--label', type = str, action = 'append', help = 'Label for the corresponding features.') 168 | arggroup.add_argument('--norm', type = str2bool, action = 'append', help = 'Whether to L2-normalize the corresponding features or not (defaults to False).') 169 | arggroup = parser.add_argument_group('Output') 170 | arggroup.add_argument('--plot_max', type = int, default = 250, help = 'Plot hierarchical precision up to this number of retrieved images. Set this to 0 to disable plotting.') 171 | arggroup.add_argument('--prec_type', type = str, default = 'LCS_HEIGHT', choices = ['WUP', 'LCS_HEIGHT'], help = 'Measure for semantic similarity between classes to be used.') 172 | arggroup.add_argument('--clip_ahp', type = int, default = None, help = 'If given, clip ranking at this position for computing AHP.') 173 | arggroup.add_argument('--csv', type = str, default = None, help = 'Name of a CSV file where performance metrics will be written to.') 174 | args = parser.parse_args() 175 | 176 | # Load dataset 177 | if args.classes_from: 178 | with open(args.classes_from, 'rb') as f: 179 | embed_labels = pickle.load(f)['ind2label'] 180 | else: 181 | embed_labels = None 182 | data_generator = get_data_generator(args.dataset, args.data_root, classes = embed_labels) 183 | labels_test = [embed_labels[lbl] for lbl in data_generator.labels_test] if embed_labels is not None else data_generator.labels_test 184 | 185 | # Load class hierarchy 186 | id_type = str if args.str_ids else int 187 | hierarchy = ClassHierarchy.from_file(args.hierarchy, is_a_relations = args.is_a, id_type = id_type) 188 | 189 | # Perform image retrieval using all images in the dataset as queries 190 | ks = list(range(1, args.plot_max + 1)) 191 | for k in [1, 10, 50, 100]: 192 | if (len(ks) == 0) or (ks[-1] < k): 193 | ks.append(k) 194 | perf = OrderedDict() 195 | for i, feat_dump in tqdm(enumerate(args.feat), total = len(args.feat)): 196 | feat_name = args.label[i] if (args.label is not None) and (i < len(args.label)) else os.path.splitext(os.path.basename(feat_dump))[0] 197 | normalize = args.norm[i] if (args.norm is not None) and (i < len(args.norm)) else False 198 | perf[feat_name] = hierarchy.hierarchical_precision(pairwise_retrieval(feat_dump, normalize), labels_test, ks, compute_ahp = args.clip_ahp if args.clip_ahp else True, compute_ap = True, all_ids = list(range(data_generator.num_test)))[0] 199 | 200 | # Show results 201 | if args.clip_ahp: 202 | METRICS[4] = 'AHP@250 (WUP)' 203 | METRICS[9] = 'AHP@250 (LCS_HEIGHT)' 204 | print_performance(perf) 205 | if args.csv: 206 | write_performance(perf, args.csv, args.prec_type) 207 | if args.plot_max > 0: 208 | plot_performance(perf, args.plot_max, args.prec_type, args.clip_ahp) -------------------------------------------------------------------------------- /iNaturalist-Hierarchy/iNaturalist_hierarchies.py: -------------------------------------------------------------------------------- 1 | import json 2 | 3 | 4 | def generate_parent_child_pairs(path, supercategory=None): 5 | classes = [ 6 | #"supercategory", 7 | "kingdom", 8 | "phylum", 9 | "class", 10 | "order", 11 | "family", 12 | "genus", 13 | "id" 14 | ] 15 | 16 | with open(path, "r") as f: 17 | data = json.loads(f.read()) 18 | 19 | parent_child_pairs = set() 20 | 21 | for category in data["categories"]: 22 | if (supercategory is None) or (category["supercategory"] == supercategory): 23 | 24 | # Super-super category to connect all kingdoms into a tree 25 | parent_child_pairs.add(("__NULL__", category["kingdom"])) 26 | 27 | for i in range(len(classes) - 1): 28 | parent_child_pairs.add((category[classes[i]], category[classes[i + 1]])) 29 | 30 | for pair in sorted(list(parent_child_pairs)): 31 | print("{} {}".format(*pair)) 32 | 33 | 34 | if __name__ == "__main__": 35 | import argparse 36 | 37 | parser = argparse.ArgumentParser(description="This tool generates a parent-child file for semantic embeddings for " 38 | "the iNaturalist dataset and possibly a selected supercategory.") 39 | 40 | parser.add_argument("dataset_path", type=str, help="The path to the training file of the iNaturalist dataset.") 41 | parser.add_argument("--supercategory", type=str, default=None, 42 | help="The name of the supercategory the hierarchy will be based on (for iNaturalist 2018).") 43 | 44 | args = parser.parse_args() 45 | 46 | generate_parent_child_pairs(args.dataset_path, supercategory=args.supercategory) 47 | -------------------------------------------------------------------------------- /learn_devise.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | import argparse 4 | import pickle 5 | import os 6 | import shutil 7 | 8 | import keras 9 | from keras import backend as K 10 | 11 | import utils 12 | from datasets import get_data_generator 13 | 14 | 15 | 16 | def transform_inputs(X, y, embedding): 17 | 18 | return X, embedding[y] 19 | 20 | 21 | 22 | if __name__ == '__main__': 23 | 24 | # Parse arguments 25 | parser = argparse.ArgumentParser(description = 'Learns to map image features onto word embeddings of labels using DeViSE.', formatter_class = argparse.ArgumentDefaultsHelpFormatter) 26 | arggroup = parser.add_argument_group('Data parameters') 27 | arggroup.add_argument('--dataset', type = str, required = True, help = 'Training dataset. See README.md for a list of available datasets.') 28 | arggroup.add_argument('--data_root', type = str, required = True, help = 'Root directory of the dataset.') 29 | arggroup.add_argument('--embedding', type = str, required = True, help = 'Path to a pickle dump of embeddings in the same format as used by compute_class_embeddings.py.') 30 | arggroup = parser.add_argument_group('Training parameters') 31 | arggroup.add_argument('--architecture', type = str, default = 'simple', choices = utils.ARCHITECTURES, help = 'Type of network architecture.') 32 | arggroup.add_argument('--init_weights', type = str, default = None, help = 'Path to a weights file to initialize the model with.') 33 | arggroup.add_argument('--init_epochs', type = int, default = 25, help = 'Number of training epochs for the linear transformation layer only, keeping the rest of the network fixed.') 34 | arggroup.add_argument('--ft_epochs', type = int, default = 75, help = 'Number of training epochs for fine-tuning the full network.') 35 | arggroup.add_argument('--init_lr', type = float, default = 0.01, help = 'Learning rate for Adagrad during initial training of the linear transformation.') 36 | arggroup.add_argument('--ft_lr', type = float, default = 0.001, help = 'Learning rate for Adagrad during fine-tuning of the full network.') 37 | arggroup.add_argument('--batch_size', type = int, default = 100, help = 'Batch size.') 38 | arggroup.add_argument('--val_batch_size', type = int, default = None, help = 'Validation batch size.') 39 | arggroup.add_argument('--max_decay', type = float, default = 0.0, help = 'Learning Rate decay at the end of training.') 40 | arggroup.add_argument('--margin', type = float, default = 0.1, help = 'Margin of the hinge ranking loss.') 41 | arggroup.add_argument('--read_workers', type = int, default = 8, help = 'Number of parallel data pre-processing processes.') 42 | arggroup.add_argument('--queue_size', type = int, default = 100, help = 'Maximum size of data queue.') 43 | arggroup = parser.add_argument_group('Output parameters') 44 | arggroup.add_argument('--model_dump', type = str, default = None, help = 'Filename where the learned model definition and weights should be written to.') 45 | arggroup.add_argument('--weight_dump', type = str, default = None, help = 'Filename where the learned model weights should be written to (without model definition).') 46 | arggroup.add_argument('--feature_dump', type = str, default = None, help = 'Filename where learned embeddings for test images should be written to.') 47 | arggroup.add_argument('--log_dir', type = str, default = None, help = 'Tensorboard log directory.') 48 | arggroup.add_argument('--no_progress', action = 'store_true', default = False, help = 'Do not display training progress, but just the final performance.') 49 | args = parser.parse_args() 50 | 51 | if args.val_batch_size is None: 52 | args.val_batch_size = args.batch_size 53 | 54 | # Configure environment 55 | K.set_session(K.tf.Session(config = K.tf.ConfigProto(gpu_options = { 'allow_growth' : True }))) 56 | 57 | # Load and L2-normalize class embeddings 58 | with open(args.embedding, 'rb') as pf: 59 | embedding = pickle.load(pf) 60 | embed_labels = embedding['ind2label'] 61 | embedding = embedding['embedding'] 62 | embedding /= np.linalg.norm(embedding, axis = -1, keepdims = True) 63 | 64 | # Load dataset 65 | data_generator = get_data_generator(args.dataset, args.data_root, classes = embed_labels) 66 | 67 | # Construct and train model 68 | if args.init_weights: 69 | print('Initializing with model {}'.format(args.init_weights)) 70 | model = keras.models.load_model(args.init_weights, custom_objects = utils.get_custom_objects(args.architecture), compile = False) 71 | new_output = keras.layers.Dense(embedding.shape[1], name = 'embedding')(model.layers[-1].input) 72 | model = keras.models.Model(model.inputs, new_output) 73 | else: 74 | model = utils.build_network(embedding.shape[1], args.architecture) 75 | 76 | if not args.no_progress: 77 | model.summary() 78 | 79 | callbacks = [] 80 | batch_transform_kwargs = { 'embedding' : embedding } 81 | 82 | if args.init_weights and (args.init_epochs > 0): 83 | print('Pre-training linear transformation') 84 | for layer in model.layers[:-1]: 85 | layer.trainable = False 86 | 87 | model.compile(optimizer = keras.optimizers.Adagrad(lr=args.init_lr), 88 | loss = utils.devise_ranking_loss(embedding, args.margin), 89 | metrics = [utils.nn_accuracy(embedding, dot_prod_sim = True)]) 90 | 91 | model.fit_generator( 92 | data_generator.train_sequence(args.batch_size, batch_transform = transform_inputs, batch_transform_kwargs = batch_transform_kwargs), 93 | validation_data = data_generator.test_sequence(args.val_batch_size, batch_transform = transform_inputs, batch_transform_kwargs = batch_transform_kwargs), 94 | epochs = args.init_epochs, 95 | callbacks = callbacks, verbose = not args.no_progress, 96 | max_queue_size = 100, workers = 8, use_multiprocessing = True) 97 | 98 | for layer in model.layers[:-1]: 99 | layer.trainable = True 100 | 101 | if args.log_dir: 102 | if os.path.isdir(args.log_dir): 103 | shutil.rmtree(args.log_dir, ignore_errors = True) 104 | callbacks.append(keras.callbacks.TensorBoard(log_dir = args.log_dir, write_graph = False)) 105 | 106 | if args.ft_epochs > 0: 107 | print('Fine-tuning all layers') 108 | 109 | if args.max_decay > 0: 110 | decay = (1.0/args.max_decay - 1) / ((data_generator.num_train // args.batch_size) * args.ft_epochs) 111 | else: 112 | decay = 0.0 113 | 114 | model.compile(optimizer = keras.optimizers.Adagrad(lr=args.ft_lr, decay=decay), 115 | loss = utils.devise_ranking_loss(embedding, args.margin), 116 | metrics = [utils.nn_accuracy(embedding, dot_prod_sim = True)]) 117 | 118 | model.fit_generator( 119 | data_generator.train_sequence(args.batch_size, batch_transform = transform_inputs, batch_transform_kwargs = batch_transform_kwargs), 120 | validation_data = data_generator.test_sequence(args.val_batch_size, batch_transform = transform_inputs, batch_transform_kwargs = batch_transform_kwargs), 121 | epochs = args.ft_epochs, 122 | callbacks = callbacks, verbose = not args.no_progress, 123 | max_queue_size = args.queue_size, workers = args.read_workers, use_multiprocessing = True) 124 | 125 | # Evaluate final performance 126 | print(model.evaluate_generator(data_generator.test_sequence(args.val_batch_size, batch_transform = transform_inputs, batch_transform_kwargs = batch_transform_kwargs))) 127 | 128 | # Save model 129 | if args.weight_dump: 130 | try: 131 | model.save_weights(args.weight_dump) 132 | except Exception as e: 133 | print('An error occurred while saving the model weights: {}'.format(e)) 134 | if args.model_dump: 135 | try: 136 | model.save(args.model_dump) 137 | except Exception as e: 138 | print('An error occurred while saving the model: {}'.format(e)) 139 | 140 | # Save test image embeddings 141 | if args.feature_dump: 142 | pred_features = model.predict_generator(data_generator.flow_test(1, False), data_generator.num_test) 143 | with open(args.feature_dump,'wb') as dump_file: 144 | pickle.dump({ 'feat' : dict(enumerate(pred_features)) }, dump_file) 145 | -------------------------------------------------------------------------------- /models/DenseNet/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Somshubra Majumdar 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /models/DenseNet/README.md: -------------------------------------------------------------------------------- 1 | # Dense Net in Keras 2 | DenseNet implementation of the paper [Densely Connected Convolutional Networks](https://arxiv.org/pdf/1608.06993v3.pdf) in Keras 3 | 4 | Now supports the more efficient DenseNet-BC (DenseNet-Bottleneck-Compressed) networks. Using the DenseNet-BC-190-40 model, 5 | it obtaines state of the art performance on CIFAR-10 and CIFAR-100 6 | 7 | # Architecture 8 | DenseNet is an extention to Wide Residual Networks. According to the paper:
9 | ``` 10 | The lth layer has l inputs, consisting of the feature maps of all preceding convolutional blocks. 11 | Its own feature maps are passed on to all L − l subsequent layers. This introduces L(L+1) / 2 connections 12 | in an L-layer network, instead of just L, as in traditional feed-forward architectures. 13 | Because of its dense connectivity pattern, we refer to our approach as Dense Convolutional Network (DenseNet). 14 | ``` 15 | 16 | It features several improvements such as : 17 | 18 | 1. Dense connectivity : Connecting any layer to any other layer. 19 | 2. Growth Rate parameter Which dictates how fast the number of features increase as the network becomes deeper. 20 | 3. Consecutive functions : BatchNorm - Relu - Conv which is from the Wide ResNet paper and improvement from the ResNet paper. 21 | 22 | The Bottleneck - Compressed DenseNets offer further performance benefits, such as reduced number of parameters, with similar or better performance. 23 | 24 | - Take into consideration the DenseNet-100-12 model, with nearly 7 million parameters against with the DenseNet-BC-100-12, with just 0.8 million parameters. 25 | The BC model acheives 4.51 % error in comparison to the original models' 4.10 % error 26 | 27 | - The best original model, DenseNet-100-24 (27.2 million parameters) acheives 3.74 % error, whereas the DenseNet-BC-190-40 (25.6 million parameters) acheives 28 | 3.46 % error which is a new state of the art performance on CIFAR-10. 29 | 30 | Dense Nets have an architecture which can be shown in the following image from the paper:
31 | 32 | 33 | # Performance 34 | The accuracy of DenseNet has been provided in the paper, beating all previous benchmarks in CIFAR 10, CIFAR 100 and SVHN
35 | 36 | 37 | # Usage 38 | 39 | Import the `densenet.py` script and use the `DenseNet(...)` method to create a custom DenseNet model with a variety of parameters. 40 | 41 | Examples : 42 | 43 | ``` 44 | import densenet 45 | 46 | # 'th' dim-ordering or 'tf' dim-ordering 47 | image_dim = (3, 32, 32) or image_dim = (32, 32, 3) 48 | 49 | model = densenet.DenseNet(classes=10, input_shape=image_dim, depth=40, growth_rate=12, 50 | bottleneck=True, reduction=0.5) 51 | ``` 52 | 53 | Or, Import a pre-built DenseNet model for ImageNet, with some of these models having pre-trained weights (121, 161 and 169). 54 | 55 | Example : 56 | ``` 57 | import densenet 58 | 59 | # 'th' dim-ordering or 'tf' dim-ordering 60 | image_dim = (3, 224, 224) or image_dim = (224, 224, 3) 61 | 62 | model = densenet.DenseNetImageNet121(input_shape=image_dim) 63 | ``` 64 | 65 | Weights for the DenseNetImageNet121, DenseNetImageNet161 and DenseNetImageNet169 models are provided ([in the release tab](https://github.com/titu1994/DenseNet/releases)) and will be automatically downloaded when first called. They have been trained on ImageNet. The weights were ported from the repository https://github.com/flyyufelix/DenseNet-Keras. 66 | 67 | 68 | 69 | # Requirements 70 | 71 | - Keras 72 | - Theano (weights not tested) / Tensorflow (tested) / CNTK (weights not tested) 73 | - h5Py 74 | -------------------------------------------------------------------------------- /models/DenseNet/cifar10.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | 3 | import os.path 4 | 5 | import densenet 6 | import numpy as np 7 | import sklearn.metrics as metrics 8 | 9 | from keras.datasets import cifar10 10 | from keras.utils import np_utils 11 | from keras.preprocessing.image import ImageDataGenerator 12 | from keras.optimizers import Adam 13 | from keras.callbacks import ModelCheckpoint, ReduceLROnPlateau 14 | from keras import backend as K 15 | 16 | batch_size = 100 17 | nb_classes = 10 18 | nb_epoch = 300 19 | 20 | img_rows, img_cols = 32, 32 21 | img_channels = 3 22 | 23 | img_dim = (img_channels, img_rows, img_cols) if K.image_dim_ordering() == "th" else (img_rows, img_cols, img_channels) 24 | depth = 40 25 | nb_dense_block = 3 26 | growth_rate = 12 27 | nb_filter = -1 28 | dropout_rate = 0.0 # 0.0 for data augmentation 29 | 30 | model = densenet.DenseNet(img_dim, classes=nb_classes, depth=depth, nb_dense_block=nb_dense_block, 31 | growth_rate=growth_rate, nb_filter=nb_filter, dropout_rate=dropout_rate, weights=None) 32 | print("Model created") 33 | 34 | model.summary() 35 | optimizer = Adam(lr=1e-3) # Using Adam instead of SGD to speed up training 36 | model.compile(loss='categorical_crossentropy', optimizer=optimizer, metrics=["accuracy"]) 37 | print("Finished compiling") 38 | print("Building model...") 39 | 40 | (trainX, trainY), (testX, testY) = cifar10.load_data() 41 | 42 | trainX = trainX.astype('float32') 43 | testX = testX.astype('float32') 44 | 45 | trainX = densenet.preprocess_input(trainX) 46 | testX = densenet.preprocess_input(testX) 47 | 48 | Y_train = np_utils.to_categorical(trainY, nb_classes) 49 | Y_test = np_utils.to_categorical(testY, nb_classes) 50 | 51 | generator = ImageDataGenerator(rotation_range=15, 52 | width_shift_range=5./32, 53 | height_shift_range=5./32, 54 | horizontal_flip=True) 55 | 56 | generator.fit(trainX, seed=0) 57 | 58 | # Load model 59 | weights_file="weights/DenseNet-40-12-CIFAR10.h5" 60 | if os.path.exists(weights_file): 61 | #model.load_weights(weights_file, by_name=True) 62 | print("Model loaded.") 63 | 64 | out_dir="weights/" 65 | 66 | lr_reducer = ReduceLROnPlateau(monitor='val_acc', factor=np.sqrt(0.1), 67 | cooldown=0, patience=5, min_lr=1e-5) 68 | model_checkpoint= ModelCheckpoint(weights_file, monitor="val_acc", save_best_only=True, 69 | save_weights_only=True, verbose=1) 70 | 71 | callbacks=[lr_reducer, model_checkpoint] 72 | 73 | model.fit_generator(generator.flow(trainX, Y_train, batch_size=batch_size), 74 | steps_per_epoch=len(trainX) // batch_size, epochs=nb_epoch, 75 | callbacks=callbacks, 76 | validation_data=(testX, Y_test), 77 | validation_steps=testX.shape[0] // batch_size, verbose=1) 78 | 79 | yPreds = model.predict(testX) 80 | yPred = np.argmax(yPreds, axis=1) 81 | yTrue = testY 82 | 83 | accuracy = metrics.accuracy_score(yTrue, yPred) * 100 84 | error = 100 - accuracy 85 | print("Accuracy : ", accuracy) 86 | print("Error : ", error) 87 | 88 | -------------------------------------------------------------------------------- /models/DenseNet/cifar100.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | 3 | import sys 4 | sys.setrecursionlimit(10000) 5 | 6 | import densenet 7 | import numpy as np 8 | import sklearn.metrics as metrics 9 | 10 | from keras.datasets import cifar100 11 | from keras.utils import np_utils 12 | from keras.preprocessing.image import ImageDataGenerator 13 | from keras.optimizers import Adam 14 | from keras.callbacks import ModelCheckpoint, ReduceLROnPlateau, EarlyStopping 15 | from keras import backend as K 16 | 17 | batch_size = 64 18 | nb_classes = 100 19 | nb_epoch = 15 20 | 21 | img_rows, img_cols = 32, 32 22 | img_channels = 3 23 | 24 | img_dim = (img_channels, img_rows, img_cols) if K.image_dim_ordering() == "th" else (img_rows, img_cols, img_channels) 25 | depth = 40 26 | nb_dense_block = 3 27 | growth_rate = 12 28 | nb_filter = 12 29 | bottleneck = False 30 | reduction = 0.0 31 | dropout_rate = 0.0 # 0.0 for data augmentation 32 | 33 | 34 | model = densenet.DenseNet(img_dim, classes=nb_classes, depth=depth, nb_dense_block=nb_dense_block, 35 | growth_rate=growth_rate, nb_filter=nb_filter, dropout_rate=dropout_rate, 36 | bottleneck=bottleneck, reduction=reduction, weights=None) 37 | print("Model created") 38 | 39 | model.summary() 40 | optimizer = Adam(lr=1e-4) # Using Adam instead of SGD to speed up training 41 | model.compile(loss='categorical_crossentropy', optimizer=optimizer, metrics=["accuracy"]) 42 | print("Finished compiling") 43 | print("Building model...") 44 | 45 | (trainX, trainY), (testX, testY) = cifar100.load_data() 46 | 47 | trainX = trainX.astype('float32') 48 | testX = testX.astype('float32') 49 | 50 | trainX /= 255. 51 | testX /= 255. 52 | 53 | Y_train = np_utils.to_categorical(trainY, nb_classes) 54 | Y_test = np_utils.to_categorical(testY, nb_classes) 55 | 56 | generator = ImageDataGenerator(rotation_range=15, 57 | width_shift_range=5./32, 58 | height_shift_range=5./32) 59 | 60 | generator.fit(trainX, seed=0) 61 | 62 | # Load model 63 | # model.load_weights("weights/DenseNet-BC-100-12-CIFAR100.h5") 64 | # print("Model loaded.") 65 | 66 | lr_reducer = ReduceLROnPlateau(monitor='val_loss', factor=np.sqrt(0.1), 67 | cooldown=0, patience=10, min_lr=0.5e-6) 68 | early_stopper = EarlyStopping(monitor='val_acc', min_delta=0.0001, patience=20) 69 | model_checkpoint= ModelCheckpoint("weights/DenseNet-BC-100-12-CIFAR100.h5", monitor="val_acc", save_best_only=True, 70 | save_weights_only=True) 71 | 72 | callbacks=[lr_reducer, early_stopper, model_checkpoint] 73 | 74 | 75 | model.fit_generator(generator.flow(trainX, Y_train, batch_size=batch_size), samples_per_epoch=len(trainX), nb_epoch=nb_epoch, 76 | callbacks=callbacks, 77 | validation_data=(testX, Y_test), 78 | nb_val_samples=testX.shape[0], verbose=1) 79 | 80 | yPreds = model.predict(testX) 81 | yPred = np.argmax(yPreds, axis=1) 82 | yTrue = testY 83 | 84 | accuracy = metrics.accuracy_score(yTrue, yPred) * 100 85 | error = 100 - accuracy 86 | print("Accuracy : ", accuracy) 87 | print("Error : ", error) 88 | 89 | -------------------------------------------------------------------------------- /models/DenseNet/densenet_fast.py: -------------------------------------------------------------------------------- 1 | from keras.models import Model 2 | from keras.layers.core import Dense, Dropout, Activation 3 | from keras.layers.convolutional import Convolution2D 4 | from keras.layers.pooling import AveragePooling2D 5 | from keras.layers.pooling import GlobalAveragePooling2D 6 | from keras.layers import Input, merge 7 | from keras.layers.normalization import BatchNormalization 8 | from keras.regularizers import l2 9 | import keras.backend as K 10 | 11 | ''' 12 | Based on the implementation here : https://github.com/Lasagne/Recipes/blob/master/papers/densenet/densenet_fast.py 13 | ''' 14 | 15 | def conv_block(ip, nb_filter, dropout_rate=None, weight_decay=1E-4): 16 | ''' Apply BatchNorm, Relu 3x3, Conv2D, optional dropout 17 | 18 | Args: 19 | ip: Input keras tensor 20 | nb_filter: number of filters 21 | dropout_rate: dropout rate 22 | weight_decay: weight decay factor 23 | 24 | Returns: keras tensor with batch_norm, relu and convolution2d added 25 | 26 | ''' 27 | 28 | x = Activation('relu')(ip) 29 | x = Convolution2D(nb_filter, 3, 3, init="he_uniform", border_mode="same", bias=False, 30 | W_regularizer=l2(weight_decay))(x) 31 | if dropout_rate: 32 | x = Dropout(dropout_rate)(x) 33 | 34 | return x 35 | 36 | 37 | def transition_block(ip, nb_filter, dropout_rate=None, weight_decay=1E-4): 38 | ''' Apply BatchNorm, Relu 1x1, Conv2D, optional dropout and Maxpooling2D 39 | 40 | Args: 41 | ip: keras tensor 42 | nb_filter: number of filters 43 | dropout_rate: dropout rate 44 | weight_decay: weight decay factor 45 | 46 | Returns: keras tensor, after applying batch_norm, relu-conv, dropout, maxpool 47 | 48 | ''' 49 | 50 | concat_axis = 1 if K.image_dim_ordering() == "th" else -1 51 | 52 | x = Convolution2D(nb_filter, 1, 1, init="he_uniform", border_mode="same", bias=False, 53 | W_regularizer=l2(weight_decay))(ip) 54 | if dropout_rate: 55 | x = Dropout(dropout_rate)(x) 56 | x = AveragePooling2D((2, 2), strides=(2, 2))(x) 57 | 58 | x = BatchNormalization(mode=0, axis=concat_axis, gamma_regularizer=l2(weight_decay), 59 | beta_regularizer=l2(weight_decay))(x) 60 | 61 | return x 62 | 63 | 64 | def dense_block(x, nb_layers, nb_filter, growth_rate, dropout_rate=None, weight_decay=1E-4): 65 | ''' Build a dense_block where the output of each conv_block is fed to subsequent ones 66 | 67 | Args: 68 | x: keras tensor 69 | nb_layers: the number of layers of conv_block to append to the model. 70 | nb_filter: number of filters 71 | growth_rate: growth rate 72 | dropout_rate: dropout rate 73 | weight_decay: weight decay factor 74 | 75 | Returns: keras tensor with nb_layers of conv_block appended 76 | 77 | ''' 78 | 79 | concat_axis = 1 if K.image_dim_ordering() == "th" else -1 80 | 81 | feature_list = [x] 82 | 83 | for i in range(nb_layers): 84 | x = conv_block(x, growth_rate, dropout_rate, weight_decay) 85 | feature_list.append(x) 86 | x = merge(feature_list, mode='concat', concat_axis=concat_axis) 87 | nb_filter += growth_rate 88 | 89 | return x, nb_filter 90 | 91 | 92 | def create_dense_net(nb_classes, img_dim, depth=40, nb_dense_block=3, growth_rate=12, nb_filter=16, dropout_rate=None, 93 | weight_decay=1E-4, verbose=True): 94 | ''' Build the create_dense_net model 95 | 96 | Args: 97 | nb_classes: number of classes 98 | img_dim: tuple of shape (channels, rows, columns) or (rows, columns, channels) 99 | depth: number or layers 100 | nb_dense_block: number of dense blocks to add to end 101 | growth_rate: number of filters to add 102 | nb_filter: number of filters 103 | dropout_rate: dropout rate 104 | weight_decay: weight decay 105 | 106 | Returns: keras tensor with nb_layers of conv_block appended 107 | 108 | ''' 109 | 110 | model_input = Input(shape=img_dim) 111 | 112 | concat_axis = 1 if K.image_dim_ordering() == "th" else -1 113 | 114 | assert (depth - 4) % 3 == 0, "Depth must be 3 N + 4" 115 | 116 | # layers in each dense block 117 | nb_layers = int((depth - 4) / 3) 118 | 119 | # Initial convolution 120 | x = Convolution2D(nb_filter, 3, 3, init="he_uniform", border_mode="same", name="initial_conv2D", bias=False, 121 | W_regularizer=l2(weight_decay))(model_input) 122 | 123 | x = BatchNormalization(mode=0, axis=concat_axis, gamma_regularizer=l2(weight_decay), 124 | beta_regularizer=l2(weight_decay))(x) 125 | 126 | # Add dense blocks 127 | for block_idx in range(nb_dense_block - 1): 128 | x, nb_filter = dense_block(x, nb_layers, nb_filter, growth_rate, dropout_rate=dropout_rate, 129 | weight_decay=weight_decay) 130 | # add transition_block 131 | x = transition_block(x, nb_filter, dropout_rate=dropout_rate, weight_decay=weight_decay) 132 | 133 | # The last dense_block does not have a transition_block 134 | x, nb_filter = dense_block(x, nb_layers, nb_filter, growth_rate, dropout_rate=dropout_rate, 135 | weight_decay=weight_decay) 136 | 137 | x = Activation('relu')(x) 138 | x = GlobalAveragePooling2D()(x) 139 | x = Dense(nb_classes, activation='softmax', W_regularizer=l2(weight_decay), b_regularizer=l2(weight_decay))(x) 140 | 141 | densenet = Model(input=model_input, output=x, name="create_dense_net") 142 | 143 | if verbose: print("DenseNet-%d-%d created." % (depth, growth_rate)) 144 | 145 | return densenet -------------------------------------------------------------------------------- /models/DenseNet/imagenet_inference.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | from __future__ import absolute_import 3 | 4 | from keras.preprocessing import image 5 | 6 | from densenet import DenseNetImageNet121, DenseNetImageNet169, DenseNetImageNet161, preprocess_input, decode_predictions 7 | 8 | import numpy as np 9 | 10 | if __name__ == '__main__': 11 | size = 224 12 | 13 | model = DenseNetImageNet121(input_shape=(size, size, 3)) 14 | model.summary() 15 | 16 | 17 | img_path = 'images/elephant.jpg' 18 | img = image.load_img(img_path, target_size=(size, size)) 19 | x = image.img_to_array(img) 20 | x = np.expand_dims(x, axis=0) 21 | 22 | x = preprocess_input(x) 23 | 24 | preds = model.predict(x) 25 | 26 | print('Predicted:', decode_predictions(preds)) 27 | 28 | -------------------------------------------------------------------------------- /models/DenseNet/subpixel.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | 3 | from keras import backend as K 4 | from keras.engine import Layer 5 | from keras.utils.generic_utils import get_custom_objects 6 | try: 7 | from keras.utils.conv_utils import normalize_data_format 8 | except ImportError: 9 | from keras.backend import normalize_data_format 10 | 11 | if K.backend() == 'theano': 12 | import theano_backend as K_BACKEND 13 | else: 14 | import tensorflow_backend as K_BACKEND 15 | 16 | class SubPixelUpscaling(Layer): 17 | """ Sub-pixel convolutional upscaling layer based on the paper "Real-Time Single Image 18 | and Video Super-Resolution Using an Efficient Sub-Pixel Convolutional Neural Network" 19 | (https://arxiv.org/abs/1609.05158). 20 | This layer requires a Convolution2D prior to it, having output filters computed according to 21 | the formula : 22 | filters = k * (scale_factor * scale_factor) 23 | where k = a user defined number of filters (generally larger than 32) 24 | scale_factor = the upscaling factor (generally 2) 25 | This layer performs the depth to space operation on the convolution filters, and returns a 26 | tensor with the size as defined below. 27 | # Example : 28 | ```python 29 | # A standard subpixel upscaling block 30 | x = Convolution2D(256, 3, 3, padding='same', activation='relu')(...) 31 | u = SubPixelUpscaling(scale_factor=2)(x) 32 | [Optional] 33 | x = Convolution2D(256, 3, 3, padding='same', activation='relu')(u) 34 | ``` 35 | In practice, it is useful to have a second convolution layer after the 36 | SubPixelUpscaling layer to speed up the learning process. 37 | However, if you are stacking multiple SubPixelUpscaling blocks, it may increase 38 | the number of parameters greatly, so the Convolution layer after SubPixelUpscaling 39 | layer can be removed. 40 | # Arguments 41 | scale_factor: Upscaling factor. 42 | data_format: Can be None, 'channels_first' or 'channels_last'. 43 | # Input shape 44 | 4D tensor with shape: 45 | `(samples, k * (scale_factor * scale_factor) channels, rows, cols)` if data_format='channels_first' 46 | or 4D tensor with shape: 47 | `(samples, rows, cols, k * (scale_factor * scale_factor) channels)` if data_format='channels_last'. 48 | # Output shape 49 | 4D tensor with shape: 50 | `(samples, k channels, rows * scale_factor, cols * scale_factor))` if data_format='channels_first' 51 | or 4D tensor with shape: 52 | `(samples, rows * scale_factor, cols * scale_factor, k channels)` if data_format='channels_last'. 53 | """ 54 | 55 | def __init__(self, scale_factor=2, data_format=None, **kwargs): 56 | super(SubPixelUpscaling, self).__init__(**kwargs) 57 | 58 | self.scale_factor = scale_factor 59 | self.data_format = normalize_data_format(data_format) 60 | 61 | def build(self, input_shape): 62 | pass 63 | 64 | def call(self, x, mask=None): 65 | y = K_BACKEND.depth_to_space(x, self.scale_factor, self.data_format) 66 | return y 67 | 68 | def compute_output_shape(self, input_shape): 69 | if self.data_format == 'channels_first': 70 | b, k, r, c = input_shape 71 | return (b, k // (self.scale_factor ** 2), r * self.scale_factor, c * self.scale_factor) 72 | else: 73 | b, r, c, k = input_shape 74 | return (b, r * self.scale_factor, c * self.scale_factor, k // (self.scale_factor ** 2)) 75 | 76 | def get_config(self): 77 | config = {'scale_factor': self.scale_factor, 78 | 'data_format': self.data_format} 79 | base_config = super(SubPixelUpscaling, self).get_config() 80 | return dict(list(base_config.items()) + list(config.items())) 81 | 82 | 83 | get_custom_objects().update({'SubPixelUpscaling': SubPixelUpscaling}) 84 | -------------------------------------------------------------------------------- /models/DenseNet/tensorflow_backend.py: -------------------------------------------------------------------------------- 1 | import tensorflow as tf 2 | 3 | from keras.backend import tensorflow_backend as KTF 4 | from keras.backend.common import image_data_format 5 | 6 | py_all = all 7 | 8 | def depth_to_space(input, scale, data_format=None): 9 | ''' Uses phase shift algorithm to convert channels/depth for spatial resolution ''' 10 | if data_format is None: 11 | data_format = image_data_format() 12 | 13 | if data_format == 'channels_first': 14 | data_format = 'NCHW' 15 | else: 16 | data_format = 'NHWC' 17 | 18 | data_format = data_format.lower() 19 | out = tf.depth_to_space(input, scale, data_format=data_format) 20 | return out 21 | -------------------------------------------------------------------------------- /models/DenseNet/theano_backend.py: -------------------------------------------------------------------------------- 1 | from theano import tensor as T 2 | 3 | from keras.backend import theano_backend as KTH 4 | from keras.backend.common import image_data_format 5 | from keras.backend.theano_backend import _preprocess_conv2d_input 6 | from keras.backend.theano_backend import _postprocess_conv2d_output 7 | 8 | 9 | py_all = all 10 | 11 | def depth_to_space(input, scale, data_format=None): 12 | ''' Uses phase shift algorithm to convert channels/depth for spatial resolution ''' 13 | if data_format is None: 14 | data_format = image_data_format() 15 | data_format = data_format.lower() 16 | input = _preprocess_conv2d_input(input, data_format) 17 | 18 | b, k, row, col = input.shape 19 | out_channels = k // (scale ** 2) 20 | x = T.reshape(input, (b, scale, scale, out_channels, row, col)) 21 | x = T.transpose(x, (0, 3, 4, 1, 5, 2)) 22 | out = T.reshape(x, (b, out_channels, row * scale, col * scale)) 23 | 24 | out = _postprocess_conv2d_output(out, input, None, None, None, data_format) 25 | return out 26 | -------------------------------------------------------------------------------- /models/cifar_pyramidnet.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """PyramidNet model for CIFAR. 3 | 4 | # Reference: 5 | 6 | - [Deep Pyramidal Residual Networks](https://arxiv.org/abs/1610.02915) 7 | 8 | # Reference implementation: 9 | 10 | - https://github.com/jhkim89/PyramidNet/blob/master/addpyramidnet.lua 11 | """ 12 | from __future__ import print_function 13 | from __future__ import absolute_import 14 | 15 | import warnings 16 | 17 | from keras import layers, regularizers 18 | from keras import backend as K 19 | from keras.layers import Input 20 | from keras.layers import Dense, Activation, Flatten, Conv2D, AveragePooling2D, GlobalAveragePooling2D, BatchNormalization 21 | from keras.models import Model 22 | from keras.engine import Layer, InputSpec 23 | from keras.engine.topology import get_source_inputs 24 | from keras.utils import layer_utils, conv_utils 25 | from keras.utils.data_utils import get_file 26 | 27 | from .cifar_resnet import ChannelPadding 28 | 29 | 30 | 31 | def PyramidNet(depth, alpha, bottleneck = True, 32 | include_top=True, weights=None, 33 | input_tensor=None, input_shape=None, 34 | pooling='avg', regularizer=regularizers.l2(0.0002), 35 | activation = 'relu', top_activation='softmax', 36 | classes=100, name=None): 37 | """Instantiates the PyramidNet architecture. 38 | 39 | # Arguments 40 | depth: depth of the network. 41 | alpha: total number of channels to be distributed across the layers. 42 | bottleneck: boolean specifying whether to use bottleneck blocks. 43 | include_top: whether to include the fully-connected 44 | layer at the top of the network. 45 | weights: `None` (random initialization) 46 | or path to weights file. 47 | input_tensor: optional Keras tensor (i.e. output of `layers.Input()`) 48 | to use as image input for the model. 49 | input_shape: optional shape tuple, only to be specified 50 | if `include_top` is False (otherwise the input shape 51 | has to be `(32, 32, 3)` (with `channels_last` data format) 52 | or `(3, 32, 32)` (with `channels_first` data format). 53 | It should have exactly 3 inputs channels. 54 | pooling: Optional pooling mode for feature extraction 55 | when `include_top` is `False`. 56 | - `avg` means that global average pooling 57 | will be applied to the output of the 58 | last convolutional layer, and thus 59 | the output of the model will be a 2D tensor. 60 | - `max` means that global max pooling will 61 | be applied. 62 | regularizer: weight of kernel regularizer. 63 | activation: name of the activation function to be used. 64 | top_activation: name of the activation function to be used for the top layer. 65 | conv_shortcut: boolean, specifying whether to use padding (False) or 66 | convolution (True) at the shortcuts. 67 | classes: optional number of classes to classify images 68 | into, only to be specified if `include_top` is True, and 69 | if no `weights` argument is specified. 70 | name: name of the network. 71 | 72 | # Returns 73 | A Keras model instance. 74 | 75 | # Raises 76 | ValueError: in case of invalid argument for `weights`, 77 | or invalid input shape. 78 | """ 79 | 80 | 81 | def shortcut(x, n, stride): 82 | if stride > 1: 83 | x = AveragePooling2D(stride)(x) 84 | input_channels = int(x.shape[1 if K.image_data_format() == 'channels_first' else -1]) 85 | if input_channels < n: 86 | x = ChannelPadding((0, n - input_channels))(x) 87 | return x 88 | 89 | 90 | def basic_block(x, n, stride): 91 | s = BatchNormalization()(x) 92 | s = Conv2D(n, (3, 3), strides = stride, padding = 'same', kernel_initializer = 'glorot_normal', kernel_regularizer = regularizer)(s) 93 | s = BatchNormalization()(s) 94 | s = Activation(activation)(s) 95 | s = Conv2D(n, (3, 3), padding = 'same', kernel_initializer = 'glorot_normal', kernel_regularizer = regularizer)(s) 96 | s = BatchNormalization()(s) 97 | return layers.add([s, shortcut(x, n, stride)]) 98 | 99 | 100 | def bottleneck_block(x, n, stride): 101 | s = BatchNormalization()(x) 102 | s = Conv2D(n, (1, 1), kernel_initializer = 'glorot_normal', kernel_regularizer = regularizer)(s) 103 | s = BatchNormalization()(s) 104 | s = Activation(activation)(s) 105 | s = Conv2D(n, (3, 3), strides = stride, padding = 'same', kernel_initializer = 'glorot_normal', kernel_regularizer = regularizer)(s) 106 | s = BatchNormalization()(s) 107 | s = Activation(activation)(s) 108 | s = Conv2D(n*4, (1, 1), kernel_initializer = 'glorot_normal', kernel_regularizer = regularizer)(s) 109 | s = BatchNormalization()(s) 110 | return layers.add([s, shortcut(x, n * 4, stride)]) 111 | 112 | 113 | def unit(x, features, count, stride): 114 | block = bottleneck_block if bottleneck else basic_block 115 | for i in range(count): 116 | x = block(x, features, stride) 117 | return x 118 | 119 | 120 | # Derived parameters 121 | n = (depth - 2) // 9 if bottleneck else (depth - 2) // 6 122 | channels = 16 123 | start_channel = 16 124 | add_channel = float(alpha) / (3*n) 125 | 126 | # Determine proper input shape 127 | if input_shape is None: 128 | if K.image_data_format() == 'channels_first': 129 | input_shape = (3, 32, 32) if include_top else (3, None, None) 130 | else: 131 | input_shape = (32, 32, 3) if include_top else (None, None, 3) 132 | 133 | # Build network 134 | if input_tensor is None: 135 | img_input = Input(shape=input_shape) 136 | else: 137 | if not K.is_keras_tensor(input_tensor): 138 | img_input = Input(tensor=input_tensor, shape=input_shape) 139 | else: 140 | img_input = input_tensor 141 | if K.image_data_format() == 'channels_last': 142 | bn_axis = 3 143 | else: 144 | bn_axis = 1 145 | 146 | x = Conv2D(start_channel, (3, 3), padding='same', name='conv0', kernel_initializer = 'glorot_normal', kernel_regularizer = regularizer)(img_input) 147 | x = BatchNormalization(axis=bn_axis, name='bn0')(x) 148 | 149 | for b in range(3): 150 | start_channel += add_channel 151 | x = unit(x, round(start_channel), 1, 1 if b == 0 else 2) 152 | for i in range(1, n): 153 | start_channel += add_channel 154 | x = unit(x, round(start_channel), 1, 1) 155 | 156 | x = BatchNormalization(axis=bn_axis, name='bn4')(x) 157 | x = Activation(activation, name='act4')(x) 158 | 159 | # Final pooling 160 | if pooling == 'avg': 161 | x = GlobalAveragePooling2D(name='avg_pool')(x) 162 | elif pooling == 'max': 163 | x = GlobalMaxPooling2D(name='max_pool')(x) 164 | 165 | # Top layer 166 | if include_top: 167 | x = Dense(classes, activation=top_activation, name = 'embedding' if top_activation is None else 'prob', kernel_regularizer = regularizer)(x) 168 | 169 | # Ensure that the model takes into account 170 | # any potential predecessors of `input_tensor`. 171 | if input_tensor is not None: 172 | inputs = get_source_inputs(input_tensor) 173 | else: 174 | inputs = img_input 175 | # Create model. 176 | model = Model(inputs, x, name='pyramidnet-{}-{}'.format(depth, alpha) if name is None else name) 177 | 178 | # load weights 179 | if weights is not None: 180 | model.load_weights(weights) 181 | 182 | if K.image_data_format() == 'channels_first' and K.backend() == 'tensorflow': 183 | warnings.warn('You are using the TensorFlow backend, yet you ' 184 | 'are using the Theano ' 185 | 'image data format convention ' 186 | '(`image_data_format="channels_first"`). ' 187 | 'For best performance, set ' 188 | '`image_data_format="channels_last"` in ' 189 | 'your Keras config ' 190 | 'at ~/.keras/keras.json.') 191 | return model 192 | -------------------------------------------------------------------------------- /models/plainnet.py: -------------------------------------------------------------------------------- 1 | import keras 2 | from keras import backend as K 3 | 4 | 5 | def PlainNet(output_dim, 6 | filters = [64, 64, 'ap', 128, 128, 128, 'ap', 256, 256, 256, 'ap', 512, 'gap', 'fc512'], 7 | activation = 'relu', 8 | regularizer = keras.regularizers.l2(0.0005), 9 | final_activation = None, 10 | input_shape = (None, None, 3), 11 | pool_size = (2,2), 12 | name = None): 13 | """ Creates the Plain-11 network architecture. 14 | 15 | # Reference: 16 | 17 | Björn Barz and Joachim Denzler: 18 | "Deep Learning is not a Matter of Depth but of Good Training." 19 | International Conference on Pattern Recognition and Artificial Intelligence (ICPRAI), pp. 683-687, 2018. 20 | http://hera.inf-cv.uni-jena.de:6680/pdf/Barz18:GoodTraining 21 | 22 | # Arguments: 23 | 24 | - output_dim: Number of output units of the final layer. 25 | 26 | - filters: List specifying the individual layers constituting the network architecture. 27 | BatchNormalization will be inserted automatically. 28 | Possible types of values for the items of this list are: 29 | - int: a 3x3 Conv2D layer with this number of channels. 30 | - 'fc'+int: fully-connected layer with the specified number of units. 31 | - 'ap': average pooling. 32 | - 'mp': maximum pooling. 33 | - 'gap': global average pooling. 34 | 35 | - activation: Activation function of Conv2D and Dense layers. 36 | 37 | - regularizer: Kernel regularizer of Conv2D and Dense layers. 38 | 39 | - final_activation: Activation function of the final layer. 40 | 41 | - input_shape: 3-tuple specifying the shape of the input tensor. 42 | 43 | - pool_size: 2-tuple specifying the kernel size of average pooling and maximum pooling layers. 44 | 45 | - name: Name of the network. 46 | """ 47 | 48 | prefix = '' if name is None else name + '_' 49 | 50 | flattened = False 51 | layers = [ 52 | keras.layers.Conv2D(filters[0], (3, 3), padding = 'same', activation = activation, kernel_regularizer = regularizer, input_shape = input_shape, name = prefix + 'conv1'), 53 | keras.layers.BatchNormalization(name = prefix + 'bn1') 54 | ] 55 | for i, f in enumerate(filters[1:], start = 2): 56 | if f == 'mp': 57 | layers.append(keras.layers.MaxPooling2D(pool_size = pool_size, name = '{}mp{}'.format(prefix, i))) 58 | elif f == 'ap': 59 | layers.append(keras.layers.AveragePooling2D(pool_size = pool_size, name = '{}ap{}'.format(prefix, i))) 60 | elif f == 'gap': 61 | layers.append(keras.layers.GlobalAvgPool2D(name = prefix + 'avg_pool')) 62 | flattened = True 63 | elif isinstance(f, str) and f.startswith('fc'): 64 | if not flattened: 65 | layers.append(keras.layers.Flatten(name = prefix + 'flatten')) 66 | flattened = True 67 | layers.append(keras.layers.Dense(int(f[2:]), activation = activation, kernel_regularizer = regularizer, name = '{}fc{}'.format(prefix, i))) 68 | layers.append(keras.layers.BatchNormalization(name = '{}bn{}'.format(prefix, i))) 69 | else: 70 | layers.append(keras.layers.Conv2D(f, (3, 3), padding = 'same', activation = activation, kernel_regularizer = regularizer, name = '{}conv{}'.format(prefix, i))) 71 | layers.append(keras.layers.BatchNormalization(name = '{}bn{}'.format(prefix, i))) 72 | 73 | if not flattened: 74 | layers.append(keras.layers.Flatten(name = prefix + 'flatten')) 75 | flattened = True 76 | layers.append(keras.layers.Dense(output_dim, activation = final_activation, name = prefix + ('prob' if final_activation == 'softmax' else 'embedding'))) 77 | 78 | return keras.models.Sequential(layers, name = name) -------------------------------------------------------------------------------- /models/wide_residual_network.py: -------------------------------------------------------------------------------- 1 | from keras.models import Model 2 | from keras.layers import Input, Add, Activation, Dropout, GlobalAveragePooling2D, Dense 3 | from keras.layers.convolutional import Convolution2D 4 | from keras.layers.normalization import BatchNormalization 5 | from keras import backend as K 6 | 7 | 8 | def initial_conv(input): 9 | x = Convolution2D(16, (3, 3), padding='same', kernel_initializer='he_normal', 10 | use_bias=False)(input) 11 | 12 | channel_axis = 1 if K.image_data_format() == "channels_first" else -1 13 | 14 | x = BatchNormalization(axis=channel_axis, momentum=0.1, epsilon=1e-5, gamma_initializer='uniform')(x) 15 | x = Activation('relu')(x) 16 | return x 17 | 18 | 19 | def expand_conv(init, base, k, strides=(1, 1)): 20 | x = Convolution2D(base * k, (3, 3), padding='same', strides=strides, kernel_initializer='he_normal', 21 | use_bias=False)(init) 22 | 23 | channel_axis = 1 if K.image_data_format() == "channels_first" else -1 24 | 25 | x = BatchNormalization(axis=channel_axis, momentum=0.1, epsilon=1e-5, gamma_initializer='uniform')(x) 26 | x = Activation('relu')(x) 27 | 28 | x = Convolution2D(base * k, (3, 3), padding='same', kernel_initializer='he_normal', 29 | use_bias=False)(x) 30 | 31 | skip = Convolution2D(base * k, (1, 1), padding='same', strides=strides, kernel_initializer='he_normal', 32 | use_bias=False)(init) 33 | 34 | m = Add()([x, skip]) 35 | 36 | return m 37 | 38 | 39 | def conv_block(input, base, k=1, dropout=0.0): 40 | init = input 41 | 42 | channel_axis = 1 if K.image_data_format() == "channels_first" else -1 43 | 44 | x = BatchNormalization(axis=channel_axis, momentum=0.1, epsilon=1e-5, gamma_initializer='uniform')(input) 45 | x = Activation('relu')(x) 46 | x = Convolution2D(base * k, (3, 3), padding='same', kernel_initializer='he_normal', 47 | use_bias=False)(x) 48 | 49 | if dropout > 0.0: x = Dropout(dropout)(x) 50 | 51 | x = BatchNormalization(axis=channel_axis, momentum=0.1, epsilon=1e-5, gamma_initializer='uniform')(x) 52 | x = Activation('relu')(x) 53 | x = Convolution2D(base * k, (3, 3), padding='same', kernel_initializer='he_normal', 54 | use_bias=False)(x) 55 | 56 | m = Add()([init, x]) 57 | return m 58 | 59 | 60 | def create_wide_residual_network(input_dim, nb_classes=100, N=2, k=1, dropout=0.0, final_activation='softmax', verbose=1, name=None): 61 | """ 62 | Creates a Wide Residual Network with specified parameters 63 | 64 | :param input: Input Keras object 65 | :param nb_classes: Number of output classes 66 | :param N: Depth of the network. Compute N = (n - 4) / 6. 67 | Example : For a depth of 16, n = 16, N = (16 - 4) / 6 = 2 68 | Example2: For a depth of 28, n = 28, N = (28 - 4) / 6 = 4 69 | Example3: For a depth of 40, n = 40, N = (40 - 4) / 6 = 6 70 | :param k: Width of the network. 71 | :param dropout: Adds dropout if value is greater than 0.0 72 | :param final_activation: Activation function of last layer 73 | :param verbose: Debug info to describe created WRN 74 | :return: 75 | """ 76 | channel_axis = 1 if K.image_data_format() == "channels_first" else -1 77 | 78 | ip = Input(shape=input_dim) 79 | 80 | x = initial_conv(ip) 81 | nb_conv = 4 82 | 83 | for block_index, base in enumerate([16, 32, 64]): 84 | 85 | x = expand_conv(x, base, k, strides=(2, 2) if block_index > 0 else (1, 1)) 86 | 87 | for i in range(N - 1): 88 | x = conv_block(x, base, k, dropout) 89 | nb_conv += 2 90 | 91 | x = BatchNormalization(axis=channel_axis, momentum=0.1, epsilon=1e-5, gamma_initializer='uniform')(x) 92 | x = Activation('relu')(x) 93 | 94 | x = GlobalAveragePooling2D()(x) 95 | 96 | x = Dense(nb_classes, activation=final_activation, name = 'prob' if final_activation == 'softmax' else 'embedding')(x) 97 | 98 | model = Model(ip, x, name=name) 99 | 100 | if verbose: print("Wide Residual Network-%d-%d created." % (nb_conv, k)) 101 | return model 102 | 103 | if __name__ == "__main__": 104 | from keras.utils import plot_model 105 | from keras.layers import Input 106 | from keras.models import Model 107 | 108 | init = (32, 32, 3) 109 | 110 | wrn_28_10 = create_wide_residual_network(init, nb_classes=10, N=2, k=2, dropout=0.0) 111 | 112 | wrn_28_10.summary() 113 | 114 | plot_model(wrn_28_10, "WRN-16-2.png", show_shapes=True, show_layer_names=True) 115 | -------------------------------------------------------------------------------- /plot_hierarchy.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import argparse 3 | import pydot 4 | 5 | from class_hierarchy import ClassHierarchy 6 | 7 | 8 | 9 | def plot_hierarchy(hierarchy, filename, class_names = None): 10 | 11 | if isinstance(hierarchy, ClassHierarchy): 12 | hierarchy = hierarchy.children 13 | 14 | graph = pydot.Dot(graph_type = 'digraph', rankdir = 'LR') 15 | nodes = {} 16 | for lbl, children in hierarchy.items(): 17 | nodes[lbl] = pydot.Node(lbl, label = lbl if class_names is None else class_names[lbl], style = 'filled', fillcolor = '#ffffff' if len(children) == 0 else '#eaeaea') 18 | for child in children: 19 | if child not in hierarchy: 20 | nodes[child] = pydot.Node(child, label = child if class_names is None else class_names[child], style = 'filled', fillcolor = '#ffffff') 21 | for node in nodes.values(): 22 | graph.add_node(node) 23 | 24 | for parent, children in hierarchy.items(): 25 | for child in children: 26 | graph.add_edge(pydot.Edge(nodes[parent], nodes[child])) 27 | 28 | graph.write_svg(filename, prog = 'dot') 29 | 30 | 31 | 32 | if __name__ == '__main__': 33 | 34 | # Parse arguments 35 | parser = argparse.ArgumentParser(description = 'Creates a graphical visualization of a class taxonomy.', formatter_class = argparse.ArgumentDefaultsHelpFormatter) 36 | parser.add_argument('--hierarchy', type = str, required = True, help = 'Path to a file containing parent-child or is-a relationships (one per line).') 37 | parser.add_argument('--is_a', action = 'store_true', default = False, help = 'If given, --hierarchy is assumed to contain is-a instead of parent-child relationships.') 38 | parser.add_argument('--str_ids', action = 'store_true', default = False, help = 'If given, class IDs are treated as strings instead of integers.') 39 | parser.add_argument('--class_names', type = str, default = None, help = 'Optionally, a text file mapping class labels to names, given as one comma-separated label-name tuple per line.') 40 | parser.add_argument('--out', type = str, required = True, help = 'Filename of the resulting SVG plot.') 41 | args = parser.parse_args() 42 | id_type = str if args.str_ids else int 43 | 44 | # Read hierarchy 45 | hierarchy = ClassHierarchy.from_file(args.hierarchy, is_a_relations = args.is_a, id_type = id_type) 46 | 47 | # Read class names 48 | if args.class_names is not None: 49 | with open(args.class_names) as f: 50 | class_names = { id_type(lbl) : name for l in f if l.strip() != '' for lbl, name in [l.strip().split(maxsplit=1)] } 51 | else: 52 | class_names = None 53 | 54 | # Plot hierarchy 55 | plot_hierarchy(hierarchy, args.out, class_names=class_names) -------------------------------------------------------------------------------- /plot_recall_precision.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from sklearn.metrics import average_precision_score 3 | import matplotlib.pyplot as plt 4 | 5 | import argparse, pickle, os.path 6 | from collections import OrderedDict 7 | 8 | from datasets import get_data_generator 9 | from evaluate_retrieval import pairwise_retrieval, str2bool 10 | 11 | try: 12 | from tqdm import tqdm 13 | except ImportError: 14 | def tqdm(it, **kwargs): 15 | return it 16 | 17 | 18 | 19 | if __name__ == '__main__': 20 | 21 | parser = argparse.ArgumentParser(description = 'Plots the average recall-precision curve of nearest neighbour search performed on different image embeddings.', formatter_class = argparse.ArgumentDefaultsHelpFormatter) 22 | arggroup = parser.add_argument_group('Dataset') 23 | arggroup.add_argument('--dataset', type = str, required = True, help = 'Training dataset. See README.md for a list of available datasets.') 24 | arggroup.add_argument('--data_root', type = str, required = True, help = 'Root directory of the dataset.') 25 | arggroup.add_argument('--classes_from', type = str, default = None, help = 'Optionally, a path to a pickle dump containing a dictionary with item "ind2label" specifying the classes to be considered.') 26 | arggroup = parser.add_argument_group('Features') 27 | arggroup.add_argument('--feat', type = str, action = 'append', required = True, help = 'Pickle file containing a dictionary mapping image IDs to features.') 28 | arggroup.add_argument('--label', type = str, action = 'append', help = 'Label for the corresponding features.') 29 | arggroup.add_argument('--norm', type = str2bool, action = 'append', help = 'Whether to L2-normalize the corresponding features or not (defaults to False).') 30 | arggroup = parser.add_argument_group('Plot') 31 | arggroup.add_argument('--bins', type = int, default = None, help = 'Optional, number of recall levels to be distinguished.') 32 | args = parser.parse_args() 33 | 34 | # Load dataset 35 | if args.classes_from: 36 | with open(args.classes_from, 'rb') as f: 37 | embed_labels = pickle.load(f)['ind2label'] 38 | else: 39 | embed_labels = None 40 | data_generator = get_data_generator(args.dataset, args.data_root, classes = embed_labels) 41 | labels_test = [embed_labels[lbl] for lbl in data_generator.labels_test] if embed_labels is not None else data_generator.labels_test 42 | 43 | # Create figure 44 | plt.figure() 45 | plt.xlabel('Recall') 46 | plt.ylabel('Precision') 47 | plt.xlim(0, 1) 48 | plt.ylim(0, 1) 49 | plt.grid() 50 | 51 | # Draw recall-precision curves for all features 52 | for i, feat_dump in tqdm(enumerate(args.feat), total = len(args.feat)): 53 | 54 | feat_name = args.label[i] if (args.label is not None) and (i < len(args.label)) else os.path.splitext(os.path.basename(feat_dump))[0] 55 | normalize = args.norm[i] if (args.norm is not None) and (i < len(args.norm)) else False 56 | recprec = {} 57 | aps = [] 58 | 59 | for qid, retrieved in tqdm(pairwise_retrieval(feat_dump, normalize, True), total = data_generator.num_test): 60 | 61 | rp = {} 62 | 63 | correct = np.asarray([labels_test[r] == labels_test[qid] for r in retrieved if r != qid]) 64 | aps.append(average_precision_score(correct, -np.arange(len(correct)))) 65 | 66 | tp = correct.astype(np.float).cumsum() 67 | recall = tp / tp[-1] 68 | precision = tp / np.arange(1, len(tp) + 1) 69 | for r, p in zip(recall, precision): 70 | if args.bins: 71 | r = int(r * args.bins) / args.bins + 1/(2*args.bins) 72 | rp[r] = max(rp[r], p) if r in rp else p 73 | for r, p in rp.items(): 74 | if r in recprec: 75 | recprec[r].append(p) 76 | else: 77 | recprec[r] = [p] 78 | 79 | levels = sorted(recprec.keys()) 80 | plt.plot(levels, [np.mean(recprec[r]) for r in levels], label = '{} (mAP: {:.2%})'.format(feat_name, np.mean(aps))) 81 | 82 | # Show figure 83 | plt.legend(fontsize = 'x-small') 84 | plt.show() -------------------------------------------------------------------------------- /sgdr_callback.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from keras.callbacks import Callback 3 | from keras import backend as K 4 | 5 | 6 | class SGDR(Callback): 7 | """This callback implements the learning rate schedule for 8 | Stochastic Gradient Descent with warm Restarts (SGDR), 9 | as proposed by Loshchilov & Hutter (https://arxiv.org/abs/1608.03983). 10 | 11 | The learning rate at each epoch is computed as: 12 | lr(i) = min_lr + 0.5 * (max_lr - min_lr) * (1 + cos(pi * i/num_epochs)) 13 | 14 | Here, num_epochs is the number of epochs in the current cycle, which starts 15 | with base_epochs initially and is multiplied by mul_epochs after each cycle. 16 | 17 | # Example 18 | ```python 19 | sgdr = SGDR(min_lr=0.0, max_lr=0.05, 20 | base_epochs=10, mul_epochs=2) 21 | model.compile(optimizer=keras.optimizers.SGD(decay=1e-4, momentum=0.9), 22 | loss=loss) 23 | model.fit(X_train, Y_train, callbacks=[sgdr]) 24 | ``` 25 | 26 | # Arguments 27 | min_lr: minimum learning rate reached at the end of each cycle. 28 | max_lr: maximum learning rate used at the beginning of each cycle. 29 | base_epochs: number of epochs in the first cycle. 30 | mul_epochs: factor with which the number of epochs is multiplied 31 | after each cycle. 32 | """ 33 | 34 | def __init__(self, min_lr=0.0, max_lr=0.05, base_epochs=10, mul_epochs=2): 35 | super(SGDR, self).__init__() 36 | 37 | self.min_lr = min_lr 38 | self.max_lr = max_lr 39 | self.base_epochs = base_epochs 40 | self.mul_epochs = mul_epochs 41 | 42 | self.cycles = 0. 43 | self.cycle_iterations = 0. 44 | self.trn_iterations = 0. 45 | 46 | self._reset() 47 | 48 | def _reset(self, new_min_lr=None, new_max_lr=None, 49 | new_base_epochs=None, new_mul_epochs=None): 50 | """Resets cycle iterations.""" 51 | 52 | if new_min_lr != None: 53 | self.min_lr = new_min_lr 54 | if new_max_lr != None: 55 | self.max_lr = new_max_lr 56 | if new_base_epochs != None: 57 | self.base_epochs = new_base_epochs 58 | if new_mul_epochs != None: 59 | self.mul_epochs = new_mul_epochs 60 | self.cycles = 0. 61 | self.cycle_iterations = 0. 62 | 63 | def sgdr(self): 64 | 65 | cycle_epochs = self.base_epochs * (self.mul_epochs ** self.cycles) 66 | return self.min_lr + 0.5 * (self.max_lr - self.min_lr) * (1 + np.cos(np.pi * (self.cycle_iterations + 1) / cycle_epochs)) 67 | 68 | def on_train_begin(self, logs=None): 69 | 70 | if self.cycle_iterations == 0: 71 | K.set_value(self.model.optimizer.lr, self.max_lr) 72 | else: 73 | K.set_value(self.model.optimizer.lr, self.sgdr()) 74 | 75 | def on_epoch_end(self, epoch, logs=None): 76 | 77 | logs = logs or {} 78 | logs['lr'] = K.get_value(self.model.optimizer.lr) 79 | 80 | self.trn_iterations += 1 81 | self.cycle_iterations += 1 82 | if self.cycle_iterations >= self.base_epochs * (self.mul_epochs ** self.cycles): 83 | self.cycles += 1 84 | self.cycle_iterations = 0 85 | K.set_value(self.model.optimizer.lr, self.max_lr) 86 | else: 87 | K.set_value(self.model.optimizer.lr, self.sgdr()) 88 | --------------------------------------------------------------------------------