├── .gitignore ├── .travis.yml ├── LICENSE.txt ├── README.md ├── data ├── cat.jpg ├── cat_224.jpg ├── croco.jpg ├── imagenet_classes.txt └── imagenet_synsets.txt ├── examples ├── imagenet_eval.py ├── imagenet_logits.py ├── visu_arch.py └── voc2007_extract.py ├── pretrainedmodels ├── __init__.py ├── datasets │ ├── __init__.py │ ├── utils.py │ └── voc.py ├── models │ ├── __init__.py │ ├── bninception.py │ ├── cafferesnet.py │ ├── dpn.py │ ├── fbresnet.py │ ├── fbresnet │ │ ├── resnet152_dump.lua │ │ └── resnet152_load.py │ ├── inceptionresnetv2.py │ ├── inceptionv4.py │ ├── nasnet.py │ ├── nasnet_mobile.py │ ├── pnasnet.py │ ├── polynet.py │ ├── resnext.py │ ├── resnext_features │ │ ├── __init__.py │ │ ├── resnext101_32x4d_features.py │ │ └── resnext101_64x4d_features.py │ ├── senet.py │ ├── torchvision_models.py │ ├── utils.py │ ├── vggm.py │ ├── wideresnet.py │ └── xception.py ├── utils.py └── version.py ├── requirements.txt ├── setup.cfg ├── setup.py └── tests ├── test_pm_imagenet.py └── test_torch_save.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Added by ~ cadene ~ 2 | .DS_Store 3 | ._.DS_Store 4 | 5 | # Byte-compiled / optimized / DLL files 6 | __pycache__/ 7 | *.py[cod] 8 | *$py.class 9 | 10 | # C extensions 11 | *.so 12 | 13 | # Distribution / packaging 14 | .Python 15 | build/ 16 | develop-eggs/ 17 | dist/ 18 | downloads/ 19 | eggs/ 20 | .eggs/ 21 | lib/ 22 | lib64/ 23 | parts/ 24 | sdist/ 25 | var/ 26 | wheels/ 27 | *.egg-info/ 28 | .installed.cfg 29 | *.egg 30 | 31 | # PyInstaller 32 | # Usually these files are written by a python script from a template 33 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 34 | *.manifest 35 | *.spec 36 | 37 | # Installer logs 38 | pip-log.txt 39 | pip-delete-this-directory.txt 40 | 41 | # Unit test / coverage reports 42 | htmlcov/ 43 | .tox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | .hypothesis/ 51 | 52 | # Translations 53 | *.mo 54 | *.pot 55 | 56 | # Django stuff: 57 | *.log 58 | local_settings.py 59 | 60 | # Flask stuff: 61 | instance/ 62 | .webassets-cache 63 | 64 | # Scrapy stuff: 65 | .scrapy 66 | 67 | # Sphinx documentation 68 | docs/_build/ 69 | 70 | # PyBuilder 71 | target/ 72 | 73 | # Jupyter Notebook 74 | .ipynb_checkpoints 75 | 76 | # pyenv 77 | .python-version 78 | 79 | # celery beat schedule file 80 | celerybeat-schedule 81 | 82 | # SageMath parsed files 83 | *.sage.py 84 | 85 | # Environments 86 | .env 87 | .venv 88 | env/ 89 | venv/ 90 | ENV/ 91 | 92 | # Spyder project settings 93 | .spyderproject 94 | .spyproject 95 | 96 | # Rope project settings 97 | .ropeproject 98 | 99 | # mkdocs documentation 100 | /site 101 | 102 | # mypy 103 | .mypy_cache/ 104 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | python: 3 | - "3.6" 4 | # - "2.7" 5 | 6 | # cache: 7 | # directories: 8 | # - $HOME/.torch 9 | 10 | stages: 11 | # - lint_check 12 | - test 13 | # - docs 14 | 15 | install: 16 | - sudo apt-get update 17 | - wget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh; 18 | - bash miniconda.sh -b -p $HOME/miniconda 19 | - export PATH="$HOME/miniconda/bin:$PATH" 20 | - hash -r 21 | - conda config --set always_yes yes --set changeps1 no 22 | - conda update -q conda 23 | # Useful for debugging any issues with conda 24 | - conda info -a 25 | - conda create -q -n test-environment -c pytorch python=$TRAVIS_PYTHON_VERSION numpy mock pytorch-cpu 26 | - if [[ $TRAVIS_PYTHON_VERSION == 2.7 ]]; then pip install enum34; fi 27 | - source activate test-environment 28 | - python setup.py install 29 | - pip install --upgrade pytest #codecov pytest-cov 30 | # Test contrib dependencies 31 | # - pip install scikit-learn 32 | # Examples dependencies 33 | - pip install -r requirements.txt 34 | #visdom torchvision tensorboardX 35 | #- pip install gym 36 | #- pip install tqdm 37 | 38 | script: 39 | - python -m pytest -s tests #--cov pretrainedmodels --cov-report term-missing 40 | 41 | # Smoke tests for the examples 42 | # Mnist 43 | # 1) mnist.py 44 | #- python examples/mnist/mnist.py --epochs=1 45 | # 2) mnist_with_visdom.py 46 | # - python -c "from visdom.server import download_scripts; download_scripts()" # download scripts : https://github.com/facebookresearch/visdom/blob/master/py/server.py#L929 47 | # - python -m visdom.server & 48 | # - sleep 10 49 | # - python examples/mnist/mnist_with_visdom.py --epochs=1 50 | # - kill %1 51 | # # 3) mnist_with_tensorboardx.py 52 | # - python examples/mnist/mnist_with_tensorboardx.py --epochs=1 53 | 54 | # # dcgan.py 55 | # - python examples/gan/dcgan.py --dataset fake --dataroot /tmp/fakedata --output-dir /tmp/outputs-dcgan --batch-size 2 --epochs 2 --workers 0 56 | 57 | # # RL 58 | # # 1) Actor-Critic 59 | # - python examples/reinforcement_learning/actor_critic.py --max-episodes=2 60 | # # 1) Reinforce 61 | # - python examples/reinforcement_learning/reinforce.py --max-episodes=2 62 | 63 | # #fast-neural-style 64 | # #train 65 | # - python examples/fast_neural_style/neural_style.py train --epochs 1 --cuda 0 --dataset test --dataroot . --image_size 32 --style_image examples/fast_neural_style/images/style_images/mosaic.jpg --style_size 32 66 | 67 | after_success: 68 | # Ignore codecov failures as the codecov server is not 69 | # very reliable but we don't want travis to report a failure 70 | # in the github UI just because the coverage report failed to 71 | # be published. 72 | - codecov || echo "codecov upload failed" 73 | 74 | # jobs: 75 | # include: 76 | # - stage: lint_check 77 | # python: "3.6" 78 | # install: pip install flake8 79 | # script: flake8 80 | # after_success: # Nothing to do 81 | 82 | 83 | # # GitHub Pages Deployment: https://docs.travis-ci.com/user/deployment/pages/ 84 | # - stage: docs 85 | # python: "3.6" 86 | # install: 87 | # # Minimal install : ignite and dependencies just to build the docs 88 | # - pip install -r docs/requirements.txt 89 | # - pip install http://download.pytorch.org/whl/cpu/torch-0.4.1-cp35-cp35m-linux_x86_64.whl 90 | # # Add contrib dependencies (otherwise doc is not built) 91 | # - pip install scikit-learn scipy 92 | # # `pip install .` vs `python setup.py install` : 1st works better to produce _module/ignite with source links 93 | # - pip install . 94 | # script: 95 | # - cd docs && make html 96 | # # Create .nojekyll file to serve correctly _static and friends 97 | # - touch build/html/.nojekyll 98 | # after_success: # Nothing to do 99 | # deploy: 100 | # provider: pages 101 | # skip-cleanup: true 102 | # github-token: $GITHUB_TOKEN # Set in the settings page of your repository, as a secure variable 103 | # keep-history: false 104 | # local_dir: docs/build/html 105 | # on: 106 | # branch: master -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2017, Remi Cadene 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | * Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | * Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | * Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /data/cat.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cadene/pretrained-models.pytorch/8aae3d8f1135b6b13fed79c1d431e3449fdbf6e0/data/cat.jpg -------------------------------------------------------------------------------- /data/cat_224.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cadene/pretrained-models.pytorch/8aae3d8f1135b6b13fed79c1d431e3449fdbf6e0/data/cat_224.jpg -------------------------------------------------------------------------------- /data/croco.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cadene/pretrained-models.pytorch/8aae3d8f1135b6b13fed79c1d431e3449fdbf6e0/data/croco.jpg -------------------------------------------------------------------------------- /data/imagenet_classes.txt: -------------------------------------------------------------------------------- 1 | n01440764 2 | n01443537 3 | n01484850 4 | n01491361 5 | n01494475 6 | n01496331 7 | n01498041 8 | n01514668 9 | n01514859 10 | n01518878 11 | n01530575 12 | n01531178 13 | n01532829 14 | n01534433 15 | n01537544 16 | n01558993 17 | n01560419 18 | n01580077 19 | n01582220 20 | n01592084 21 | n01601694 22 | n01608432 23 | n01614925 24 | n01616318 25 | n01622779 26 | n01629819 27 | n01630670 28 | n01631663 29 | n01632458 30 | n01632777 31 | n01641577 32 | n01644373 33 | n01644900 34 | n01664065 35 | n01665541 36 | n01667114 37 | n01667778 38 | n01669191 39 | n01675722 40 | n01677366 41 | n01682714 42 | n01685808 43 | n01687978 44 | n01688243 45 | n01689811 46 | n01692333 47 | n01693334 48 | n01694178 49 | n01695060 50 | n01697457 51 | n01698640 52 | n01704323 53 | n01728572 54 | n01728920 55 | n01729322 56 | n01729977 57 | n01734418 58 | n01735189 59 | n01737021 60 | n01739381 61 | n01740131 62 | n01742172 63 | n01744401 64 | n01748264 65 | n01749939 66 | n01751748 67 | n01753488 68 | n01755581 69 | n01756291 70 | n01768244 71 | n01770081 72 | n01770393 73 | n01773157 74 | n01773549 75 | n01773797 76 | n01774384 77 | n01774750 78 | n01775062 79 | n01776313 80 | n01784675 81 | n01795545 82 | n01796340 83 | n01797886 84 | n01798484 85 | n01806143 86 | n01806567 87 | n01807496 88 | n01817953 89 | n01818515 90 | n01819313 91 | n01820546 92 | n01824575 93 | n01828970 94 | n01829413 95 | n01833805 96 | n01843065 97 | n01843383 98 | n01847000 99 | n01855032 100 | n01855672 101 | n01860187 102 | n01871265 103 | n01872401 104 | n01873310 105 | n01877812 106 | n01882714 107 | n01883070 108 | n01910747 109 | n01914609 110 | n01917289 111 | n01924916 112 | n01930112 113 | n01943899 114 | n01944390 115 | n01945685 116 | n01950731 117 | n01955084 118 | n01968897 119 | n01978287 120 | n01978455 121 | n01980166 122 | n01981276 123 | n01983481 124 | n01984695 125 | n01985128 126 | n01986214 127 | n01990800 128 | n02002556 129 | n02002724 130 | n02006656 131 | n02007558 132 | n02009229 133 | n02009912 134 | n02011460 135 | n02012849 136 | n02013706 137 | n02017213 138 | n02018207 139 | n02018795 140 | n02025239 141 | n02027492 142 | n02028035 143 | n02033041 144 | n02037110 145 | n02051845 146 | n02056570 147 | n02058221 148 | n02066245 149 | n02071294 150 | n02074367 151 | n02077923 152 | n02085620 153 | n02085782 154 | n02085936 155 | n02086079 156 | n02086240 157 | n02086646 158 | n02086910 159 | n02087046 160 | n02087394 161 | n02088094 162 | n02088238 163 | n02088364 164 | n02088466 165 | n02088632 166 | n02089078 167 | n02089867 168 | n02089973 169 | n02090379 170 | n02090622 171 | n02090721 172 | n02091032 173 | n02091134 174 | n02091244 175 | n02091467 176 | n02091635 177 | n02091831 178 | n02092002 179 | n02092339 180 | n02093256 181 | n02093428 182 | n02093647 183 | n02093754 184 | n02093859 185 | n02093991 186 | n02094114 187 | n02094258 188 | n02094433 189 | n02095314 190 | n02095570 191 | n02095889 192 | n02096051 193 | n02096177 194 | n02096294 195 | n02096437 196 | n02096585 197 | n02097047 198 | n02097130 199 | n02097209 200 | n02097298 201 | n02097474 202 | n02097658 203 | n02098105 204 | n02098286 205 | n02098413 206 | n02099267 207 | n02099429 208 | n02099601 209 | n02099712 210 | n02099849 211 | n02100236 212 | n02100583 213 | n02100735 214 | n02100877 215 | n02101006 216 | n02101388 217 | n02101556 218 | n02102040 219 | n02102177 220 | n02102318 221 | n02102480 222 | n02102973 223 | n02104029 224 | n02104365 225 | n02105056 226 | n02105162 227 | n02105251 228 | n02105412 229 | n02105505 230 | n02105641 231 | n02105855 232 | n02106030 233 | n02106166 234 | n02106382 235 | n02106550 236 | n02106662 237 | n02107142 238 | n02107312 239 | n02107574 240 | n02107683 241 | n02107908 242 | n02108000 243 | n02108089 244 | n02108422 245 | n02108551 246 | n02108915 247 | n02109047 248 | n02109525 249 | n02109961 250 | n02110063 251 | n02110185 252 | n02110341 253 | n02110627 254 | n02110806 255 | n02110958 256 | n02111129 257 | n02111277 258 | n02111500 259 | n02111889 260 | n02112018 261 | n02112137 262 | n02112350 263 | n02112706 264 | n02113023 265 | n02113186 266 | n02113624 267 | n02113712 268 | n02113799 269 | n02113978 270 | n02114367 271 | n02114548 272 | n02114712 273 | n02114855 274 | n02115641 275 | n02115913 276 | n02116738 277 | n02117135 278 | n02119022 279 | n02119789 280 | n02120079 281 | n02120505 282 | n02123045 283 | n02123159 284 | n02123394 285 | n02123597 286 | n02124075 287 | n02125311 288 | n02127052 289 | n02128385 290 | n02128757 291 | n02128925 292 | n02129165 293 | n02129604 294 | n02130308 295 | n02132136 296 | n02133161 297 | n02134084 298 | n02134418 299 | n02137549 300 | n02138441 301 | n02165105 302 | n02165456 303 | n02167151 304 | n02168699 305 | n02169497 306 | n02172182 307 | n02174001 308 | n02177972 309 | n02190166 310 | n02206856 311 | n02219486 312 | n02226429 313 | n02229544 314 | n02231487 315 | n02233338 316 | n02236044 317 | n02256656 318 | n02259212 319 | n02264363 320 | n02268443 321 | n02268853 322 | n02276258 323 | n02277742 324 | n02279972 325 | n02280649 326 | n02281406 327 | n02281787 328 | n02317335 329 | n02319095 330 | n02321529 331 | n02325366 332 | n02326432 333 | n02328150 334 | n02342885 335 | n02346627 336 | n02356798 337 | n02361337 338 | n02363005 339 | n02364673 340 | n02389026 341 | n02391049 342 | n02395406 343 | n02396427 344 | n02397096 345 | n02398521 346 | n02403003 347 | n02408429 348 | n02410509 349 | n02412080 350 | n02415577 351 | n02417914 352 | n02422106 353 | n02422699 354 | n02423022 355 | n02437312 356 | n02437616 357 | n02441942 358 | n02442845 359 | n02443114 360 | n02443484 361 | n02444819 362 | n02445715 363 | n02447366 364 | n02454379 365 | n02457408 366 | n02480495 367 | n02480855 368 | n02481823 369 | n02483362 370 | n02483708 371 | n02484975 372 | n02486261 373 | n02486410 374 | n02487347 375 | n02488291 376 | n02488702 377 | n02489166 378 | n02490219 379 | n02492035 380 | n02492660 381 | n02493509 382 | n02493793 383 | n02494079 384 | n02497673 385 | n02500267 386 | n02504013 387 | n02504458 388 | n02509815 389 | n02510455 390 | n02514041 391 | n02526121 392 | n02536864 393 | n02606052 394 | n02607072 395 | n02640242 396 | n02641379 397 | n02643566 398 | n02655020 399 | n02666196 400 | n02667093 401 | n02669723 402 | n02672831 403 | n02676566 404 | n02687172 405 | n02690373 406 | n02692877 407 | n02699494 408 | n02701002 409 | n02704792 410 | n02708093 411 | n02727426 412 | n02730930 413 | n02747177 414 | n02749479 415 | n02769748 416 | n02776631 417 | n02777292 418 | n02782093 419 | n02783161 420 | n02786058 421 | n02787622 422 | n02788148 423 | n02790996 424 | n02791124 425 | n02791270 426 | n02793495 427 | n02794156 428 | n02795169 429 | n02797295 430 | n02799071 431 | n02802426 432 | n02804414 433 | n02804610 434 | n02807133 435 | n02808304 436 | n02808440 437 | n02814533 438 | n02814860 439 | n02815834 440 | n02817516 441 | n02823428 442 | n02823750 443 | n02825657 444 | n02834397 445 | n02835271 446 | n02837789 447 | n02840245 448 | n02841315 449 | n02843684 450 | n02859443 451 | n02860847 452 | n02865351 453 | n02869837 454 | n02870880 455 | n02871525 456 | n02877765 457 | n02879718 458 | n02883205 459 | n02892201 460 | n02892767 461 | n02894605 462 | n02895154 463 | n02906734 464 | n02909870 465 | n02910353 466 | n02916936 467 | n02917067 468 | n02927161 469 | n02930766 470 | n02939185 471 | n02948072 472 | n02950826 473 | n02951358 474 | n02951585 475 | n02963159 476 | n02965783 477 | n02966193 478 | n02966687 479 | n02971356 480 | n02974003 481 | n02977058 482 | n02978881 483 | n02979186 484 | n02980441 485 | n02981792 486 | n02988304 487 | n02992211 488 | n02992529 489 | n02999410 490 | n03000134 491 | n03000247 492 | n03000684 493 | n03014705 494 | n03016953 495 | n03017168 496 | n03018349 497 | n03026506 498 | n03028079 499 | n03032252 500 | n03041632 501 | n03042490 502 | n03045698 503 | n03047690 504 | n03062245 505 | n03063599 506 | n03063689 507 | n03065424 508 | n03075370 509 | n03085013 510 | n03089624 511 | n03095699 512 | n03100240 513 | n03109150 514 | n03110669 515 | n03124043 516 | n03124170 517 | n03125729 518 | n03126707 519 | n03127747 520 | n03127925 521 | n03131574 522 | n03133878 523 | n03134739 524 | n03141823 525 | n03146219 526 | n03160309 527 | n03179701 528 | n03180011 529 | n03187595 530 | n03188531 531 | n03196217 532 | n03197337 533 | n03201208 534 | n03207743 535 | n03207941 536 | n03208938 537 | n03216828 538 | n03218198 539 | n03220513 540 | n03223299 541 | n03240683 542 | n03249569 543 | n03250847 544 | n03255030 545 | n03259280 546 | n03271574 547 | n03272010 548 | n03272562 549 | n03290653 550 | n03291819 551 | n03297495 552 | n03314780 553 | n03325584 554 | n03337140 555 | n03344393 556 | n03345487 557 | n03347037 558 | n03355925 559 | n03372029 560 | n03376595 561 | n03379051 562 | n03384352 563 | n03388043 564 | n03388183 565 | n03388549 566 | n03393912 567 | n03394916 568 | n03400231 569 | n03404251 570 | n03417042 571 | n03424325 572 | n03425413 573 | n03443371 574 | n03444034 575 | n03445777 576 | n03445924 577 | n03447447 578 | n03447721 579 | n03450230 580 | n03452741 581 | n03457902 582 | n03459775 583 | n03461385 584 | n03467068 585 | n03476684 586 | n03476991 587 | n03478589 588 | n03481172 589 | n03482405 590 | n03483316 591 | n03485407 592 | n03485794 593 | n03492542 594 | n03494278 595 | n03495258 596 | n03496892 597 | n03498962 598 | n03527444 599 | n03529860 600 | n03530642 601 | n03532672 602 | n03534580 603 | n03535780 604 | n03538406 605 | n03544143 606 | n03584254 607 | n03584829 608 | n03590841 609 | n03594734 610 | n03594945 611 | n03595614 612 | n03598930 613 | n03599486 614 | n03602883 615 | n03617480 616 | n03623198 617 | n03627232 618 | n03630383 619 | n03633091 620 | n03637318 621 | n03642806 622 | n03649909 623 | n03657121 624 | n03658185 625 | n03661043 626 | n03662601 627 | n03666591 628 | n03670208 629 | n03673027 630 | n03676483 631 | n03680355 632 | n03690938 633 | n03691459 634 | n03692522 635 | n03697007 636 | n03706229 637 | n03709823 638 | n03710193 639 | n03710637 640 | n03710721 641 | n03717622 642 | n03720891 643 | n03721384 644 | n03724870 645 | n03729826 646 | n03733131 647 | n03733281 648 | n03733805 649 | n03742115 650 | n03743016 651 | n03759954 652 | n03761084 653 | n03763968 654 | n03764736 655 | n03769881 656 | n03770439 657 | n03770679 658 | n03773504 659 | n03775071 660 | n03775546 661 | n03776460 662 | n03777568 663 | n03777754 664 | n03781244 665 | n03782006 666 | n03785016 667 | n03786901 668 | n03787032 669 | n03788195 670 | n03788365 671 | n03791053 672 | n03792782 673 | n03792972 674 | n03793489 675 | n03794056 676 | n03796401 677 | n03803284 678 | n03804744 679 | n03814639 680 | n03814906 681 | n03825788 682 | n03832673 683 | n03837869 684 | n03838899 685 | n03840681 686 | n03841143 687 | n03843555 688 | n03854065 689 | n03857828 690 | n03866082 691 | n03868242 692 | n03868863 693 | n03871628 694 | n03873416 695 | n03874293 696 | n03874599 697 | n03876231 698 | n03877472 699 | n03877845 700 | n03884397 701 | n03887697 702 | n03888257 703 | n03888605 704 | n03891251 705 | n03891332 706 | n03895866 707 | n03899768 708 | n03902125 709 | n03903868 710 | n03908618 711 | n03908714 712 | n03916031 713 | n03920288 714 | n03924679 715 | n03929660 716 | n03929855 717 | n03930313 718 | n03930630 719 | n03933933 720 | n03935335 721 | n03937543 722 | n03938244 723 | n03942813 724 | n03944341 725 | n03947888 726 | n03950228 727 | n03954731 728 | n03956157 729 | n03958227 730 | n03961711 731 | n03967562 732 | n03970156 733 | n03976467 734 | n03976657 735 | n03977966 736 | n03980874 737 | n03982430 738 | n03983396 739 | n03991062 740 | n03992509 741 | n03995372 742 | n03998194 743 | n04004767 744 | n04005630 745 | n04008634 746 | n04009552 747 | n04019541 748 | n04023962 749 | n04026417 750 | n04033901 751 | n04033995 752 | n04037443 753 | n04039381 754 | n04040759 755 | n04041544 756 | n04044716 757 | n04049303 758 | n04065272 759 | n04067472 760 | n04069434 761 | n04070727 762 | n04074963 763 | n04081281 764 | n04086273 765 | n04090263 766 | n04099969 767 | n04111531 768 | n04116512 769 | n04118538 770 | n04118776 771 | n04120489 772 | n04125021 773 | n04127249 774 | n04131690 775 | n04133789 776 | n04136333 777 | n04141076 778 | n04141327 779 | n04141975 780 | n04146614 781 | n04147183 782 | n04149813 783 | n04152593 784 | n04153751 785 | n04154565 786 | n04162706 787 | n04179913 788 | n04192698 789 | n04200800 790 | n04201297 791 | n04204238 792 | n04204347 793 | n04208210 794 | n04209133 795 | n04209239 796 | n04228054 797 | n04229816 798 | n04235860 799 | n04238763 800 | n04239074 801 | n04243546 802 | n04251144 803 | n04252077 804 | n04252225 805 | n04254120 806 | n04254680 807 | n04254777 808 | n04258138 809 | n04259630 810 | n04263257 811 | n04264628 812 | n04265275 813 | n04266014 814 | n04270147 815 | n04273569 816 | n04275548 817 | n04277352 818 | n04285008 819 | n04286575 820 | n04296562 821 | n04310018 822 | n04311004 823 | n04311174 824 | n04317175 825 | n04325704 826 | n04326547 827 | n04328186 828 | n04330267 829 | n04332243 830 | n04335435 831 | n04336792 832 | n04344873 833 | n04346328 834 | n04347754 835 | n04350905 836 | n04355338 837 | n04355933 838 | n04356056 839 | n04357314 840 | n04366367 841 | n04367480 842 | n04370456 843 | n04371430 844 | n04371774 845 | n04372370 846 | n04376876 847 | n04380533 848 | n04389033 849 | n04392985 850 | n04398044 851 | n04399382 852 | n04404412 853 | n04409515 854 | n04417672 855 | n04418357 856 | n04423845 857 | n04428191 858 | n04429376 859 | n04435653 860 | n04442312 861 | n04443257 862 | n04447861 863 | n04456115 864 | n04458633 865 | n04461696 866 | n04462240 867 | n04465501 868 | n04467665 869 | n04476259 870 | n04479046 871 | n04482393 872 | n04483307 873 | n04485082 874 | n04486054 875 | n04487081 876 | n04487394 877 | n04493381 878 | n04501370 879 | n04505470 880 | n04507155 881 | n04509417 882 | n04515003 883 | n04517823 884 | n04522168 885 | n04523525 886 | n04525038 887 | n04525305 888 | n04532106 889 | n04532670 890 | n04536866 891 | n04540053 892 | n04542943 893 | n04548280 894 | n04548362 895 | n04550184 896 | n04552348 897 | n04553703 898 | n04554684 899 | n04557648 900 | n04560804 901 | n04562935 902 | n04579145 903 | n04579432 904 | n04584207 905 | n04589890 906 | n04590129 907 | n04591157 908 | n04591713 909 | n04592741 910 | n04596742 911 | n04597913 912 | n04599235 913 | n04604644 914 | n04606251 915 | n04612504 916 | n04613696 917 | n06359193 918 | n06596364 919 | n06785654 920 | n06794110 921 | n06874185 922 | n07248320 923 | n07565083 924 | n07579787 925 | n07583066 926 | n07584110 927 | n07590611 928 | n07613480 929 | n07614500 930 | n07615774 931 | n07684084 932 | n07693725 933 | n07695742 934 | n07697313 935 | n07697537 936 | n07711569 937 | n07714571 938 | n07714990 939 | n07715103 940 | n07716358 941 | n07716906 942 | n07717410 943 | n07717556 944 | n07718472 945 | n07718747 946 | n07720875 947 | n07730033 948 | n07734744 949 | n07742313 950 | n07745940 951 | n07747607 952 | n07749582 953 | n07753113 954 | n07753275 955 | n07753592 956 | n07754684 957 | n07760859 958 | n07768694 959 | n07802026 960 | n07831146 961 | n07836838 962 | n07860988 963 | n07871810 964 | n07873807 965 | n07875152 966 | n07880968 967 | n07892512 968 | n07920052 969 | n07930864 970 | n07932039 971 | n09193705 972 | n09229709 973 | n09246464 974 | n09256479 975 | n09288635 976 | n09332890 977 | n09399592 978 | n09421951 979 | n09428293 980 | n09468604 981 | n09472597 982 | n09835506 983 | n10148035 984 | n10565667 985 | n11879895 986 | n11939491 987 | n12057211 988 | n12144580 989 | n12267677 990 | n12620546 991 | n12768682 992 | n12985857 993 | n12998815 994 | n13037406 995 | n13040303 996 | n13044778 997 | n13052670 998 | n13054560 999 | n13133613 1000 | n15075141 -------------------------------------------------------------------------------- /examples/imagenet_eval.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function, division, absolute_import 2 | import argparse 3 | import os 4 | import shutil 5 | import time 6 | 7 | import torch 8 | import torch.nn as nn 9 | import torch.nn.parallel 10 | import torch.backends.cudnn as cudnn 11 | import torch.optim 12 | import torch.utils.data 13 | import torchvision.transforms as transforms 14 | import torchvision.datasets as datasets 15 | 16 | import sys 17 | 18 | sys.path.append('.') 19 | import pretrainedmodels 20 | import pretrainedmodels.utils 21 | 22 | model_names = sorted(name for name in pretrainedmodels.__dict__ 23 | if not name.startswith("__") 24 | and name.islower() 25 | and callable(pretrainedmodels.__dict__[name])) 26 | 27 | parser = argparse.ArgumentParser(description='PyTorch ImageNet Training') 28 | parser.add_argument('--data', metavar='DIR', default="path_to_imagenet", 29 | help='path to dataset') 30 | parser.add_argument('--arch', '-a', metavar='ARCH', default='nasnetamobile', 31 | choices=model_names, 32 | help='model architecture: ' + 33 | ' | '.join(model_names) + 34 | ' (default: fbresnet152)') 35 | parser.add_argument('-j', '--workers', default=4, type=int, metavar='N', 36 | help='number of data loading workers (default: 4)') 37 | parser.add_argument('--epochs', default=90, type=int, metavar='N', 38 | help='number of total epochs to run') 39 | parser.add_argument('--start-epoch', default=0, type=int, metavar='N', 40 | help='manual epoch number (useful on restarts)') 41 | parser.add_argument('-b', '--batch-size', default=1256, type=int, 42 | metavar='N', help='mini-batch size (default: 256)') 43 | parser.add_argument('--lr', '--learning-rate', default=0.1, type=float, 44 | metavar='LR', help='initial learning rate') 45 | parser.add_argument('--momentum', default=0.9, type=float, metavar='M', 46 | help='momentum') 47 | parser.add_argument('--weight-decay', '--wd', default=1e-4, type=float, 48 | metavar='W', help='weight decay (default: 1e-4)') 49 | parser.add_argument('--print-freq', '-p', default=10, type=int, 50 | metavar='N', help='print frequency (default: 10)') 51 | parser.add_argument('--resume', default='', type=str, metavar='PATH', 52 | help='path to latest checkpoint (default: none)') 53 | parser.add_argument('-e', '--evaluate', dest='evaluate', default=True, 54 | action='store_true', help='evaluate model on validation set') 55 | parser.add_argument('--pretrained', default='imagenet', help='use pre-trained model') 56 | parser.add_argument('--do-not-preserve-aspect-ratio', 57 | dest='preserve_aspect_ratio', 58 | help='do not preserve the aspect ratio when resizing an image', 59 | action='store_false') 60 | parser.set_defaults(preserve_aspect_ratio=True) 61 | best_prec1 = 0 62 | 63 | 64 | def main(): 65 | global args, best_prec1 66 | args = parser.parse_args() 67 | 68 | # create model 69 | print("=> creating model '{}'".format(args.arch)) 70 | if args.pretrained.lower() not in ['false', 'none', 'not', 'no', '0']: 71 | print("=> using pre-trained parameters '{}'".format(args.pretrained)) 72 | model = pretrainedmodels.__dict__[args.arch](num_classes=1000, 73 | pretrained=args.pretrained) 74 | else: 75 | model = pretrainedmodels.__dict__[args.arch]() 76 | 77 | # optionally resume from a checkpoint 78 | if args.resume: 79 | if os.path.isfile(args.resume): 80 | print("=> loading checkpoint '{}'".format(args.resume)) 81 | checkpoint = torch.load(args.resume) 82 | args.start_epoch = checkpoint['epoch'] 83 | best_prec1 = checkpoint['best_prec1'] 84 | model.load_state_dict(checkpoint['state_dict']) 85 | print("=> loaded checkpoint '{}' (epoch {})" 86 | .format(args.resume, checkpoint['epoch'])) 87 | else: 88 | print("=> no checkpoint found at '{}'".format(args.resume)) 89 | 90 | cudnn.benchmark = True 91 | 92 | # Data loading code 93 | # traindir = os.path.join(args.data, 'train') 94 | valdir = os.path.join(args.data, 'val') 95 | 96 | # train_loader = torch.utils.data.DataLoader( 97 | # datasets.ImageFolder(traindir, transforms.Compose([ 98 | # transforms.RandomSizedCrop(max(model.input_size)), 99 | # transforms.RandomHorizontalFlip(), 100 | # transforms.ToTensor(), 101 | # normalize, 102 | # ])), 103 | # batch_size=args.batch_size, shuffle=True, 104 | # num_workers=args.workers, pin_memory=True) 105 | 106 | 107 | 108 | # if 'scale' in pretrainedmodels.pretrained_settings[args.arch][args.pretrained]: 109 | # scale = pretrainedmodels.pretrained_settings[args.arch][args.pretrained]['scale'] 110 | # else: 111 | # scale = 0.875 112 | scale = 0.875 113 | 114 | print('Images transformed from size {} to {}'.format( 115 | int(round(max(model.input_size) / scale)), 116 | model.input_size)) 117 | 118 | val_tf = pretrainedmodels.utils.TransformImage( 119 | model, 120 | scale=scale, 121 | preserve_aspect_ratio=args.preserve_aspect_ratio 122 | ) 123 | 124 | val_loader = torch.utils.data.DataLoader( 125 | datasets.ImageFolder(valdir, val_tf), 126 | batch_size=args.batch_size, shuffle=False, 127 | num_workers=args.workers, pin_memory=True) 128 | 129 | # define loss function (criterion) and optimizer 130 | criterion = nn.CrossEntropyLoss().cuda() 131 | 132 | optimizer = torch.optim.SGD(model.parameters(), args.lr, 133 | momentum=args.momentum, 134 | weight_decay=args.weight_decay) 135 | 136 | model = torch.nn.DataParallel(model).cuda() 137 | 138 | if args.evaluate: 139 | validate(val_loader, model, criterion) 140 | return 141 | 142 | for epoch in range(args.start_epoch, args.epochs): 143 | adjust_learning_rate(optimizer, epoch) 144 | 145 | # train for one epoch 146 | train(train_loader, model, criterion, optimizer, epoch) 147 | 148 | # evaluate on validation set 149 | prec1 = validate(val_loader, model, criterion) 150 | 151 | # remember best prec@1 and save checkpoint 152 | is_best = prec1 > best_prec1 153 | best_prec1 = max(prec1, best_prec1) 154 | save_checkpoint({ 155 | 'epoch': epoch + 1, 156 | 'arch': args.arch, 157 | 'state_dict': model.state_dict(), 158 | 'best_prec1': best_prec1, 159 | }, is_best) 160 | 161 | 162 | def train(train_loader, model, criterion, optimizer, epoch): 163 | batch_time = AverageMeter() 164 | data_time = AverageMeter() 165 | losses = AverageMeter() 166 | top1 = AverageMeter() 167 | top5 = AverageMeter() 168 | 169 | # switch to train mode 170 | model.train() 171 | 172 | end = time.time() 173 | for i, (input, target) in enumerate(train_loader): 174 | # measure data loading time 175 | data_time.update(time.time() - end) 176 | 177 | target = target.cuda() 178 | input_var = torch.autograd.Variable(input) 179 | target_var = torch.autograd.Variable(target) 180 | 181 | # compute output 182 | output = model(input_var) 183 | loss = criterion(output, target_var) 184 | 185 | # measure accuracy and record loss 186 | prec1, prec5 = accuracy(output.data, target, topk=(1, 5)) 187 | losses.update(loss.data[0], input.size(0)) 188 | top1.update(prec1[0], input.size(0)) 189 | top5.update(prec5[0], input.size(0)) 190 | 191 | # compute gradient and do SGD step 192 | optimizer.zero_grad() 193 | loss.backward() 194 | optimizer.step() 195 | 196 | # measure elapsed time 197 | batch_time.update(time.time() - end) 198 | end = time.time() 199 | 200 | if i % args.print_freq == 0: 201 | print('Epoch: [{0}][{1}/{2}]\t' 202 | 'Time {batch_time.val:.3f} ({batch_time.avg:.3f})\t' 203 | 'Data {data_time.val:.3f} ({data_time.avg:.3f})\t' 204 | 'Loss {loss.val:.4f} ({loss.avg:.4f})\t' 205 | 'Acc@1 {top1.val:.3f} ({top1.avg:.3f})\t' 206 | 'Acc@5 {top5.val:.3f} ({top5.avg:.3f})'.format( 207 | epoch, i, len(train_loader), batch_time=batch_time, 208 | data_time=data_time, loss=losses, top1=top1, top5=top5)) 209 | 210 | 211 | def validate(val_loader, model, criterion): 212 | with torch.no_grad(): 213 | batch_time = AverageMeter() 214 | losses = AverageMeter() 215 | top1 = AverageMeter() 216 | top5 = AverageMeter() 217 | 218 | # switch to evaluate mode 219 | model.eval() 220 | 221 | end = time.time() 222 | for i, (input, target) in enumerate(val_loader): 223 | target = target.cuda() 224 | input = input.cuda() 225 | 226 | # compute output 227 | output = model(input) 228 | loss = criterion(output, target) 229 | 230 | # measure accuracy and record loss 231 | prec1, prec5 = accuracy(output.data, target.data, topk=(1, 5)) 232 | losses.update(loss.data.item(), input.size(0)) 233 | top1.update(prec1.item(), input.size(0)) 234 | top5.update(prec5.item(), input.size(0)) 235 | 236 | # measure elapsed time 237 | batch_time.update(time.time() - end) 238 | end = time.time() 239 | 240 | if i % args.print_freq == 0: 241 | print('Test: [{0}/{1}]\t' 242 | 'Time {batch_time.val:.3f} ({batch_time.avg:.3f})\t' 243 | 'Loss {loss.val:.4f} ({loss.avg:.4f})\t' 244 | 'Acc@1 {top1.val:.3f} ({top1.avg:.3f})\t' 245 | 'Acc@5 {top5.val:.3f} ({top5.avg:.3f})'.format( 246 | i, len(val_loader), batch_time=batch_time, loss=losses, 247 | top1=top1, top5=top5)) 248 | 249 | print(' * Acc@1 {top1.avg:.3f} Acc@5 {top5.avg:.3f}' 250 | .format(top1=top1, top5=top5)) 251 | 252 | return top1.avg, top5.avg 253 | 254 | 255 | def save_checkpoint(state, is_best, filename='checkpoint.pth.tar'): 256 | torch.save(state, filename) 257 | if is_best: 258 | shutil.copyfile(filename, 'model_best.pth.tar') 259 | 260 | 261 | class AverageMeter(object): 262 | """Computes and stores the average and current value""" 263 | 264 | def __init__(self): 265 | self.reset() 266 | 267 | def reset(self): 268 | self.val = 0 269 | self.avg = 0 270 | self.sum = 0 271 | self.count = 0 272 | 273 | def update(self, val, n=1): 274 | self.val = val 275 | self.sum += val * n 276 | self.count += n 277 | self.avg = self.sum / self.count 278 | 279 | 280 | def adjust_learning_rate(optimizer, epoch): 281 | """Sets the learning rate to the initial LR decayed by 10 every 30 epochs""" 282 | lr = args.lr * (0.1 ** (epoch // 30)) 283 | for param_group in optimizer.param_groups: 284 | param_group['lr'] = lr 285 | 286 | 287 | def accuracy(output, target, topk=(1,)): 288 | """Computes the precision@k for the specified values of k""" 289 | maxk = max(topk) 290 | batch_size = target.size(0) 291 | 292 | _, pred = output.topk(maxk, 1, True, True) 293 | pred = pred.t() 294 | correct = pred.eq(target.view(1, -1).expand_as(pred)) 295 | 296 | res = [] 297 | for k in topk: 298 | correct_k = correct[:k].view(-1).float().sum(0) 299 | res.append(correct_k.mul_(100.0 / batch_size)) 300 | return res 301 | 302 | 303 | if __name__ == '__main__': 304 | main() -------------------------------------------------------------------------------- /examples/imagenet_logits.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function, division, absolute_import 2 | import argparse 3 | 4 | from PIL import Image 5 | import torch 6 | import torchvision.transforms as transforms 7 | 8 | import sys 9 | sys.path.append('.') 10 | import pretrainedmodels 11 | import pretrainedmodels.utils as utils 12 | 13 | model_names = sorted(name for name in pretrainedmodels.__dict__ 14 | if not name.startswith("__") 15 | and name.islower() 16 | and callable(pretrainedmodels.__dict__[name])) 17 | 18 | parser = argparse.ArgumentParser(description='PyTorch ImageNet Training') 19 | parser.add_argument('--arch', '-a', metavar='ARCH', default='nasnetalarge', 20 | choices=model_names, 21 | help='model architecture: ' + 22 | ' | '.join(model_names) + 23 | ' (default: nasnetalarge)', 24 | nargs='+') 25 | parser.add_argument('--path_img', type=str, default='data/cat.jpg') 26 | 27 | def main(): 28 | global args 29 | args = parser.parse_args() 30 | 31 | for arch in args.arch: 32 | # Load Model 33 | model = pretrainedmodels.__dict__[arch](num_classes=1000, 34 | pretrained='imagenet') 35 | model.eval() 36 | 37 | path_img = args.path_img 38 | # Load and Transform one input image 39 | load_img = utils.LoadImage() 40 | tf_img = utils.TransformImage(model) 41 | 42 | input_data = load_img(args.path_img) # 3x400x225 43 | input_data = tf_img(input_data) # 3x299x299 44 | input_data = input_data.unsqueeze(0) # 1x3x299x299 45 | input = torch.autograd.Variable(input_data) 46 | 47 | # Load Imagenet Synsets 48 | with open('data/imagenet_synsets.txt', 'r') as f: 49 | synsets = f.readlines() 50 | 51 | # len(synsets)==1001 52 | # sysnets[0] == background 53 | synsets = [x.strip() for x in synsets] 54 | splits = [line.split(' ') for line in synsets] 55 | key_to_classname = {spl[0]:' '.join(spl[1:]) for spl in splits} 56 | 57 | with open('data/imagenet_classes.txt', 'r') as f: 58 | class_id_to_key = f.readlines() 59 | 60 | class_id_to_key = [x.strip() for x in class_id_to_key] 61 | 62 | # Make predictions 63 | output = model(input) # size(1, 1000) 64 | max, argmax = output.data.squeeze().max(0) 65 | class_id = argmax[0] 66 | class_key = class_id_to_key[class_id] 67 | classname = key_to_classname[class_key] 68 | 69 | print("'{}': '{}' is a '{}'".format(arch, path_img, classname)) 70 | 71 | if __name__ == '__main__': 72 | main() 73 | -------------------------------------------------------------------------------- /examples/visu_arch.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function, division, absolute_import 2 | import os 3 | 4 | import torch # http://pytorch.org/about/ 5 | from torch.autograd import Variable 6 | from torch.utils import model_zoo 7 | 8 | import torchvision # https://github.com/pytorch/vision 9 | import torchvision.models as models 10 | import torchvision.transforms as transforms 11 | 12 | from lib.voc import Voc2007Classification 13 | from lib.util import load_imagenet_classes 14 | 15 | model_urls = { 16 | # Alexnet 17 | # Paper: https://papers.nips.cc/paper/4824-imagenet-classification-with-deep-convolutional-neural-networks.pdf 18 | # https://github.com/pytorch/vision/blob/master/torchvision/models/alexnet.py 19 | 'alexnet': 'https://download.pytorch.org/models/alexnet-owt-4df8aa71.pth', 20 | # VGG 21 | # Paper: https://arxiv.org/abs/1409.1556 22 | # https://github.com/pytorch/vision/blob/master/torchvision/models/vgg.py 23 | 'vgg16': 'https://download.pytorch.org/models/vgg16-397923af.pth', 24 | # VGG BatchNorm 25 | # Paper: https://arxiv.org/abs/1502.03167 26 | # https://github.com/pytorch/vision/blob/master/torchvision/models/vgg.py 27 | 'vgg16_bn': 'https://download.pytorch.org/models/vgg16_bn-6c64b313.pth', 28 | # Inception 29 | # Paper: https://arxiv.org/abs/1602.07261 30 | # https://github.com/pytorch/vision/blob/master/torchvision/models/inception.py 31 | 'inception_v3': 'https://download.pytorch.org/models/inception_v3_google-1a9a5a14.pth', 32 | # Resnet 33 | # Paper: https://arxiv.org/abs/1512.03385 34 | # https://github.com/pytorch/vision/blob/master/torchvision/models/resnet.py 35 | 'resnet18': 'https://download.pytorch.org/models/resnet18-5c106cde.pth', 36 | 'resnet50': 'https://download.pytorch.org/models/resnet50-19c8e357.pth', 37 | 'resnet152': 'https://download.pytorch.org/models/resnet152-b121ed2d.pth' 38 | } 39 | 40 | if __name__ == '__main__': 41 | 42 | model_name = 'alexnet' 43 | 44 | dir_datasets = '/home/sasl/shared/EI-SE5-CS/datasets' # '/tmp/torch/datasets' 45 | dir_models = '/home/sasl/shared/EI-SE5-CS/models' # '/tmp/torch/models' 46 | dir_outputs = '/tmp/outputs/' + model_name 47 | 48 | print('Create network') 49 | model = models.__dict__[model_name]() # https://stackoverflow.com/questions/19907442/python-explain-dict-attribute 50 | model.eval() # http://pytorch.org/docs/master/nn.html?highlight=eval#torch.nn.Module.eval 51 | print('') 52 | 53 | ########################################################################## 54 | 55 | print('Display modules') 56 | print(model) 57 | print('') 58 | 59 | ########################################################################## 60 | 61 | print('Display parameters') 62 | state_dict = model.state_dict() # http://pytorch.org/docs/master/_modules/torch/nn/modules/module.html#Module.state_dict 63 | for key, value in state_dict.items(): 64 | print(key, value.size()) 65 | print('') 66 | 67 | print('Display features.0.weight') 68 | print(state_dict['features.0.weight']) 69 | print('') 70 | 71 | ########################################################################## 72 | 73 | print('Display inputs/outputs') 74 | 75 | def print_info(self, input, output): 76 | print('Inside '+ self.__class__.__name__+ ' forward') 77 | print('input size', input[0].size()) 78 | print('output size', output.data.size()) 79 | print('') 80 | 81 | handles = [] 82 | for m in model.features: 83 | handles.append(m.register_forward_hook(print_info)) # http://pytorch.org/docs/master/_modules/torch/nn/modules/module.html#Module.register_forward_pre_hook 84 | 85 | for m in model.classifier: 86 | handles.append(m.register_forward_hook(print_info)) 87 | 88 | input = Variable(torch.randn(1,3,224,224).float(), requires_grad=False) # http://pytorch.org/tutorials/beginner/blitz/autograd_tutorial.html#sphx-glr-beginner-blitz-autograd-tutorial-py 89 | output = model(input) # model(input) calls model.__call__(input) which calls model.forward(hook) and then calls the hooks 90 | 91 | for h in handles: 92 | h.remove() # to remove the hooks 93 | 94 | print('') 95 | 96 | ########################################################################## 97 | 98 | print('Load dataset Voc2007') 99 | 100 | train_data = Voc2007Classification(dir_datasets, 'train') # or val, test, trainval 101 | 102 | print('Voc2007 trainset has {} images'.format(len(train_data))) 103 | 104 | print('Voc2007 has {} classes'.format(len(train_data.classes))) 105 | print(train_data.classes) 106 | 107 | item = train_data[0] # train_data contains a list of items (image, name, target) 108 | img_data = item[0] # PIL.Image.Image 109 | img_name = item[1] # string 110 | target = item[2] # torch.Tensor of size=20 (=nb_classes), contains 3 values: -1 (absence of class), 1 (presence of class), 0 (hard example) 111 | 112 | os.system('mkdir -p ' + dir_outputs) # create a directory 113 | path_img = os.path.join(dir_outputs, img_name+'.png') 114 | img_data.save(path_img) # save image using PIL 115 | 116 | print('Write image to ' + path_img) 117 | for class_id, has_class in enumerate(target): 118 | if has_class == 1: 119 | print('image {} has object of class {}'.format(img_name, train_data.classes[class_id])) 120 | 121 | ########################################################################## 122 | 123 | print('Load pretrained model on Imagenet') 124 | model.load_state_dict(model_zoo.load_url(model_urls[model_name], 125 | model_dir=dir_models)) 126 | 127 | print('Display predictions') 128 | 129 | tf = transforms.Compose([ 130 | transforms.Scale(224), # rescale an RGB image to size 224^ (not a square) 131 | transforms.CenterCrop(224), # extract a square of size 224 at the center of the image 132 | transforms.ToTensor(), # convert the PIL.Image into a torch.Tensor 133 | transforms.Normalize( 134 | mean=[0.485, 0.456, 0.406], # mean pixel value per channel 135 | std=[0.229, 0.224, 0.225] # standard deviation value per channel 136 | ) 137 | ]) 138 | 139 | input_data = tf(img_data) 140 | input_data = input_data.unsqueeze(0) # (3,224,224) -> (1,3,224,224) 141 | print('input size', input_data.size()) 142 | print(input_data) 143 | 144 | input = Variable(input_data, requires_grad=False) 145 | output = model(input) 146 | 147 | print('output size', output.data.size()) 148 | print(output.data) 149 | 150 | # Load Imagenet Synsets 151 | imagenet_classes = load_imagenet_classes() 152 | print('Imagenet has {} classes'.format(imagenet_classes)) 153 | 154 | max, argmax = output.data.squeeze().max(0) 155 | class_id = argmax[0] 156 | print('Image {} is of class "{}"'.format(img_name, imagenet_classes[class_id])) 157 | 158 | ############################################################################# 159 | 160 | print('Save normalized input as RGB image') 161 | 162 | dir_activations = os.path.join(dir_outputs,'activations') 163 | os.system('mkdir -p ' + dir_activations) 164 | 165 | path_img_input = os.path.join(dir_activations, 'input.png') 166 | print('save input activation to ' + path_img_input) 167 | transforms.ToPILImage()(input_data[0]).save(path_img_input) # save image using PIL 168 | 169 | print('') 170 | 171 | ############################################################################# 172 | 173 | print('Save activations as Gray images') 174 | 175 | layer_id = 0 176 | 177 | def save_activation(self, input, output): 178 | global layer_id 179 | 180 | for i in range(10):#output.data.size(1)): 181 | path_img_output = os.path.join(dir_activations, 'layer{}_{}_channel{}.png'.format(layer_id, self.__class__.__name__, i)) 182 | print('save output activation to ' + path_img_output) 183 | torchvision.utils.save_image(output.data.squeeze(0)[i], path_img_output) # save image (of type Tensor) using torchvision 184 | 185 | layer_id += 1 186 | 187 | handles = [] 188 | for m in model.features: 189 | handles.append(m.register_forward_hook(save_activation)) 190 | 191 | input = Variable(input_data, requires_grad=False) 192 | output = model(input) 193 | 194 | for h in handles: 195 | h.remove() 196 | 197 | print('') 198 | 199 | ############################################################################# 200 | 201 | dir_parameters = os.path.join(dir_outputs, 'parameters') 202 | os.system('mkdir -p ' + dir_parameters) 203 | state_dict = model.state_dict() 204 | 205 | print('Save first layer parameters as RGB images') 206 | 207 | weight = state_dict['features.0.weight'] 208 | for filter_id in range(weight.size(0)): 209 | path_param = os.path.join(dir_parameters, 'features.0.weight_filter{}.png'.format(filter_id)) 210 | print('save ' + path_param) 211 | torchvision.utils.save_image(weight[filter_id], path_param) 212 | 213 | print('') 214 | 215 | 216 | print('Save other layer parameters as Gray images') 217 | 218 | for key in state_dict: 219 | if 'features' in key and 'weight' in key: 220 | for filter_id in range(3): 221 | for channel_id in range(3): 222 | path_param = os.path.join(dir_parameters, '{}_filter{}_channel{}.png'.format(key, filter_id, channel_id)) 223 | print('save ' + path_param) 224 | torchvision.utils.save_image(state_dict[key][filter_id][channel_id], path_param) 225 | 226 | print('') 227 | 228 | -------------------------------------------------------------------------------- /examples/voc2007_extract.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function, division, absolute_import 2 | import os 3 | import argparse 4 | from tqdm import tqdm 5 | 6 | import torch 7 | from torch.autograd import Variable 8 | from torch.utils import model_zoo 9 | 10 | # http://scikit-learn.org 11 | from sklearn.metrics import accuracy_score 12 | from sklearn.metrics import average_precision_score 13 | from sklearn.svm import LinearSVC 14 | from sklearn.svm import SVC 15 | 16 | import sys 17 | sys.path.append('.') 18 | import pretrainedmodels 19 | import pretrainedmodels.utils 20 | import pretrainedmodels.datasets 21 | 22 | model_names = sorted(name for name in pretrainedmodels.__dict__ 23 | if not name.startswith("__") 24 | and name.islower() 25 | and callable(pretrainedmodels.__dict__[name])) 26 | 27 | def extract_features_targets(model, features_size, loader, path_data, cuda=False): 28 | if os.path.isfile(path_data): 29 | print('Load features from {}'.format(path_data)) 30 | return torch.load(path_data) 31 | 32 | print('\nExtract features on {}set'.format(loader.dataset.set)) 33 | 34 | features = torch.Tensor(len(loader.dataset), features_size) 35 | targets = torch.Tensor(len(loader.dataset), len(loader.dataset.classes)) 36 | 37 | for batch_id, batch in enumerate(tqdm(loader)): 38 | img = batch[0] 39 | target = batch[2] 40 | current_bsize = img.size(0) 41 | from_ = int(batch_id * loader.batch_size) 42 | to_ = int(from_ + current_bsize) 43 | 44 | if cuda: 45 | img = img.cuda(async=True) 46 | 47 | input = Variable(img, requires_grad=False) 48 | output = model(input) 49 | 50 | features[from_:to_] = output.data.cpu() 51 | targets[from_:to_] = target 52 | 53 | os.system('mkdir -p {}'.format(os.path.dirname(path_data))) 54 | print('save ' + path_data) 55 | torch.save((features, targets), path_data) 56 | print('') 57 | return features, targets 58 | 59 | def train_multilabel(features, targets, classes, train_split, test_split, C=1.0, ignore_hard_examples=True, after_ReLU=False, normalize_L2=False): 60 | print('\nHyperparameters:\n - C: {}\n - after_ReLU: {}\n - normL2: {}'.format(C, after_ReLU, normalize_L2)) 61 | train_APs = [] 62 | test_APs = [] 63 | for class_id in range(len(classes)): 64 | 65 | classifier = SVC(C=C, kernel='linear') # http://scikit-learn.org/stable/modules/generated/sklearn.svm.SVC.html 66 | 67 | if ignore_hard_examples: 68 | train_masks = (targets[train_split][:,class_id] != 0).view(-1, 1) 69 | train_features = torch.masked_select(features[train_split], train_masks.expand_as(features[train_split])).view(-1,features[train_split].size(1)) 70 | train_targets = torch.masked_select(targets[train_split], train_masks.expand_as(targets[train_split])).view(-1,targets[train_split].size(1)) 71 | test_masks = (targets[test_split][:,class_id] != 0).view(-1, 1) 72 | test_features = torch.masked_select(features[test_split], test_masks.expand_as(features[test_split])).view(-1,features[test_split].size(1)) 73 | test_targets = torch.masked_select(targets[test_split], test_masks.expand_as(targets[test_split])).view(-1,targets[test_split].size(1)) 74 | else: 75 | train_features = features[train_split] 76 | train_targets = targets[train_split] 77 | test_features = features[test_split] 78 | test_targets = features[test_split] 79 | 80 | if after_ReLU: 81 | train_features[train_features < 0] = 0 82 | test_features[test_features < 0] = 0 83 | 84 | if normalize_L2: 85 | train_norm = torch.norm(train_features, p=2, dim=1).unsqueeze(1) 86 | train_features = train_features.div(train_norm.expand_as(train_features)) 87 | test_norm = torch.norm(test_features, p=2, dim=1).unsqueeze(1) 88 | test_features = test_features.div(test_norm.expand_as(test_features)) 89 | 90 | train_X = train_features.numpy() 91 | train_y = (train_targets[:,class_id] != -1).numpy() # uses hard examples if not ignored 92 | 93 | test_X = test_features.numpy() 94 | test_y = (test_targets[:,class_id] != -1).numpy() 95 | 96 | classifier.fit(train_X, train_y) # train parameters of the classifier 97 | 98 | train_preds = classifier.predict(train_X) 99 | train_acc = accuracy_score(train_y, train_preds) * 100 100 | train_AP = average_precision_score(train_y, train_preds) * 100 101 | train_APs.append(train_AP) 102 | 103 | test_preds = classifier.predict(test_X) 104 | test_acc = accuracy_score(test_y, test_preds) * 100 105 | test_AP = average_precision_score(test_y, test_preds) * 100 106 | test_APs.append(test_AP) 107 | 108 | print('class "{}" ({}/{}):'.format(classes[class_id], test_y.sum(), test_y.shape[0])) 109 | print(' - {:8}: acc {:.2f}, AP {:.2f}'.format(train_split, train_acc, train_AP)) 110 | print(' - {:8}: acc {:.2f}, AP {:.2f}'.format(test_split, test_acc, test_AP)) 111 | 112 | print('all classes:') 113 | print(' - {:8}: mAP {:.4f}'.format(train_split, sum(train_APs)/len(classes))) 114 | print(' - {:8}: mAP {:.4f}'.format(test_split, sum(test_APs)/len(classes))) 115 | 116 | ########################################################################## 117 | # main 118 | ########################################################################## 119 | 120 | parser = argparse.ArgumentParser( 121 | description='Train/Evaluate models', 122 | formatter_class=argparse.ArgumentDefaultsHelpFormatter) 123 | parser.add_argument('--dir_outputs', default='/tmp/outputs', type=str, help='') 124 | parser.add_argument('--dir_datasets', default='/tmp/datasets', type=str, help='') 125 | parser.add_argument('--C', default=1, type=float, help='') 126 | parser.add_argument('-b', '--batch_size', default=50, type=float, help='') 127 | parser.add_argument('-a', '--arch', default='alexnet', choices=model_names, 128 | help='model architecture: ' + 129 | ' | '.join(model_names) + 130 | ' (default: alexnet)') 131 | parser.add_argument('--train_split', default='train', type=str, help='') 132 | parser.add_argument('--test_split', default='val', type=str, help='') 133 | parser.add_argument('--cuda', const=True, nargs='?', type=bool, help='') 134 | 135 | def main (): 136 | global args 137 | args = parser.parse_args() 138 | print('\nCUDA status: {}'.format(args.cuda)) 139 | 140 | print('\nLoad pretrained model on Imagenet') 141 | model = pretrainedmodels.__dict__[args.arch](num_classes=1000, pretrained='imagenet') 142 | model.eval() 143 | if args.cuda: 144 | model.cuda() 145 | 146 | features_size = model.last_linear.in_features 147 | model.last_linear = pretrainedmodels.utils.Identity() # Trick to get inputs (features) from last_linear 148 | 149 | print('\nLoad datasets') 150 | tf_img = pretrainedmodels.utils.TransformImage(model) 151 | train_set = pretrainedmodels.datasets.Voc2007Classification(args.dir_datasets, 'train', transform=tf_img) 152 | val_set = pretrainedmodels.datasets.Voc2007Classification(args.dir_datasets, 'val', transform=tf_img) 153 | test_set = pretrainedmodels.datasets.Voc2007Classification(args.dir_datasets, 'test', transform=tf_img) 154 | 155 | train_loader = torch.utils.data.DataLoader(train_set, batch_size=args.batch_size, shuffle=False, num_workers=2) 156 | val_loader = torch.utils.data.DataLoader(val_set, batch_size=args.batch_size, shuffle=False, num_workers=2) 157 | test_loader = torch.utils.data.DataLoader(test_set, batch_size=args.batch_size, shuffle=False, num_workers=2) 158 | 159 | print('\nLoad features') 160 | dir_features = os.path.join(args.dir_outputs, 'data/{}'.format(args.arch)) 161 | path_train_data = '{}/{}set.pth'.format(dir_features, 'train') 162 | path_val_data = '{}/{}set.pth'.format(dir_features, 'val') 163 | path_test_data = '{}/{}set.pth'.format(dir_features, 'test') 164 | 165 | features = {} 166 | targets = {} 167 | features['train'], targets['train'] = extract_features_targets(model, features_size, train_loader, path_train_data, args.cuda) 168 | features['val'], targets['val'] = extract_features_targets(model, features_size, val_loader, path_val_data, args.cuda) 169 | features['test'], targets['test'] = extract_features_targets(model, features_size, test_loader, path_test_data, args.cuda) 170 | features['trainval'] = torch.cat([features['train'], features['val']], 0) 171 | targets['trainval'] = torch.cat([targets['train'], targets['val']], 0) 172 | 173 | print('\nTrain Support Vector Machines') 174 | if args.train_split == 'train' and args.test_split == 'val': 175 | print('\nHyperparameters search: train multilabel classifiers (on-versus-all) on train/val') 176 | elif args.train_split == 'trainval' and args.test_split == 'test': 177 | print('\nEvaluation: train a multilabel classifier on trainval/test') 178 | else: 179 | raise ValueError('Trying to train on {} and eval on {}'.format(args.train_split, args.test_split)) 180 | 181 | train_multilabel(features, targets, train_set.classes, args.train_split, args.test_split, C=args.C) 182 | 183 | 184 | if __name__ == '__main__': 185 | main() -------------------------------------------------------------------------------- /pretrainedmodels/__init__.py: -------------------------------------------------------------------------------- 1 | from .version import __version__ 2 | 3 | from . import models 4 | from . import datasets 5 | 6 | from .models.utils import pretrained_settings 7 | from .models.utils import model_names 8 | 9 | # to support pretrainedmodels.__dict__['nasnetalarge'] 10 | # but depreciated 11 | from .models.fbresnet import fbresnet152 12 | from .models.cafferesnet import cafferesnet101 13 | from .models.bninception import bninception 14 | from .models.resnext import resnext101_32x4d 15 | from .models.resnext import resnext101_64x4d 16 | from .models.inceptionv4 import inceptionv4 17 | from .models.inceptionresnetv2 import inceptionresnetv2 18 | from .models.nasnet import nasnetalarge 19 | from .models.nasnet_mobile import nasnetamobile 20 | from .models.torchvision_models import alexnet 21 | from .models.torchvision_models import densenet121 22 | from .models.torchvision_models import densenet169 23 | from .models.torchvision_models import densenet201 24 | from .models.torchvision_models import densenet161 25 | from .models.torchvision_models import resnet18 26 | from .models.torchvision_models import resnet34 27 | from .models.torchvision_models import resnet50 28 | from .models.torchvision_models import resnet101 29 | from .models.torchvision_models import resnet152 30 | from .models.torchvision_models import inceptionv3 31 | from .models.torchvision_models import squeezenet1_0 32 | from .models.torchvision_models import squeezenet1_1 33 | from .models.torchvision_models import vgg11 34 | from .models.torchvision_models import vgg11_bn 35 | from .models.torchvision_models import vgg13 36 | from .models.torchvision_models import vgg13_bn 37 | from .models.torchvision_models import vgg16 38 | from .models.torchvision_models import vgg16_bn 39 | from .models.torchvision_models import vgg19_bn 40 | from .models.torchvision_models import vgg19 41 | from .models.dpn import dpn68 42 | from .models.dpn import dpn68b 43 | from .models.dpn import dpn92 44 | from .models.dpn import dpn98 45 | from .models.dpn import dpn131 46 | from .models.dpn import dpn107 47 | from .models.xception import xception 48 | from .models.senet import senet154 49 | from .models.senet import se_resnet50 50 | from .models.senet import se_resnet101 51 | from .models.senet import se_resnet152 52 | from .models.senet import se_resnext50_32x4d 53 | from .models.senet import se_resnext101_32x4d 54 | from .models.pnasnet import pnasnet5large 55 | from .models.polynet import polynet 56 | -------------------------------------------------------------------------------- /pretrainedmodels/datasets/__init__.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function, division, absolute_import 2 | from .voc import Voc2007Classification -------------------------------------------------------------------------------- /pretrainedmodels/datasets/utils.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function, division, absolute_import 2 | import math 3 | from six.moves.urllib.request import urlretrieve 4 | 5 | import torch 6 | from PIL import Image 7 | from tqdm import tqdm 8 | 9 | def load_imagenet_classes(path_synsets='data/imagenet_synsets.txt', 10 | path_classes='data/imagenet_classes.txt'): 11 | with open(path_synsets, 'r') as f: 12 | synsets = f.readlines() 13 | 14 | synsets = [x.strip() for x in synsets] 15 | splits = [line.split(' ') for line in synsets] 16 | key_to_classname = {spl[0]:' '.join(spl[1:]) for spl in splits} 17 | 18 | with open(path_classes, 'r') as f: 19 | class_id_to_key = f.readlines() 20 | 21 | class_id_to_key = [x.strip() for x in class_id_to_key] 22 | 23 | cid_to_cname = [] 24 | for i in range(len(class_id_to_key)): 25 | key = class_id_to_key[i] 26 | cname = key_to_classname[key] 27 | cid_to_cname.append(cname) 28 | 29 | return cid_to_cname 30 | 31 | 32 | class Warp(object): 33 | def __init__(self, size, interpolation=Image.BILINEAR): 34 | self.size = int(size) 35 | self.interpolation = interpolation 36 | 37 | def __call__(self, img): 38 | return img.resize((self.size, self.size), self.interpolation) 39 | 40 | def __str__(self): 41 | return self.__class__.__name__ + ' (size={size}, interpolation={interpolation})'.format(size=self.size, 42 | interpolation=self.interpolation) 43 | 44 | 45 | def download_url(url, destination=None, progress_bar=True): 46 | """Download a URL to a local file. 47 | 48 | Parameters 49 | ---------- 50 | url : str 51 | The URL to download. 52 | destination : str, None 53 | The destination of the file. If None is given the file is saved to a temporary directory. 54 | progress_bar : bool 55 | Whether to show a command-line progress bar while downloading. 56 | 57 | Returns 58 | ------- 59 | filename : str 60 | The location of the downloaded file. 61 | 62 | Notes 63 | ----- 64 | Progress bar use/example adapted from tqdm documentation: https://github.com/tqdm/tqdm 65 | """ 66 | 67 | def my_hook(t): 68 | last_b = [0] 69 | 70 | def inner(b=1, bsize=1, tsize=None): 71 | if tsize is not None: 72 | t.total = tsize 73 | if b > 0: 74 | t.update((b - last_b[0]) * bsize) 75 | last_b[0] = b 76 | 77 | return inner 78 | 79 | if progress_bar: 80 | with tqdm(unit='B', unit_scale=True, miniters=1, desc=url.split('/')[-1]) as t: 81 | filename, _ = urlretrieve(url, filename=destination, reporthook=my_hook(t)) 82 | else: 83 | filename, _ = urlretrieve(url, filename=destination) 84 | 85 | 86 | class AveragePrecisionMeter(object): 87 | """ 88 | The APMeter measures the average precision per class. 89 | The APMeter is designed to operate on `NxK` Tensors `output` and 90 | `target`, and optionally a `Nx1` Tensor weight where (1) the `output` 91 | contains model output scores for `N` examples and `K` classes that ought to 92 | be higher when the model is more convinced that the example should be 93 | positively labeled, and smaller when the model believes the example should 94 | be negatively labeled (for instance, the output of a sigmoid function); (2) 95 | the `target` contains only values 0 (for negative examples) and 1 96 | (for positive examples); and (3) the `weight` ( > 0) represents weight for 97 | each sample. 98 | """ 99 | 100 | def __init__(self, difficult_examples=False): 101 | super(AveragePrecisionMeter, self).__init__() 102 | self.reset() 103 | self.difficult_examples = difficult_examples 104 | 105 | def reset(self): 106 | """Resets the meter with empty member variables""" 107 | self.scores = torch.FloatTensor(torch.FloatStorage()) 108 | self.targets = torch.LongTensor(torch.LongStorage()) 109 | 110 | def add(self, output, target): 111 | """ 112 | Args: 113 | output (Tensor): NxK tensor that for each of the N examples 114 | indicates the probability of the example belonging to each of 115 | the K classes, according to the model. The probabilities should 116 | sum to one over all classes 117 | target (Tensor): binary NxK tensort that encodes which of the K 118 | classes are associated with the N-th input 119 | (eg: a row [0, 1, 0, 1] indicates that the example is 120 | associated with classes 2 and 4) 121 | weight (optional, Tensor): Nx1 tensor representing the weight for 122 | each example (each weight > 0) 123 | """ 124 | if not torch.is_tensor(output): 125 | output = torch.from_numpy(output) 126 | if not torch.is_tensor(target): 127 | target = torch.from_numpy(target) 128 | 129 | if output.dim() == 1: 130 | output = output.view(-1, 1) 131 | else: 132 | assert output.dim() == 2, \ 133 | 'wrong output size (should be 1D or 2D with one column \ 134 | per class)' 135 | if target.dim() == 1: 136 | target = target.view(-1, 1) 137 | else: 138 | assert target.dim() == 2, \ 139 | 'wrong target size (should be 1D or 2D with one column \ 140 | per class)' 141 | if self.scores.numel() > 0: 142 | assert target.size(1) == self.targets.size(1), \ 143 | 'dimensions for output should match previously added examples.' 144 | 145 | # make sure storage is of sufficient size 146 | if self.scores.storage().size() < self.scores.numel() + output.numel(): 147 | new_size = math.ceil(self.scores.storage().size() * 1.5) 148 | self.scores.storage().resize_(int(new_size + output.numel())) 149 | self.targets.storage().resize_(int(new_size + output.numel())) 150 | 151 | # store scores and targets 152 | offset = self.scores.size(0) if self.scores.dim() > 0 else 0 153 | self.scores.resize_(offset + output.size(0), output.size(1)) 154 | self.targets.resize_(offset + target.size(0), target.size(1)) 155 | self.scores.narrow(0, offset, output.size(0)).copy_(output) 156 | self.targets.narrow(0, offset, target.size(0)).copy_(target) 157 | 158 | def value(self): 159 | """Returns the model's average precision for each class 160 | Return: 161 | ap (FloatTensor): 1xK tensor, with avg precision for each class k 162 | """ 163 | 164 | if self.scores.numel() == 0: 165 | return 0 166 | ap = torch.zeros(self.scores.size(1)) 167 | rg = torch.arange(1, self.scores.size(0)).float() 168 | 169 | # compute average precision for each class 170 | for k in range(self.scores.size(1)): 171 | # sort scores 172 | scores = self.scores[:, k] 173 | targets = self.targets[:, k] 174 | 175 | # compute average precision 176 | ap[k] = AveragePrecisionMeter.average_precision(scores, targets, self.difficult_examples) 177 | return ap 178 | 179 | @staticmethod 180 | def average_precision(output, target, difficult_examples=True): 181 | 182 | # sort examples 183 | sorted, indices = torch.sort(output, dim=0, descending=True) 184 | 185 | # Computes prec@i 186 | pos_count = 0. 187 | total_count = 0. 188 | precision_at_i = 0. 189 | for i in indices: 190 | label = target[i] 191 | if difficult_examples and label == 0: 192 | continue 193 | if label == 1: 194 | pos_count += 1 195 | total_count += 1 196 | if label == 1: 197 | precision_at_i += pos_count / total_count 198 | precision_at_i /= pos_count 199 | return precision_at_i -------------------------------------------------------------------------------- /pretrainedmodels/datasets/voc.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function, division, absolute_import 2 | import csv 3 | import os 4 | import os.path 5 | import tarfile 6 | from six.moves.urllib.parse import urlparse 7 | 8 | import numpy as np 9 | import torch 10 | import torch.utils.data as data 11 | from PIL import Image 12 | 13 | from . import utils 14 | 15 | object_categories = ['aeroplane', 'bicycle', 'bird', 'boat', 16 | 'bottle', 'bus', 'car', 'cat', 'chair', 17 | 'cow', 'diningtable', 'dog', 'horse', 18 | 'motorbike', 'person', 'pottedplant', 19 | 'sheep', 'sofa', 'train', 'tvmonitor'] 20 | 21 | urls = { 22 | 'devkit': 'http://host.robots.ox.ac.uk/pascal/VOC/voc2012/VOCdevkit_18-May-2011.tar', 23 | 'trainval_2007': 'http://host.robots.ox.ac.uk/pascal/VOC/voc2007/VOCtrainval_06-Nov-2007.tar', 24 | 'test_images_2007': 'http://host.robots.ox.ac.uk/pascal/VOC/voc2007/VOCtest_06-Nov-2007.tar', 25 | 'test_anno_2007': 'http://host.robots.ox.ac.uk/pascal/VOC/voc2007/VOCtestnoimgs_06-Nov-2007.tar', 26 | } 27 | 28 | 29 | def read_image_label(file): 30 | print('[dataset] read ' + file) 31 | data = dict() 32 | with open(file, 'r') as f: 33 | for line in f: 34 | tmp = line.split(' ') 35 | name = tmp[0] 36 | label = int(tmp[-1]) 37 | data[name] = label 38 | # data.append([name, label]) 39 | # print('%s %d' % (name, label)) 40 | return data 41 | 42 | 43 | def read_object_labels(root, dataset, set): 44 | path_labels = os.path.join(root, 'VOCdevkit', dataset, 'ImageSets', 'Main') 45 | labeled_data = dict() 46 | num_classes = len(object_categories) 47 | 48 | for i in range(num_classes): 49 | file = os.path.join(path_labels, object_categories[i] + '_' + set + '.txt') 50 | data = read_image_label(file) 51 | 52 | if i == 0: 53 | for (name, label) in data.items(): 54 | labels = np.zeros(num_classes) 55 | labels[i] = label 56 | labeled_data[name] = labels 57 | else: 58 | for (name, label) in data.items(): 59 | labeled_data[name][i] = label 60 | 61 | return labeled_data 62 | 63 | 64 | def write_object_labels_csv(file, labeled_data): 65 | # write a csv file 66 | print('[dataset] write file %s' % file) 67 | with open(file, 'w') as csvfile: 68 | fieldnames = ['name'] 69 | fieldnames.extend(object_categories) 70 | writer = csv.DictWriter(csvfile, fieldnames=fieldnames) 71 | 72 | writer.writeheader() 73 | for (name, labels) in labeled_data.items(): 74 | example = {'name': name} 75 | for i in range(20): 76 | example[fieldnames[i + 1]] = int(labels[i]) 77 | writer.writerow(example) 78 | 79 | csvfile.close() 80 | 81 | 82 | def read_object_labels_csv(file, header=True): 83 | images = [] 84 | num_categories = 0 85 | print('[dataset] read', file) 86 | with open(file, 'r') as f: 87 | reader = csv.reader(f) 88 | rownum = 0 89 | for row in reader: 90 | if header and rownum == 0: 91 | header = row 92 | else: 93 | if num_categories == 0: 94 | num_categories = len(row) - 1 95 | name = row[0] 96 | labels = (np.asarray(row[1:num_categories + 1])).astype(np.float32) 97 | labels = torch.from_numpy(labels) 98 | item = (name, labels) 99 | images.append(item) 100 | rownum += 1 101 | return images 102 | 103 | 104 | def find_images_classification(root, dataset, set): 105 | path_labels = os.path.join(root, 'VOCdevkit', dataset, 'ImageSets', 'Main') 106 | images = [] 107 | file = os.path.join(path_labels, set + '.txt') 108 | with open(file, 'r') as f: 109 | for line in f: 110 | images.append(line) 111 | return images 112 | 113 | 114 | def download_voc2007(root): 115 | path_devkit = os.path.join(root, 'VOCdevkit') 116 | path_images = os.path.join(root, 'VOCdevkit', 'VOC2007', 'JPEGImages') 117 | tmpdir = os.path.join(root, 'tmp') 118 | 119 | # create directory 120 | if not os.path.exists(root): 121 | os.makedirs(root) 122 | 123 | if not os.path.exists(path_devkit): 124 | 125 | if not os.path.exists(tmpdir): 126 | os.makedirs(tmpdir) 127 | 128 | parts = urlparse(urls['devkit']) 129 | filename = os.path.basename(parts.path) 130 | cached_file = os.path.join(tmpdir, filename) 131 | 132 | if not os.path.exists(cached_file): 133 | print('Downloading: "{}" to {}\n'.format(urls['devkit'], cached_file)) 134 | utils.download_url(urls['devkit'], cached_file) 135 | 136 | # extract file 137 | print('[dataset] Extracting tar file {file} to {path}'.format(file=cached_file, path=root)) 138 | cwd = os.getcwd() 139 | tar = tarfile.open(cached_file, "r") 140 | os.chdir(root) 141 | tar.extractall() 142 | tar.close() 143 | os.chdir(cwd) 144 | print('[dataset] Done!') 145 | 146 | # train/val images/annotations 147 | if not os.path.exists(path_images): 148 | 149 | # download train/val images/annotations 150 | parts = urlparse(urls['trainval_2007']) 151 | filename = os.path.basename(parts.path) 152 | cached_file = os.path.join(tmpdir, filename) 153 | 154 | if not os.path.exists(cached_file): 155 | print('Downloading: "{}" to {}\n'.format(urls['trainval_2007'], cached_file)) 156 | utils.download_url(urls['trainval_2007'], cached_file) 157 | 158 | # extract file 159 | print('[dataset] Extracting tar file {file} to {path}'.format(file=cached_file, path=root)) 160 | cwd = os.getcwd() 161 | tar = tarfile.open(cached_file, "r") 162 | os.chdir(root) 163 | tar.extractall() 164 | tar.close() 165 | os.chdir(cwd) 166 | print('[dataset] Done!') 167 | 168 | # test annotations 169 | test_anno = os.path.join(path_devkit, 'VOC2007/ImageSets/Main/aeroplane_test.txt') 170 | if not os.path.exists(test_anno): 171 | 172 | # download test annotations 173 | parts = urlparse(urls['test_images_2007']) 174 | filename = os.path.basename(parts.path) 175 | cached_file = os.path.join(tmpdir, filename) 176 | 177 | if not os.path.exists(cached_file): 178 | print('Downloading: "{}" to {}\n'.format(urls['test_images_2007'], cached_file)) 179 | utils.download_url(urls['test_images_2007'], cached_file) 180 | 181 | # extract file 182 | print('[dataset] Extracting tar file {file} to {path}'.format(file=cached_file, path=root)) 183 | cwd = os.getcwd() 184 | tar = tarfile.open(cached_file, "r") 185 | os.chdir(root) 186 | tar.extractall() 187 | tar.close() 188 | os.chdir(cwd) 189 | print('[dataset] Done!') 190 | 191 | # test images 192 | test_image = os.path.join(path_devkit, 'VOC2007/JPEGImages/000001.jpg') 193 | if not os.path.exists(test_image): 194 | 195 | # download test images 196 | parts = urlparse(urls['test_anno_2007']) 197 | filename = os.path.basename(parts.path) 198 | cached_file = os.path.join(tmpdir, filename) 199 | 200 | if not os.path.exists(cached_file): 201 | print('Downloading: "{}" to {}\n'.format(urls['test_anno_2007'], cached_file)) 202 | utils.download_url(urls['test_anno_2007'], cached_file) 203 | 204 | # extract file 205 | print('[dataset] Extracting tar file {file} to {path}'.format(file=cached_file, path=root)) 206 | cwd = os.getcwd() 207 | tar = tarfile.open(cached_file, "r") 208 | os.chdir(root) 209 | tar.extractall() 210 | tar.close() 211 | os.chdir(cwd) 212 | print('[dataset] Done!') 213 | 214 | 215 | class Voc2007Classification(data.Dataset): 216 | 217 | def __init__(self, root, set, transform=None, target_transform=None): 218 | self.root = root 219 | self.path_devkit = os.path.join(root, 'VOCdevkit') 220 | self.path_images = os.path.join(root, 'VOCdevkit', 'VOC2007', 'JPEGImages') 221 | self.set = set 222 | self.transform = transform 223 | self.target_transform = target_transform 224 | 225 | # download dataset 226 | download_voc2007(self.root) 227 | 228 | # define path of csv file 229 | path_csv = os.path.join(self.root, 'files', 'VOC2007') 230 | # define filename of csv file 231 | file_csv = os.path.join(path_csv, 'classification_' + set + '.csv') 232 | 233 | # create the csv file if necessary 234 | if not os.path.exists(file_csv): 235 | if not os.path.exists(path_csv): # create dir if necessary 236 | os.makedirs(path_csv) 237 | # generate csv file 238 | labeled_data = read_object_labels(self.root, 'VOC2007', self.set) 239 | # write csv file 240 | write_object_labels_csv(file_csv, labeled_data) 241 | 242 | self.classes = object_categories 243 | self.images = read_object_labels_csv(file_csv) 244 | 245 | print('[dataset] VOC 2007 classification set=%s number of classes=%d number of images=%d' % ( 246 | set, len(self.classes), len(self.images))) 247 | 248 | def __getitem__(self, index): 249 | path, target = self.images[index] 250 | img = Image.open(os.path.join(self.path_images, path + '.jpg')).convert('RGB') 251 | if self.transform is not None: 252 | img = self.transform(img) 253 | if self.target_transform is not None: 254 | target = self.target_transform(target) 255 | return img, path, target 256 | 257 | def __len__(self): 258 | return len(self.images) 259 | 260 | def get_number_classes(self): 261 | return len(self.classes) 262 | -------------------------------------------------------------------------------- /pretrainedmodels/models/__init__.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function, division, absolute_import 2 | from .fbresnet import fbresnet152 3 | 4 | from .cafferesnet import cafferesnet101 5 | 6 | from .bninception import bninception 7 | 8 | from .resnext import resnext101_32x4d 9 | from .resnext import resnext101_64x4d 10 | 11 | from .inceptionv4 import inceptionv4 12 | 13 | from .inceptionresnetv2 import inceptionresnetv2 14 | 15 | from .nasnet import nasnetalarge 16 | 17 | from .nasnet_mobile import nasnetamobile 18 | 19 | from .torchvision_models import alexnet 20 | from .torchvision_models import densenet121 21 | from .torchvision_models import densenet169 22 | from .torchvision_models import densenet201 23 | from .torchvision_models import densenet161 24 | from .torchvision_models import resnet18 25 | from .torchvision_models import resnet34 26 | from .torchvision_models import resnet50 27 | from .torchvision_models import resnet101 28 | from .torchvision_models import resnet152 29 | from .torchvision_models import inceptionv3 30 | from .torchvision_models import squeezenet1_0 31 | from .torchvision_models import squeezenet1_1 32 | from .torchvision_models import vgg11 33 | from .torchvision_models import vgg11_bn 34 | from .torchvision_models import vgg13 35 | from .torchvision_models import vgg13_bn 36 | from .torchvision_models import vgg16 37 | from .torchvision_models import vgg16_bn 38 | from .torchvision_models import vgg19_bn 39 | from .torchvision_models import vgg19 40 | 41 | from .dpn import dpn68 42 | from .dpn import dpn68b 43 | from .dpn import dpn92 44 | from .dpn import dpn98 45 | from .dpn import dpn131 46 | from .dpn import dpn107 47 | 48 | from .xception import xception 49 | 50 | from .senet import senet154 51 | from .senet import se_resnet50 52 | from .senet import se_resnet101 53 | from .senet import se_resnet152 54 | from .senet import se_resnext50_32x4d 55 | from .senet import se_resnext101_32x4d 56 | 57 | from .pnasnet import pnasnet5large 58 | from .polynet import polynet 59 | -------------------------------------------------------------------------------- /pretrainedmodels/models/cafferesnet.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function, division, absolute_import 2 | import math 3 | import torch 4 | import torch.nn as nn 5 | import torch.nn.functional as F 6 | import torch.utils.model_zoo as model_zoo 7 | 8 | pretrained_settings = { 9 | 'cafferesnet101': { 10 | 'imagenet': { 11 | 'url': 'http://data.lip6.fr/cadene/pretrainedmodels/cafferesnet101-9d633cc0.pth', 12 | 'input_space': 'BGR', 13 | 'input_size': [3, 224, 224], 14 | 'input_range': [0, 255], 15 | 'mean': [102.9801, 115.9465, 122.7717], 16 | 'std': [1, 1, 1], 17 | 'num_classes': 1000 18 | } 19 | } 20 | } 21 | 22 | 23 | def conv3x3(in_planes, out_planes, stride=1): 24 | "3x3 convolution with padding" 25 | return nn.Conv2d(in_planes, out_planes, kernel_size=3, stride=stride, 26 | padding=1, bias=False) 27 | 28 | 29 | class BasicBlock(nn.Module): 30 | expansion = 1 31 | 32 | def __init__(self, inplanes, planes, stride=1, downsample=None): 33 | super(BasicBlock, self).__init__() 34 | self.conv1 = conv3x3(inplanes, planes, stride) 35 | self.bn1 = nn.BatchNorm2d(planes) 36 | self.relu = nn.ReLU(inplace=True) 37 | self.conv2 = conv3x3(planes, planes) 38 | self.bn2 = nn.BatchNorm2d(planes) 39 | self.downsample = downsample 40 | self.stride = stride 41 | 42 | def forward(self, x): 43 | residual = x 44 | 45 | out = self.conv1(x) 46 | out = self.bn1(out) 47 | out = self.relu(out) 48 | 49 | out = self.conv2(out) 50 | out = self.bn2(out) 51 | 52 | if self.downsample is not None: 53 | residual = self.downsample(x) 54 | 55 | out += residual 56 | out = self.relu(out) 57 | 58 | return out 59 | 60 | 61 | class Bottleneck(nn.Module): 62 | expansion = 4 63 | 64 | def __init__(self, inplanes, planes, stride=1, downsample=None): 65 | super(Bottleneck, self).__init__() 66 | self.conv1 = nn.Conv2d(inplanes, planes, kernel_size=1, stride=stride, bias=False) # change 67 | self.bn1 = nn.BatchNorm2d(planes) 68 | self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=1, # change 69 | padding=1, bias=False) 70 | self.bn2 = nn.BatchNorm2d(planes) 71 | self.conv3 = nn.Conv2d(planes, planes * 4, kernel_size=1, bias=False) 72 | self.bn3 = nn.BatchNorm2d(planes * 4) 73 | self.relu = nn.ReLU(inplace=True) 74 | self.downsample = downsample 75 | self.stride = stride 76 | 77 | def forward(self, x): 78 | residual = x 79 | 80 | out = self.conv1(x) 81 | out = self.bn1(out) 82 | out = self.relu(out) 83 | 84 | out = self.conv2(out) 85 | out = self.bn2(out) 86 | out = self.relu(out) 87 | 88 | out = self.conv3(out) 89 | out = self.bn3(out) 90 | 91 | if self.downsample is not None: 92 | residual = self.downsample(x) 93 | 94 | out += residual 95 | out = self.relu(out) 96 | 97 | return out 98 | 99 | 100 | class ResNet(nn.Module): 101 | 102 | def __init__(self, block, layers, num_classes=1000): 103 | self.inplanes = 64 104 | super(ResNet, self).__init__() 105 | self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3, 106 | bias=False) 107 | self.bn1 = nn.BatchNorm2d(64) 108 | self.relu = nn.ReLU(inplace=True) 109 | self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=0, ceil_mode=True) # change 110 | self.layer1 = self._make_layer(block, 64, layers[0]) 111 | self.layer2 = self._make_layer(block, 128, layers[1], stride=2) 112 | self.layer3 = self._make_layer(block, 256, layers[2], stride=2) 113 | self.layer4 = self._make_layer(block, 512, layers[3], stride=2) 114 | # it is slightly better whereas slower to set stride = 1 115 | # self.layer4 = self._make_layer(block, 512, layers[3], stride=1) 116 | self.avgpool = nn.AvgPool2d(7) 117 | self.last_linear = nn.Linear(512 * block.expansion, num_classes) 118 | 119 | for m in self.modules(): 120 | if isinstance(m, nn.Conv2d): 121 | n = m.kernel_size[0] * m.kernel_size[1] * m.out_channels 122 | m.weight.data.normal_(0, math.sqrt(2. / n)) 123 | elif isinstance(m, nn.BatchNorm2d): 124 | m.weight.data.fill_(1) 125 | m.bias.data.zero_() 126 | 127 | def _make_layer(self, block, planes, blocks, stride=1): 128 | downsample = None 129 | if stride != 1 or self.inplanes != planes * block.expansion: 130 | downsample = nn.Sequential( 131 | nn.Conv2d(self.inplanes, planes * block.expansion, 132 | kernel_size=1, stride=stride, bias=False), 133 | nn.BatchNorm2d(planes * block.expansion), 134 | ) 135 | 136 | layers = [] 137 | layers.append(block(self.inplanes, planes, stride, downsample)) 138 | self.inplanes = planes * block.expansion 139 | for i in range(1, blocks): 140 | layers.append(block(self.inplanes, planes)) 141 | 142 | return nn.Sequential(*layers) 143 | 144 | def features(self, x): 145 | x = self.conv1(x) 146 | x = self.bn1(x) 147 | x = self.relu(x) 148 | x = self.maxpool(x) 149 | 150 | x = self.layer1(x) 151 | x = self.layer2(x) 152 | x = self.layer3(x) 153 | x = self.layer4(x) 154 | return x 155 | 156 | def logits(self, x): 157 | x = self.avgpool(x) 158 | x = x.view(x.size(0), -1) 159 | x = self.last_linear(x) 160 | return x 161 | 162 | def forward(self, x): 163 | x = self.features(x) 164 | x = self.logits(x) 165 | return x 166 | 167 | 168 | def cafferesnet101(num_classes=1000, pretrained='imagenet'): 169 | """Constructs a ResNet-101 model. 170 | Args: 171 | pretrained (bool): If True, returns a model pre-trained on ImageNet 172 | """ 173 | model = ResNet(Bottleneck, [3, 4, 23, 3], num_classes=num_classes) 174 | if pretrained is not None: 175 | settings = pretrained_settings['cafferesnet101'][pretrained] 176 | assert num_classes == settings['num_classes'], \ 177 | "num_classes should be {}, but is {}".format(settings['num_classes'], num_classes) 178 | model.load_state_dict(model_zoo.load_url(settings['url'])) 179 | model.input_space = settings['input_space'] 180 | model.input_size = settings['input_size'] 181 | model.input_range = settings['input_range'] 182 | model.mean = settings['mean'] 183 | model.std = settings['std'] 184 | return model -------------------------------------------------------------------------------- /pretrainedmodels/models/fbresnet.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function, division, absolute_import 2 | import torch.nn as nn 3 | import torch.nn.functional as F 4 | import math 5 | import torch.utils.model_zoo as model_zoo 6 | 7 | 8 | __all__ = ['FBResNet', 9 | #'fbresnet18', 'fbresnet34', 'fbresnet50', 'fbresnet101', 10 | 'fbresnet152'] 11 | 12 | pretrained_settings = { 13 | 'fbresnet152': { 14 | 'imagenet': { 15 | 'url': 'http://data.lip6.fr/cadene/pretrainedmodels/fbresnet152-2e20f6b4.pth', 16 | 'input_space': 'RGB', 17 | 'input_size': [3, 224, 224], 18 | 'input_range': [0, 1], 19 | 'mean': [0.485, 0.456, 0.406], 20 | 'std': [0.229, 0.224, 0.225], 21 | 'num_classes': 1000 22 | } 23 | } 24 | } 25 | 26 | 27 | def conv3x3(in_planes, out_planes, stride=1): 28 | "3x3 convolution with padding" 29 | return nn.Conv2d(in_planes, out_planes, kernel_size=3, stride=stride, 30 | padding=1, bias=True) 31 | 32 | 33 | class BasicBlock(nn.Module): 34 | expansion = 1 35 | 36 | def __init__(self, inplanes, planes, stride=1, downsample=None): 37 | super(BasicBlock, self).__init__() 38 | self.conv1 = conv3x3(inplanes, planes, stride) 39 | self.bn1 = nn.BatchNorm2d(planes) 40 | self.relu = nn.ReLU(inplace=True) 41 | self.conv2 = conv3x3(planes, planes) 42 | self.bn2 = nn.BatchNorm2d(planes) 43 | self.downsample = downsample 44 | self.stride = stride 45 | 46 | def forward(self, x): 47 | residual = x 48 | 49 | out = self.conv1(x) 50 | out = self.bn1(out) 51 | out = self.relu(out) 52 | 53 | out = self.conv2(out) 54 | out = self.bn2(out) 55 | 56 | if self.downsample is not None: 57 | residual = self.downsample(x) 58 | 59 | out += residual 60 | out = self.relu(out) 61 | 62 | return out 63 | 64 | 65 | class Bottleneck(nn.Module): 66 | expansion = 4 67 | 68 | def __init__(self, inplanes, planes, stride=1, downsample=None): 69 | super(Bottleneck, self).__init__() 70 | self.conv1 = nn.Conv2d(inplanes, planes, kernel_size=1, bias=True) 71 | self.bn1 = nn.BatchNorm2d(planes) 72 | self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=stride, 73 | padding=1, bias=True) 74 | self.bn2 = nn.BatchNorm2d(planes) 75 | self.conv3 = nn.Conv2d(planes, planes * 4, kernel_size=1, bias=True) 76 | self.bn3 = nn.BatchNorm2d(planes * 4) 77 | self.relu = nn.ReLU(inplace=True) 78 | self.downsample = downsample 79 | self.stride = stride 80 | 81 | def forward(self, x): 82 | residual = x 83 | 84 | out = self.conv1(x) 85 | out = self.bn1(out) 86 | out = self.relu(out) 87 | 88 | out = self.conv2(out) 89 | out = self.bn2(out) 90 | out = self.relu(out) 91 | 92 | out = self.conv3(out) 93 | out = self.bn3(out) 94 | 95 | if self.downsample is not None: 96 | residual = self.downsample(x) 97 | 98 | out += residual 99 | out = self.relu(out) 100 | 101 | return out 102 | 103 | class FBResNet(nn.Module): 104 | 105 | def __init__(self, block, layers, num_classes=1000): 106 | self.inplanes = 64 107 | # Special attributs 108 | self.input_space = None 109 | self.input_size = (299, 299, 3) 110 | self.mean = None 111 | self.std = None 112 | super(FBResNet, self).__init__() 113 | # Modules 114 | self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3, 115 | bias=True) 116 | self.bn1 = nn.BatchNorm2d(64) 117 | self.relu = nn.ReLU(inplace=True) 118 | self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1) 119 | self.layer1 = self._make_layer(block, 64, layers[0]) 120 | self.layer2 = self._make_layer(block, 128, layers[1], stride=2) 121 | self.layer3 = self._make_layer(block, 256, layers[2], stride=2) 122 | self.layer4 = self._make_layer(block, 512, layers[3], stride=2) 123 | self.last_linear = nn.Linear(512 * block.expansion, num_classes) 124 | 125 | for m in self.modules(): 126 | if isinstance(m, nn.Conv2d): 127 | n = m.kernel_size[0] * m.kernel_size[1] * m.out_channels 128 | m.weight.data.normal_(0, math.sqrt(2. / n)) 129 | elif isinstance(m, nn.BatchNorm2d): 130 | m.weight.data.fill_(1) 131 | m.bias.data.zero_() 132 | 133 | def _make_layer(self, block, planes, blocks, stride=1): 134 | downsample = None 135 | if stride != 1 or self.inplanes != planes * block.expansion: 136 | downsample = nn.Sequential( 137 | nn.Conv2d(self.inplanes, planes * block.expansion, 138 | kernel_size=1, stride=stride, bias=True), 139 | nn.BatchNorm2d(planes * block.expansion), 140 | ) 141 | 142 | layers = [] 143 | layers.append(block(self.inplanes, planes, stride, downsample)) 144 | self.inplanes = planes * block.expansion 145 | for i in range(1, blocks): 146 | layers.append(block(self.inplanes, planes)) 147 | 148 | return nn.Sequential(*layers) 149 | 150 | def features(self, input): 151 | x = self.conv1(input) 152 | self.conv1_input = x.clone() 153 | x = self.bn1(x) 154 | x = self.relu(x) 155 | x = self.maxpool(x) 156 | 157 | x = self.layer1(x) 158 | x = self.layer2(x) 159 | x = self.layer3(x) 160 | x = self.layer4(x) 161 | return x 162 | 163 | def logits(self, features): 164 | adaptiveAvgPoolWidth = features.shape[2] 165 | x = F.avg_pool2d(features, kernel_size=adaptiveAvgPoolWidth) 166 | x = x.view(x.size(0), -1) 167 | x = self.last_linear(x) 168 | return x 169 | 170 | def forward(self, input): 171 | x = self.features(input) 172 | x = self.logits(x) 173 | return x 174 | 175 | 176 | def fbresnet18(num_classes=1000): 177 | """Constructs a ResNet-18 model. 178 | 179 | Args: 180 | pretrained (bool): If True, returns a model pre-trained on ImageNet 181 | """ 182 | model = FBResNet(BasicBlock, [2, 2, 2, 2], num_classes=num_classes) 183 | return model 184 | 185 | 186 | def fbresnet34(num_classes=1000): 187 | """Constructs a ResNet-34 model. 188 | 189 | Args: 190 | pretrained (bool): If True, returns a model pre-trained on ImageNet 191 | """ 192 | model = FBResNet(BasicBlock, [3, 4, 6, 3], num_classes=num_classes) 193 | return model 194 | 195 | 196 | def fbresnet50(num_classes=1000): 197 | """Constructs a ResNet-50 model. 198 | 199 | Args: 200 | pretrained (bool): If True, returns a model pre-trained on ImageNet 201 | """ 202 | model = FBResNet(Bottleneck, [3, 4, 6, 3], num_classes=num_classes) 203 | return model 204 | 205 | 206 | def fbresnet101(num_classes=1000): 207 | """Constructs a ResNet-101 model. 208 | 209 | Args: 210 | pretrained (bool): If True, returns a model pre-trained on ImageNet 211 | """ 212 | model = FBResNet(Bottleneck, [3, 4, 23, 3], num_classes=num_classes) 213 | return model 214 | 215 | 216 | def fbresnet152(num_classes=1000, pretrained='imagenet'): 217 | """Constructs a ResNet-152 model. 218 | 219 | Args: 220 | pretrained (bool): If True, returns a model pre-trained on ImageNet 221 | """ 222 | model = FBResNet(Bottleneck, [3, 8, 36, 3], num_classes=num_classes) 223 | if pretrained is not None: 224 | settings = pretrained_settings['fbresnet152'][pretrained] 225 | assert num_classes == settings['num_classes'], \ 226 | "num_classes should be {}, but is {}".format(settings['num_classes'], num_classes) 227 | model.load_state_dict(model_zoo.load_url(settings['url'])) 228 | model.input_space = settings['input_space'] 229 | model.input_size = settings['input_size'] 230 | model.input_range = settings['input_range'] 231 | model.mean = settings['mean'] 232 | model.std = settings['std'] 233 | return model 234 | 235 | 236 | -------------------------------------------------------------------------------- /pretrainedmodels/models/fbresnet/resnet152_dump.lua: -------------------------------------------------------------------------------- 1 | require 'cutorch' 2 | require 'cunn' 3 | require 'cudnn' 4 | require 'image' 5 | vision=require 'torchnet-vision' 6 | 7 | net=vision.models.resnet.load{filename='data/resnet152/net.t7',length=152} 8 | print(net) 9 | 10 | require 'nn' 11 | nn.Module.parameters = function(self) 12 | if self.weight and self.bias and self.running_mean and self.running_var then 13 | return {self.weight, self.bias, self.running_mean, self.running_var}, {self.gradWeight, self.gradBias} 14 | 15 | elseif self.weight and self.bias then 16 | return {self.weight, self.bias}, {self.gradWeight, self.gradBias} 17 | elseif self.weight then 18 | return {self.weight}, {self.gradWeight} 19 | elseif self.bias then 20 | return {self.bias}, {self.gradBias} 21 | else 22 | return 23 | end 24 | end 25 | 26 | netparams, _ = net:parameters() 27 | print(#netparams) 28 | torch.save('data/resnet152/netparams.t7', netparams) 29 | 30 | net=net:cuda() 31 | net:evaluate() 32 | --p, gp = net:getParameters() 33 | input = torch.ones(1,3,224,224) 34 | input[{1,1,1,1}] = -1 35 | input[1] = image.load('data/cat_224.png') 36 | print(input:sum()) 37 | input = input:cuda() 38 | output=net:forward(input) 39 | 40 | for i=1, 11 do 41 | torch.save('data/resnet152/output'..i..'.t7', net:get(i).output:float()) 42 | end 43 | -------------------------------------------------------------------------------- /pretrainedmodels/models/fbresnet/resnet152_load.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function, division, absolute_import 2 | import torch.nn as nn 3 | import math 4 | import torch.utils.model_zoo as model_zoo 5 | 6 | 7 | __all__ = ['ResNet', 'resnet18', 'resnet34', 'resnet50', 'resnet101', 8 | 'resnet152'] 9 | 10 | 11 | model_urls = { 12 | 'resnet18': 'https://download.pytorch.org/models/resnet18-5c106cde.pth', 13 | 'resnet34': 'https://download.pytorch.org/models/resnet34-333f7ec4.pth', 14 | 'resnet50': 'https://download.pytorch.org/models/resnet50-19c8e357.pth', 15 | 'resnet101': 'https://download.pytorch.org/models/resnet101-5d3b4d8f.pth', 16 | 'resnet152': 'https://download.pytorch.org/models/resnet152-b121ed2d.pth', 17 | } 18 | 19 | 20 | def conv3x3(in_planes, out_planes, stride=1): 21 | "3x3 convolution with padding" 22 | return nn.Conv2d(in_planes, out_planes, kernel_size=3, stride=stride, 23 | padding=1, bias=True) 24 | 25 | 26 | class BasicBlock(nn.Module): 27 | expansion = 1 28 | 29 | def __init__(self, inplanes, planes, stride=1, downsample=None): 30 | super(BasicBlock, self).__init__() 31 | self.conv1 = conv3x3(inplanes, planes, stride) 32 | self.bn1 = nn.BatchNorm2d(planes) 33 | self.relu = nn.ReLU(inplace=True) 34 | self.conv2 = conv3x3(planes, planes) 35 | self.bn2 = nn.BatchNorm2d(planes) 36 | self.downsample = downsample 37 | self.stride = stride 38 | 39 | def forward(self, x): 40 | residual = x 41 | 42 | out = self.conv1(x) 43 | out = self.bn1(out) 44 | out = self.relu(out) 45 | 46 | out = self.conv2(out) 47 | out = self.bn2(out) 48 | 49 | if self.downsample is not None: 50 | residual = self.downsample(x) 51 | 52 | out += residual 53 | out = self.relu(out) 54 | 55 | return out 56 | 57 | 58 | class Bottleneck(nn.Module): 59 | expansion = 4 60 | 61 | def __init__(self, inplanes, planes, stride=1, downsample=None): 62 | super(Bottleneck, self).__init__() 63 | self.conv1 = nn.Conv2d(inplanes, planes, kernel_size=1, bias=True) 64 | self.bn1 = nn.BatchNorm2d(planes) 65 | self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=stride, 66 | padding=1, bias=True) 67 | self.bn2 = nn.BatchNorm2d(planes) 68 | self.conv3 = nn.Conv2d(planes, planes * 4, kernel_size=1, bias=True) 69 | self.bn3 = nn.BatchNorm2d(planes * 4) 70 | self.relu = nn.ReLU(inplace=True) 71 | self.downsample = downsample 72 | self.stride = stride 73 | 74 | def forward(self, x): 75 | residual = x 76 | 77 | out = self.conv1(x) 78 | out = self.bn1(out) 79 | out = self.relu(out) 80 | 81 | out = self.conv2(out) 82 | out = self.bn2(out) 83 | out = self.relu(out) 84 | 85 | out = self.conv3(out) 86 | out = self.bn3(out) 87 | 88 | if self.downsample is not None: 89 | residual = self.downsample(x) 90 | 91 | out += residual 92 | out = self.relu(out) 93 | 94 | return out 95 | 96 | from torch.legacy import nn as nnl 97 | 98 | class ResNet(nn.Module): 99 | 100 | def __init__(self, block, layers, num_classes=1000): 101 | self.inplanes = 64 102 | super(ResNet, self).__init__() 103 | self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3, 104 | bias=True) 105 | #self.conv1 = nnl.SpatialConvolution(3, 64, 7, 7, 2, 2, 3, 3) 106 | self.bn1 = nn.BatchNorm2d(64) 107 | self.relu = nn.ReLU(inplace=True) 108 | self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1) 109 | self.layer1 = self._make_layer(block, 64, layers[0]) 110 | self.layer2 = self._make_layer(block, 128, layers[1], stride=2) 111 | self.layer3 = self._make_layer(block, 256, layers[2], stride=2) 112 | self.layer4 = self._make_layer(block, 512, layers[3], stride=2) 113 | self.avgpool = nn.AvgPool2d(7) 114 | self.fc = nn.Linear(512 * block.expansion, num_classes) 115 | 116 | for m in self.modules(): 117 | if isinstance(m, nn.Conv2d): 118 | n = m.kernel_size[0] * m.kernel_size[1] * m.out_channels 119 | m.weight.data.normal_(0, math.sqrt(2. / n)) 120 | elif isinstance(m, nn.BatchNorm2d): 121 | m.weight.data.fill_(1) 122 | m.bias.data.zero_() 123 | 124 | def _make_layer(self, block, planes, blocks, stride=1): 125 | downsample = None 126 | if stride != 1 or self.inplanes != planes * block.expansion: 127 | downsample = nn.Sequential( 128 | nn.Conv2d(self.inplanes, planes * block.expansion, 129 | kernel_size=1, stride=stride, bias=True), 130 | nn.BatchNorm2d(planes * block.expansion), 131 | ) 132 | 133 | layers = [] 134 | layers.append(block(self.inplanes, planes, stride, downsample)) 135 | self.inplanes = planes * block.expansion 136 | for i in range(1, blocks): 137 | layers.append(block(self.inplanes, planes)) 138 | 139 | return nn.Sequential(*layers) 140 | 141 | def forward(self, x): 142 | x = self.conv1(x) 143 | self.conv1_input = x.clone() 144 | x = self.bn1(x) 145 | x = self.relu(x) 146 | x = self.maxpool(x) 147 | 148 | x = self.layer1(x) 149 | x = self.layer2(x) 150 | x = self.layer3(x) 151 | x = self.layer4(x) 152 | 153 | x = self.avgpool(x) 154 | x = x.view(x.size(0), -1) 155 | x = self.fc(x) 156 | 157 | return x 158 | 159 | 160 | def resnet18(pretrained=False, **kwargs): 161 | """Constructs a ResNet-18 model. 162 | 163 | Args: 164 | pretrained (bool): If True, returns a model pre-trained on ImageNet 165 | """ 166 | model = ResNet(BasicBlock, [2, 2, 2, 2], **kwargs) 167 | if pretrained: 168 | model.load_state_dict(model_zoo.load_url(model_urls['resnet18'])) 169 | return model 170 | 171 | 172 | def resnet34(pretrained=False, **kwargs): 173 | """Constructs a ResNet-34 model. 174 | 175 | Args: 176 | pretrained (bool): If True, returns a model pre-trained on ImageNet 177 | """ 178 | model = ResNet(BasicBlock, [3, 4, 6, 3], **kwargs) 179 | if pretrained: 180 | model.load_state_dict(model_zoo.load_url(model_urls['resnet34'])) 181 | return model 182 | 183 | 184 | def resnet50(pretrained=False, **kwargs): 185 | """Constructs a ResNet-50 model. 186 | 187 | Args: 188 | pretrained (bool): If True, returns a model pre-trained on ImageNet 189 | """ 190 | model = ResNet(Bottleneck, [3, 4, 6, 3], **kwargs) 191 | if pretrained: 192 | model.load_state_dict(model_zoo.load_url(model_urls['resnet50'])) 193 | return model 194 | 195 | 196 | def resnet101(pretrained=False, **kwargs): 197 | """Constructs a ResNet-101 model. 198 | 199 | Args: 200 | pretrained (bool): If True, returns a model pre-trained on ImageNet 201 | """ 202 | model = ResNet(Bottleneck, [3, 4, 23, 3], **kwargs) 203 | if pretrained: 204 | model.load_state_dict(model_zoo.load_url(model_urls['resnet101'])) 205 | return model 206 | 207 | 208 | def resnet152(pretrained=False, **kwargs): 209 | """Constructs a ResNet-152 model. 210 | 211 | Args: 212 | pretrained (bool): If True, returns a model pre-trained on ImageNet 213 | """ 214 | model = ResNet(Bottleneck, [3, 8, 36, 3], **kwargs) 215 | if pretrained: 216 | model.load_state_dict(model_zoo.load_url(model_urls['resnet152'])) 217 | return model 218 | 219 | import torchfile 220 | from torch.utils.serialization import load_lua 221 | import torch 222 | netparams = torchfile.load('data/resnet152/netparams.t7') 223 | #netparams2 = load_lua('data/resnet152/netparams.t7') 224 | #import ipdb; ipdb.set_trace() 225 | netoutputs = [] 226 | for i in range(1, 12): 227 | path = 'data/resnet152/output{}.t7'.format(i) 228 | out = load_lua(path) 229 | #print(out.size()) 230 | if out.dim()==4: 231 | pass#out.transpose_(2, 3) 232 | netoutputs.append(out) 233 | 234 | net = resnet152() 235 | state_dict = net.state_dict() 236 | 237 | import collections 238 | s = collections.OrderedDict() 239 | 240 | 241 | i=0 242 | for key in state_dict.keys(): 243 | new = torch.from_numpy(netparams[i]) 244 | s[key] = new 245 | if s[key].dim() == 4: 246 | pass#s[key].transpose_(2,3) 247 | i += 1 248 | 249 | net.load_state_dict(s) 250 | 251 | net.conv1.register_forward_hook(lambda self, input, output: \ 252 | print('conv1', torch.dist(output.data, netoutputs[0]))) 253 | net.bn1.register_forward_hook(lambda self, input, output: \ 254 | print('bn1', torch.dist(output.data, netoutputs[1]))) 255 | net.relu.register_forward_hook(lambda self, input, output: \ 256 | print('relu', torch.dist(output.data, netoutputs[2]))) 257 | net.maxpool.register_forward_hook(lambda self, input, output: \ 258 | print('maxpool', torch.dist(output.data, netoutputs[3]))) 259 | net.layer1.register_forward_hook(lambda self, input, output: \ 260 | print('layer1', torch.dist(output.data, netoutputs[4]))) 261 | net.layer2.register_forward_hook(lambda self, input, output: \ 262 | print('layer2', torch.dist(output.data, netoutputs[5]))) 263 | net.layer3.register_forward_hook(lambda self, input, output: \ 264 | print('layer3', torch.dist(output.data, netoutputs[6]))) 265 | net.layer4.register_forward_hook(lambda self, input, output: \ 266 | print('layer4', torch.dist(output.data, netoutputs[7]))) 267 | net.avgpool.register_forward_hook(lambda self, input, output: \ 268 | print('avgpool', torch.dist(output.data, netoutputs[8]))) 269 | net.fc.register_forward_hook(lambda self, input, output: \ 270 | print('fc', torch.dist(output.data, netoutputs[10]))) 271 | 272 | net.eval() 273 | input_data = torch.ones(1,3,224,224) 274 | input_data[0][0][0][0] = -1 275 | from PIL import Image 276 | import torchvision.transforms as transforms 277 | input_data[0] = transforms.ToTensor()(Image.open('data/cat_224.png')) 278 | print('cat sum', input_data.sum()) 279 | input = torch.autograd.Variable(input_data) 280 | output = net.forward(input) 281 | 282 | torch.save(s, 'data/resnet152.pth') 283 | 284 | 285 | -------------------------------------------------------------------------------- /pretrainedmodels/models/inceptionresnetv2.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function, division, absolute_import 2 | import torch 3 | import torch.nn as nn 4 | import torch.utils.model_zoo as model_zoo 5 | import os 6 | import sys 7 | 8 | __all__ = ['InceptionResNetV2', 'inceptionresnetv2'] 9 | 10 | pretrained_settings = { 11 | 'inceptionresnetv2': { 12 | 'imagenet': { 13 | 'url': 'http://data.lip6.fr/cadene/pretrainedmodels/inceptionresnetv2-520b38e4.pth', 14 | 'input_space': 'RGB', 15 | 'input_size': [3, 299, 299], 16 | 'input_range': [0, 1], 17 | 'mean': [0.5, 0.5, 0.5], 18 | 'std': [0.5, 0.5, 0.5], 19 | 'num_classes': 1000 20 | }, 21 | 'imagenet+background': { 22 | 'url': 'http://data.lip6.fr/cadene/pretrainedmodels/inceptionresnetv2-520b38e4.pth', 23 | 'input_space': 'RGB', 24 | 'input_size': [3, 299, 299], 25 | 'input_range': [0, 1], 26 | 'mean': [0.5, 0.5, 0.5], 27 | 'std': [0.5, 0.5, 0.5], 28 | 'num_classes': 1001 29 | } 30 | } 31 | } 32 | 33 | 34 | class BasicConv2d(nn.Module): 35 | 36 | def __init__(self, in_planes, out_planes, kernel_size, stride, padding=0): 37 | super(BasicConv2d, self).__init__() 38 | self.conv = nn.Conv2d(in_planes, out_planes, 39 | kernel_size=kernel_size, stride=stride, 40 | padding=padding, bias=False) # verify bias false 41 | self.bn = nn.BatchNorm2d(out_planes, 42 | eps=0.001, # value found in tensorflow 43 | momentum=0.1, # default pytorch value 44 | affine=True) 45 | self.relu = nn.ReLU(inplace=False) 46 | 47 | def forward(self, x): 48 | x = self.conv(x) 49 | x = self.bn(x) 50 | x = self.relu(x) 51 | return x 52 | 53 | 54 | class Mixed_5b(nn.Module): 55 | 56 | def __init__(self): 57 | super(Mixed_5b, self).__init__() 58 | 59 | self.branch0 = BasicConv2d(192, 96, kernel_size=1, stride=1) 60 | 61 | self.branch1 = nn.Sequential( 62 | BasicConv2d(192, 48, kernel_size=1, stride=1), 63 | BasicConv2d(48, 64, kernel_size=5, stride=1, padding=2) 64 | ) 65 | 66 | self.branch2 = nn.Sequential( 67 | BasicConv2d(192, 64, kernel_size=1, stride=1), 68 | BasicConv2d(64, 96, kernel_size=3, stride=1, padding=1), 69 | BasicConv2d(96, 96, kernel_size=3, stride=1, padding=1) 70 | ) 71 | 72 | self.branch3 = nn.Sequential( 73 | nn.AvgPool2d(3, stride=1, padding=1, count_include_pad=False), 74 | BasicConv2d(192, 64, kernel_size=1, stride=1) 75 | ) 76 | 77 | def forward(self, x): 78 | x0 = self.branch0(x) 79 | x1 = self.branch1(x) 80 | x2 = self.branch2(x) 81 | x3 = self.branch3(x) 82 | out = torch.cat((x0, x1, x2, x3), 1) 83 | return out 84 | 85 | 86 | class Block35(nn.Module): 87 | 88 | def __init__(self, scale=1.0): 89 | super(Block35, self).__init__() 90 | 91 | self.scale = scale 92 | 93 | self.branch0 = BasicConv2d(320, 32, kernel_size=1, stride=1) 94 | 95 | self.branch1 = nn.Sequential( 96 | BasicConv2d(320, 32, kernel_size=1, stride=1), 97 | BasicConv2d(32, 32, kernel_size=3, stride=1, padding=1) 98 | ) 99 | 100 | self.branch2 = nn.Sequential( 101 | BasicConv2d(320, 32, kernel_size=1, stride=1), 102 | BasicConv2d(32, 48, kernel_size=3, stride=1, padding=1), 103 | BasicConv2d(48, 64, kernel_size=3, stride=1, padding=1) 104 | ) 105 | 106 | self.conv2d = nn.Conv2d(128, 320, kernel_size=1, stride=1) 107 | self.relu = nn.ReLU(inplace=False) 108 | 109 | def forward(self, x): 110 | x0 = self.branch0(x) 111 | x1 = self.branch1(x) 112 | x2 = self.branch2(x) 113 | out = torch.cat((x0, x1, x2), 1) 114 | out = self.conv2d(out) 115 | out = out * self.scale + x 116 | out = self.relu(out) 117 | return out 118 | 119 | 120 | class Mixed_6a(nn.Module): 121 | 122 | def __init__(self): 123 | super(Mixed_6a, self).__init__() 124 | 125 | self.branch0 = BasicConv2d(320, 384, kernel_size=3, stride=2) 126 | 127 | self.branch1 = nn.Sequential( 128 | BasicConv2d(320, 256, kernel_size=1, stride=1), 129 | BasicConv2d(256, 256, kernel_size=3, stride=1, padding=1), 130 | BasicConv2d(256, 384, kernel_size=3, stride=2) 131 | ) 132 | 133 | self.branch2 = nn.MaxPool2d(3, stride=2) 134 | 135 | def forward(self, x): 136 | x0 = self.branch0(x) 137 | x1 = self.branch1(x) 138 | x2 = self.branch2(x) 139 | out = torch.cat((x0, x1, x2), 1) 140 | return out 141 | 142 | 143 | class Block17(nn.Module): 144 | 145 | def __init__(self, scale=1.0): 146 | super(Block17, self).__init__() 147 | 148 | self.scale = scale 149 | 150 | self.branch0 = BasicConv2d(1088, 192, kernel_size=1, stride=1) 151 | 152 | self.branch1 = nn.Sequential( 153 | BasicConv2d(1088, 128, kernel_size=1, stride=1), 154 | BasicConv2d(128, 160, kernel_size=(1,7), stride=1, padding=(0,3)), 155 | BasicConv2d(160, 192, kernel_size=(7,1), stride=1, padding=(3,0)) 156 | ) 157 | 158 | self.conv2d = nn.Conv2d(384, 1088, kernel_size=1, stride=1) 159 | self.relu = nn.ReLU(inplace=False) 160 | 161 | def forward(self, x): 162 | x0 = self.branch0(x) 163 | x1 = self.branch1(x) 164 | out = torch.cat((x0, x1), 1) 165 | out = self.conv2d(out) 166 | out = out * self.scale + x 167 | out = self.relu(out) 168 | return out 169 | 170 | 171 | class Mixed_7a(nn.Module): 172 | 173 | def __init__(self): 174 | super(Mixed_7a, self).__init__() 175 | 176 | self.branch0 = nn.Sequential( 177 | BasicConv2d(1088, 256, kernel_size=1, stride=1), 178 | BasicConv2d(256, 384, kernel_size=3, stride=2) 179 | ) 180 | 181 | self.branch1 = nn.Sequential( 182 | BasicConv2d(1088, 256, kernel_size=1, stride=1), 183 | BasicConv2d(256, 288, kernel_size=3, stride=2) 184 | ) 185 | 186 | self.branch2 = nn.Sequential( 187 | BasicConv2d(1088, 256, kernel_size=1, stride=1), 188 | BasicConv2d(256, 288, kernel_size=3, stride=1, padding=1), 189 | BasicConv2d(288, 320, kernel_size=3, stride=2) 190 | ) 191 | 192 | self.branch3 = nn.MaxPool2d(3, stride=2) 193 | 194 | def forward(self, x): 195 | x0 = self.branch0(x) 196 | x1 = self.branch1(x) 197 | x2 = self.branch2(x) 198 | x3 = self.branch3(x) 199 | out = torch.cat((x0, x1, x2, x3), 1) 200 | return out 201 | 202 | 203 | class Block8(nn.Module): 204 | 205 | def __init__(self, scale=1.0, noReLU=False): 206 | super(Block8, self).__init__() 207 | 208 | self.scale = scale 209 | self.noReLU = noReLU 210 | 211 | self.branch0 = BasicConv2d(2080, 192, kernel_size=1, stride=1) 212 | 213 | self.branch1 = nn.Sequential( 214 | BasicConv2d(2080, 192, kernel_size=1, stride=1), 215 | BasicConv2d(192, 224, kernel_size=(1,3), stride=1, padding=(0,1)), 216 | BasicConv2d(224, 256, kernel_size=(3,1), stride=1, padding=(1,0)) 217 | ) 218 | 219 | self.conv2d = nn.Conv2d(448, 2080, kernel_size=1, stride=1) 220 | if not self.noReLU: 221 | self.relu = nn.ReLU(inplace=False) 222 | 223 | def forward(self, x): 224 | x0 = self.branch0(x) 225 | x1 = self.branch1(x) 226 | out = torch.cat((x0, x1), 1) 227 | out = self.conv2d(out) 228 | out = out * self.scale + x 229 | if not self.noReLU: 230 | out = self.relu(out) 231 | return out 232 | 233 | 234 | class InceptionResNetV2(nn.Module): 235 | 236 | def __init__(self, num_classes=1001): 237 | super(InceptionResNetV2, self).__init__() 238 | # Special attributs 239 | self.input_space = None 240 | self.input_size = (299, 299, 3) 241 | self.mean = None 242 | self.std = None 243 | # Modules 244 | self.conv2d_1a = BasicConv2d(3, 32, kernel_size=3, stride=2) 245 | self.conv2d_2a = BasicConv2d(32, 32, kernel_size=3, stride=1) 246 | self.conv2d_2b = BasicConv2d(32, 64, kernel_size=3, stride=1, padding=1) 247 | self.maxpool_3a = nn.MaxPool2d(3, stride=2) 248 | self.conv2d_3b = BasicConv2d(64, 80, kernel_size=1, stride=1) 249 | self.conv2d_4a = BasicConv2d(80, 192, kernel_size=3, stride=1) 250 | self.maxpool_5a = nn.MaxPool2d(3, stride=2) 251 | self.mixed_5b = Mixed_5b() 252 | self.repeat = nn.Sequential( 253 | Block35(scale=0.17), 254 | Block35(scale=0.17), 255 | Block35(scale=0.17), 256 | Block35(scale=0.17), 257 | Block35(scale=0.17), 258 | Block35(scale=0.17), 259 | Block35(scale=0.17), 260 | Block35(scale=0.17), 261 | Block35(scale=0.17), 262 | Block35(scale=0.17) 263 | ) 264 | self.mixed_6a = Mixed_6a() 265 | self.repeat_1 = nn.Sequential( 266 | Block17(scale=0.10), 267 | Block17(scale=0.10), 268 | Block17(scale=0.10), 269 | Block17(scale=0.10), 270 | Block17(scale=0.10), 271 | Block17(scale=0.10), 272 | Block17(scale=0.10), 273 | Block17(scale=0.10), 274 | Block17(scale=0.10), 275 | Block17(scale=0.10), 276 | Block17(scale=0.10), 277 | Block17(scale=0.10), 278 | Block17(scale=0.10), 279 | Block17(scale=0.10), 280 | Block17(scale=0.10), 281 | Block17(scale=0.10), 282 | Block17(scale=0.10), 283 | Block17(scale=0.10), 284 | Block17(scale=0.10), 285 | Block17(scale=0.10) 286 | ) 287 | self.mixed_7a = Mixed_7a() 288 | self.repeat_2 = nn.Sequential( 289 | Block8(scale=0.20), 290 | Block8(scale=0.20), 291 | Block8(scale=0.20), 292 | Block8(scale=0.20), 293 | Block8(scale=0.20), 294 | Block8(scale=0.20), 295 | Block8(scale=0.20), 296 | Block8(scale=0.20), 297 | Block8(scale=0.20) 298 | ) 299 | self.block8 = Block8(noReLU=True) 300 | self.conv2d_7b = BasicConv2d(2080, 1536, kernel_size=1, stride=1) 301 | self.avgpool_1a = nn.AvgPool2d(8, count_include_pad=False) 302 | self.last_linear = nn.Linear(1536, num_classes) 303 | 304 | def features(self, input): 305 | x = self.conv2d_1a(input) 306 | x = self.conv2d_2a(x) 307 | x = self.conv2d_2b(x) 308 | x = self.maxpool_3a(x) 309 | x = self.conv2d_3b(x) 310 | x = self.conv2d_4a(x) 311 | x = self.maxpool_5a(x) 312 | x = self.mixed_5b(x) 313 | x = self.repeat(x) 314 | x = self.mixed_6a(x) 315 | x = self.repeat_1(x) 316 | x = self.mixed_7a(x) 317 | x = self.repeat_2(x) 318 | x = self.block8(x) 319 | x = self.conv2d_7b(x) 320 | return x 321 | 322 | def logits(self, features): 323 | x = self.avgpool_1a(features) 324 | x = x.view(x.size(0), -1) 325 | x = self.last_linear(x) 326 | return x 327 | 328 | def forward(self, input): 329 | x = self.features(input) 330 | x = self.logits(x) 331 | return x 332 | 333 | def inceptionresnetv2(num_classes=1000, pretrained='imagenet'): 334 | r"""InceptionResNetV2 model architecture from the 335 | `"InceptionV4, Inception-ResNet..." `_ paper. 336 | """ 337 | if pretrained: 338 | settings = pretrained_settings['inceptionresnetv2'][pretrained] 339 | assert num_classes == settings['num_classes'], \ 340 | "num_classes should be {}, but is {}".format(settings['num_classes'], num_classes) 341 | 342 | # both 'imagenet'&'imagenet+background' are loaded from same parameters 343 | model = InceptionResNetV2(num_classes=1001) 344 | model.load_state_dict(model_zoo.load_url(settings['url'])) 345 | 346 | if pretrained == 'imagenet': 347 | new_last_linear = nn.Linear(1536, 1000) 348 | new_last_linear.weight.data = model.last_linear.weight.data[1:] 349 | new_last_linear.bias.data = model.last_linear.bias.data[1:] 350 | model.last_linear = new_last_linear 351 | 352 | model.input_space = settings['input_space'] 353 | model.input_size = settings['input_size'] 354 | model.input_range = settings['input_range'] 355 | 356 | model.mean = settings['mean'] 357 | model.std = settings['std'] 358 | else: 359 | model = InceptionResNetV2(num_classes=num_classes) 360 | return model 361 | 362 | ''' 363 | TEST 364 | Run this code with: 365 | ``` 366 | cd $HOME/pretrained-models.pytorch 367 | python -m pretrainedmodels.inceptionresnetv2 368 | ``` 369 | ''' 370 | if __name__ == '__main__': 371 | 372 | assert inceptionresnetv2(num_classes=10, pretrained=None) 373 | print('success') 374 | assert inceptionresnetv2(num_classes=1000, pretrained='imagenet') 375 | print('success') 376 | assert inceptionresnetv2(num_classes=1001, pretrained='imagenet+background') 377 | print('success') 378 | 379 | # fail 380 | assert inceptionresnetv2(num_classes=1001, pretrained='imagenet') -------------------------------------------------------------------------------- /pretrainedmodels/models/inceptionv4.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function, division, absolute_import 2 | import torch 3 | import torch.nn as nn 4 | import torch.nn.functional as F 5 | import torch.utils.model_zoo as model_zoo 6 | import os 7 | import sys 8 | 9 | __all__ = ['InceptionV4', 'inceptionv4'] 10 | 11 | pretrained_settings = { 12 | 'inceptionv4': { 13 | 'imagenet': { 14 | 'url': 'http://data.lip6.fr/cadene/pretrainedmodels/inceptionv4-8e4777a0.pth', 15 | 'input_space': 'RGB', 16 | 'input_size': [3, 299, 299], 17 | 'input_range': [0, 1], 18 | 'mean': [0.5, 0.5, 0.5], 19 | 'std': [0.5, 0.5, 0.5], 20 | 'num_classes': 1000 21 | }, 22 | 'imagenet+background': { 23 | 'url': 'http://data.lip6.fr/cadene/pretrainedmodels/inceptionv4-8e4777a0.pth', 24 | 'input_space': 'RGB', 25 | 'input_size': [3, 299, 299], 26 | 'input_range': [0, 1], 27 | 'mean': [0.5, 0.5, 0.5], 28 | 'std': [0.5, 0.5, 0.5], 29 | 'num_classes': 1001 30 | } 31 | } 32 | } 33 | 34 | 35 | class BasicConv2d(nn.Module): 36 | 37 | def __init__(self, in_planes, out_planes, kernel_size, stride, padding=0): 38 | super(BasicConv2d, self).__init__() 39 | self.conv = nn.Conv2d(in_planes, out_planes, 40 | kernel_size=kernel_size, stride=stride, 41 | padding=padding, bias=False) # verify bias false 42 | self.bn = nn.BatchNorm2d(out_planes, 43 | eps=0.001, # value found in tensorflow 44 | momentum=0.1, # default pytorch value 45 | affine=True) 46 | self.relu = nn.ReLU(inplace=True) 47 | 48 | def forward(self, x): 49 | x = self.conv(x) 50 | x = self.bn(x) 51 | x = self.relu(x) 52 | return x 53 | 54 | 55 | class Mixed_3a(nn.Module): 56 | 57 | def __init__(self): 58 | super(Mixed_3a, self).__init__() 59 | self.maxpool = nn.MaxPool2d(3, stride=2) 60 | self.conv = BasicConv2d(64, 96, kernel_size=3, stride=2) 61 | 62 | def forward(self, x): 63 | x0 = self.maxpool(x) 64 | x1 = self.conv(x) 65 | out = torch.cat((x0, x1), 1) 66 | return out 67 | 68 | 69 | class Mixed_4a(nn.Module): 70 | 71 | def __init__(self): 72 | super(Mixed_4a, self).__init__() 73 | 74 | self.branch0 = nn.Sequential( 75 | BasicConv2d(160, 64, kernel_size=1, stride=1), 76 | BasicConv2d(64, 96, kernel_size=3, stride=1) 77 | ) 78 | 79 | self.branch1 = nn.Sequential( 80 | BasicConv2d(160, 64, kernel_size=1, stride=1), 81 | BasicConv2d(64, 64, kernel_size=(1,7), stride=1, padding=(0,3)), 82 | BasicConv2d(64, 64, kernel_size=(7,1), stride=1, padding=(3,0)), 83 | BasicConv2d(64, 96, kernel_size=(3,3), stride=1) 84 | ) 85 | 86 | def forward(self, x): 87 | x0 = self.branch0(x) 88 | x1 = self.branch1(x) 89 | out = torch.cat((x0, x1), 1) 90 | return out 91 | 92 | 93 | class Mixed_5a(nn.Module): 94 | 95 | def __init__(self): 96 | super(Mixed_5a, self).__init__() 97 | self.conv = BasicConv2d(192, 192, kernel_size=3, stride=2) 98 | self.maxpool = nn.MaxPool2d(3, stride=2) 99 | 100 | def forward(self, x): 101 | x0 = self.conv(x) 102 | x1 = self.maxpool(x) 103 | out = torch.cat((x0, x1), 1) 104 | return out 105 | 106 | 107 | class Inception_A(nn.Module): 108 | 109 | def __init__(self): 110 | super(Inception_A, self).__init__() 111 | self.branch0 = BasicConv2d(384, 96, kernel_size=1, stride=1) 112 | 113 | self.branch1 = nn.Sequential( 114 | BasicConv2d(384, 64, kernel_size=1, stride=1), 115 | BasicConv2d(64, 96, kernel_size=3, stride=1, padding=1) 116 | ) 117 | 118 | self.branch2 = nn.Sequential( 119 | BasicConv2d(384, 64, kernel_size=1, stride=1), 120 | BasicConv2d(64, 96, kernel_size=3, stride=1, padding=1), 121 | BasicConv2d(96, 96, kernel_size=3, stride=1, padding=1) 122 | ) 123 | 124 | self.branch3 = nn.Sequential( 125 | nn.AvgPool2d(3, stride=1, padding=1, count_include_pad=False), 126 | BasicConv2d(384, 96, kernel_size=1, stride=1) 127 | ) 128 | 129 | def forward(self, x): 130 | x0 = self.branch0(x) 131 | x1 = self.branch1(x) 132 | x2 = self.branch2(x) 133 | x3 = self.branch3(x) 134 | out = torch.cat((x0, x1, x2, x3), 1) 135 | return out 136 | 137 | 138 | class Reduction_A(nn.Module): 139 | 140 | def __init__(self): 141 | super(Reduction_A, self).__init__() 142 | self.branch0 = BasicConv2d(384, 384, kernel_size=3, stride=2) 143 | 144 | self.branch1 = nn.Sequential( 145 | BasicConv2d(384, 192, kernel_size=1, stride=1), 146 | BasicConv2d(192, 224, kernel_size=3, stride=1, padding=1), 147 | BasicConv2d(224, 256, kernel_size=3, stride=2) 148 | ) 149 | 150 | self.branch2 = nn.MaxPool2d(3, stride=2) 151 | 152 | def forward(self, x): 153 | x0 = self.branch0(x) 154 | x1 = self.branch1(x) 155 | x2 = self.branch2(x) 156 | out = torch.cat((x0, x1, x2), 1) 157 | return out 158 | 159 | 160 | class Inception_B(nn.Module): 161 | 162 | def __init__(self): 163 | super(Inception_B, self).__init__() 164 | self.branch0 = BasicConv2d(1024, 384, kernel_size=1, stride=1) 165 | 166 | self.branch1 = nn.Sequential( 167 | BasicConv2d(1024, 192, kernel_size=1, stride=1), 168 | BasicConv2d(192, 224, kernel_size=(1,7), stride=1, padding=(0,3)), 169 | BasicConv2d(224, 256, kernel_size=(7,1), stride=1, padding=(3,0)) 170 | ) 171 | 172 | self.branch2 = nn.Sequential( 173 | BasicConv2d(1024, 192, kernel_size=1, stride=1), 174 | BasicConv2d(192, 192, kernel_size=(7,1), stride=1, padding=(3,0)), 175 | BasicConv2d(192, 224, kernel_size=(1,7), stride=1, padding=(0,3)), 176 | BasicConv2d(224, 224, kernel_size=(7,1), stride=1, padding=(3,0)), 177 | BasicConv2d(224, 256, kernel_size=(1,7), stride=1, padding=(0,3)) 178 | ) 179 | 180 | self.branch3 = nn.Sequential( 181 | nn.AvgPool2d(3, stride=1, padding=1, count_include_pad=False), 182 | BasicConv2d(1024, 128, kernel_size=1, stride=1) 183 | ) 184 | 185 | def forward(self, x): 186 | x0 = self.branch0(x) 187 | x1 = self.branch1(x) 188 | x2 = self.branch2(x) 189 | x3 = self.branch3(x) 190 | out = torch.cat((x0, x1, x2, x3), 1) 191 | return out 192 | 193 | 194 | class Reduction_B(nn.Module): 195 | 196 | def __init__(self): 197 | super(Reduction_B, self).__init__() 198 | 199 | self.branch0 = nn.Sequential( 200 | BasicConv2d(1024, 192, kernel_size=1, stride=1), 201 | BasicConv2d(192, 192, kernel_size=3, stride=2) 202 | ) 203 | 204 | self.branch1 = nn.Sequential( 205 | BasicConv2d(1024, 256, kernel_size=1, stride=1), 206 | BasicConv2d(256, 256, kernel_size=(1,7), stride=1, padding=(0,3)), 207 | BasicConv2d(256, 320, kernel_size=(7,1), stride=1, padding=(3,0)), 208 | BasicConv2d(320, 320, kernel_size=3, stride=2) 209 | ) 210 | 211 | self.branch2 = nn.MaxPool2d(3, stride=2) 212 | 213 | def forward(self, x): 214 | x0 = self.branch0(x) 215 | x1 = self.branch1(x) 216 | x2 = self.branch2(x) 217 | out = torch.cat((x0, x1, x2), 1) 218 | return out 219 | 220 | 221 | class Inception_C(nn.Module): 222 | 223 | def __init__(self): 224 | super(Inception_C, self).__init__() 225 | 226 | self.branch0 = BasicConv2d(1536, 256, kernel_size=1, stride=1) 227 | 228 | self.branch1_0 = BasicConv2d(1536, 384, kernel_size=1, stride=1) 229 | self.branch1_1a = BasicConv2d(384, 256, kernel_size=(1,3), stride=1, padding=(0,1)) 230 | self.branch1_1b = BasicConv2d(384, 256, kernel_size=(3,1), stride=1, padding=(1,0)) 231 | 232 | self.branch2_0 = BasicConv2d(1536, 384, kernel_size=1, stride=1) 233 | self.branch2_1 = BasicConv2d(384, 448, kernel_size=(3,1), stride=1, padding=(1,0)) 234 | self.branch2_2 = BasicConv2d(448, 512, kernel_size=(1,3), stride=1, padding=(0,1)) 235 | self.branch2_3a = BasicConv2d(512, 256, kernel_size=(1,3), stride=1, padding=(0,1)) 236 | self.branch2_3b = BasicConv2d(512, 256, kernel_size=(3,1), stride=1, padding=(1,0)) 237 | 238 | self.branch3 = nn.Sequential( 239 | nn.AvgPool2d(3, stride=1, padding=1, count_include_pad=False), 240 | BasicConv2d(1536, 256, kernel_size=1, stride=1) 241 | ) 242 | 243 | def forward(self, x): 244 | x0 = self.branch0(x) 245 | 246 | x1_0 = self.branch1_0(x) 247 | x1_1a = self.branch1_1a(x1_0) 248 | x1_1b = self.branch1_1b(x1_0) 249 | x1 = torch.cat((x1_1a, x1_1b), 1) 250 | 251 | x2_0 = self.branch2_0(x) 252 | x2_1 = self.branch2_1(x2_0) 253 | x2_2 = self.branch2_2(x2_1) 254 | x2_3a = self.branch2_3a(x2_2) 255 | x2_3b = self.branch2_3b(x2_2) 256 | x2 = torch.cat((x2_3a, x2_3b), 1) 257 | 258 | x3 = self.branch3(x) 259 | 260 | out = torch.cat((x0, x1, x2, x3), 1) 261 | return out 262 | 263 | 264 | class InceptionV4(nn.Module): 265 | 266 | def __init__(self, num_classes=1001): 267 | super(InceptionV4, self).__init__() 268 | # Special attributs 269 | self.input_space = None 270 | self.input_size = (299, 299, 3) 271 | self.mean = None 272 | self.std = None 273 | # Modules 274 | self.features = nn.Sequential( 275 | BasicConv2d(3, 32, kernel_size=3, stride=2), 276 | BasicConv2d(32, 32, kernel_size=3, stride=1), 277 | BasicConv2d(32, 64, kernel_size=3, stride=1, padding=1), 278 | Mixed_3a(), 279 | Mixed_4a(), 280 | Mixed_5a(), 281 | Inception_A(), 282 | Inception_A(), 283 | Inception_A(), 284 | Inception_A(), 285 | Reduction_A(), # Mixed_6a 286 | Inception_B(), 287 | Inception_B(), 288 | Inception_B(), 289 | Inception_B(), 290 | Inception_B(), 291 | Inception_B(), 292 | Inception_B(), 293 | Reduction_B(), # Mixed_7a 294 | Inception_C(), 295 | Inception_C(), 296 | Inception_C() 297 | ) 298 | self.last_linear = nn.Linear(1536, num_classes) 299 | 300 | def logits(self, features): 301 | #Allows image of any size to be processed 302 | adaptiveAvgPoolWidth = features.shape[2] 303 | x = F.avg_pool2d(features, kernel_size=adaptiveAvgPoolWidth) 304 | x = x.view(x.size(0), -1) 305 | x = self.last_linear(x) 306 | return x 307 | 308 | def forward(self, input): 309 | x = self.features(input) 310 | x = self.logits(x) 311 | return x 312 | 313 | 314 | def inceptionv4(num_classes=1000, pretrained='imagenet'): 315 | if pretrained: 316 | settings = pretrained_settings['inceptionv4'][pretrained] 317 | assert num_classes == settings['num_classes'], \ 318 | "num_classes should be {}, but is {}".format(settings['num_classes'], num_classes) 319 | 320 | # both 'imagenet'&'imagenet+background' are loaded from same parameters 321 | model = InceptionV4(num_classes=1001) 322 | model.load_state_dict(model_zoo.load_url(settings['url'])) 323 | 324 | if pretrained == 'imagenet': 325 | new_last_linear = nn.Linear(1536, 1000) 326 | new_last_linear.weight.data = model.last_linear.weight.data[1:] 327 | new_last_linear.bias.data = model.last_linear.bias.data[1:] 328 | model.last_linear = new_last_linear 329 | 330 | model.input_space = settings['input_space'] 331 | model.input_size = settings['input_size'] 332 | model.input_range = settings['input_range'] 333 | model.mean = settings['mean'] 334 | model.std = settings['std'] 335 | else: 336 | model = InceptionV4(num_classes=num_classes) 337 | return model 338 | 339 | 340 | ''' 341 | TEST 342 | Run this code with: 343 | ``` 344 | cd $HOME/pretrained-models.pytorch 345 | python -m pretrainedmodels.inceptionv4 346 | ``` 347 | ''' 348 | if __name__ == '__main__': 349 | 350 | assert inceptionv4(num_classes=10, pretrained=None) 351 | print('success') 352 | assert inceptionv4(num_classes=1000, pretrained='imagenet') 353 | print('success') 354 | assert inceptionv4(num_classes=1001, pretrained='imagenet+background') 355 | print('success') 356 | 357 | # fail 358 | assert inceptionv4(num_classes=1001, pretrained='imagenet') 359 | -------------------------------------------------------------------------------- /pretrainedmodels/models/pnasnet.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function, division, absolute_import 2 | from collections import OrderedDict 3 | 4 | import torch 5 | import torch.nn as nn 6 | import torch.utils.model_zoo as model_zoo 7 | 8 | 9 | pretrained_settings = { 10 | 'pnasnet5large': { 11 | 'imagenet': { 12 | 'url': 'http://data.lip6.fr/cadene/pretrainedmodels/pnasnet5large-bf079911.pth', 13 | 'input_space': 'RGB', 14 | 'input_size': [3, 331, 331], 15 | 'input_range': [0, 1], 16 | 'mean': [0.5, 0.5, 0.5], 17 | 'std': [0.5, 0.5, 0.5], 18 | 'num_classes': 1000 19 | }, 20 | 'imagenet+background': { 21 | 'url': 'http://data.lip6.fr/cadene/pretrainedmodels/pnasnet5large-bf079911.pth', 22 | 'input_space': 'RGB', 23 | 'input_size': [3, 331, 331], 24 | 'input_range': [0, 1], 25 | 'mean': [0.5, 0.5, 0.5], 26 | 'std': [0.5, 0.5, 0.5], 27 | 'num_classes': 1001 28 | } 29 | } 30 | } 31 | 32 | 33 | class MaxPool(nn.Module): 34 | 35 | def __init__(self, kernel_size, stride=1, padding=1, zero_pad=False): 36 | super(MaxPool, self).__init__() 37 | self.zero_pad = nn.ZeroPad2d((1, 0, 1, 0)) if zero_pad else None 38 | self.pool = nn.MaxPool2d(kernel_size, stride=stride, padding=padding) 39 | 40 | def forward(self, x): 41 | if self.zero_pad: 42 | x = self.zero_pad(x) 43 | x = self.pool(x) 44 | if self.zero_pad: 45 | x = x[:, :, 1:, 1:] 46 | return x 47 | 48 | 49 | class SeparableConv2d(nn.Module): 50 | 51 | def __init__(self, in_channels, out_channels, dw_kernel_size, dw_stride, 52 | dw_padding): 53 | super(SeparableConv2d, self).__init__() 54 | self.depthwise_conv2d = nn.Conv2d(in_channels, in_channels, 55 | kernel_size=dw_kernel_size, 56 | stride=dw_stride, padding=dw_padding, 57 | groups=in_channels, bias=False) 58 | self.pointwise_conv2d = nn.Conv2d(in_channels, out_channels, 59 | kernel_size=1, bias=False) 60 | 61 | def forward(self, x): 62 | x = self.depthwise_conv2d(x) 63 | x = self.pointwise_conv2d(x) 64 | return x 65 | 66 | 67 | class BranchSeparables(nn.Module): 68 | 69 | def __init__(self, in_channels, out_channels, kernel_size, stride=1, 70 | stem_cell=False, zero_pad=False): 71 | super(BranchSeparables, self).__init__() 72 | padding = kernel_size // 2 73 | middle_channels = out_channels if stem_cell else in_channels 74 | self.zero_pad = nn.ZeroPad2d((1, 0, 1, 0)) if zero_pad else None 75 | self.relu_1 = nn.ReLU() 76 | self.separable_1 = SeparableConv2d(in_channels, middle_channels, 77 | kernel_size, dw_stride=stride, 78 | dw_padding=padding) 79 | self.bn_sep_1 = nn.BatchNorm2d(middle_channels, eps=0.001) 80 | self.relu_2 = nn.ReLU() 81 | self.separable_2 = SeparableConv2d(middle_channels, out_channels, 82 | kernel_size, dw_stride=1, 83 | dw_padding=padding) 84 | self.bn_sep_2 = nn.BatchNorm2d(out_channels, eps=0.001) 85 | 86 | def forward(self, x): 87 | x = self.relu_1(x) 88 | if self.zero_pad: 89 | x = self.zero_pad(x) 90 | x = self.separable_1(x) 91 | if self.zero_pad: 92 | x = x[:, :, 1:, 1:].contiguous() 93 | x = self.bn_sep_1(x) 94 | x = self.relu_2(x) 95 | x = self.separable_2(x) 96 | x = self.bn_sep_2(x) 97 | return x 98 | 99 | 100 | class ReluConvBn(nn.Module): 101 | 102 | def __init__(self, in_channels, out_channels, kernel_size, stride=1): 103 | super(ReluConvBn, self).__init__() 104 | self.relu = nn.ReLU() 105 | self.conv = nn.Conv2d(in_channels, out_channels, 106 | kernel_size=kernel_size, stride=stride, 107 | bias=False) 108 | self.bn = nn.BatchNorm2d(out_channels, eps=0.001) 109 | 110 | def forward(self, x): 111 | x = self.relu(x) 112 | x = self.conv(x) 113 | x = self.bn(x) 114 | return x 115 | 116 | 117 | class FactorizedReduction(nn.Module): 118 | 119 | def __init__(self, in_channels, out_channels): 120 | super(FactorizedReduction, self).__init__() 121 | self.relu = nn.ReLU() 122 | self.path_1 = nn.Sequential(OrderedDict([ 123 | ('avgpool', nn.AvgPool2d(1, stride=2, count_include_pad=False)), 124 | ('conv', nn.Conv2d(in_channels, out_channels // 2, 125 | kernel_size=1, bias=False)), 126 | ])) 127 | self.path_2 = nn.Sequential(OrderedDict([ 128 | ('pad', nn.ZeroPad2d((0, 1, 0, 1))), 129 | ('avgpool', nn.AvgPool2d(1, stride=2, count_include_pad=False)), 130 | ('conv', nn.Conv2d(in_channels, out_channels // 2, 131 | kernel_size=1, bias=False)), 132 | ])) 133 | self.final_path_bn = nn.BatchNorm2d(out_channels, eps=0.001) 134 | 135 | def forward(self, x): 136 | x = self.relu(x) 137 | 138 | x_path1 = self.path_1(x) 139 | 140 | x_path2 = self.path_2.pad(x) 141 | x_path2 = x_path2[:, :, 1:, 1:] 142 | x_path2 = self.path_2.avgpool(x_path2) 143 | x_path2 = self.path_2.conv(x_path2) 144 | 145 | out = self.final_path_bn(torch.cat([x_path1, x_path2], 1)) 146 | return out 147 | 148 | 149 | class CellBase(nn.Module): 150 | 151 | def cell_forward(self, x_left, x_right): 152 | x_comb_iter_0_left = self.comb_iter_0_left(x_left) 153 | x_comb_iter_0_right = self.comb_iter_0_right(x_left) 154 | x_comb_iter_0 = x_comb_iter_0_left + x_comb_iter_0_right 155 | 156 | x_comb_iter_1_left = self.comb_iter_1_left(x_right) 157 | x_comb_iter_1_right = self.comb_iter_1_right(x_right) 158 | x_comb_iter_1 = x_comb_iter_1_left + x_comb_iter_1_right 159 | 160 | x_comb_iter_2_left = self.comb_iter_2_left(x_right) 161 | x_comb_iter_2_right = self.comb_iter_2_right(x_right) 162 | x_comb_iter_2 = x_comb_iter_2_left + x_comb_iter_2_right 163 | 164 | x_comb_iter_3_left = self.comb_iter_3_left(x_comb_iter_2) 165 | x_comb_iter_3_right = self.comb_iter_3_right(x_right) 166 | x_comb_iter_3 = x_comb_iter_3_left + x_comb_iter_3_right 167 | 168 | x_comb_iter_4_left = self.comb_iter_4_left(x_left) 169 | if self.comb_iter_4_right: 170 | x_comb_iter_4_right = self.comb_iter_4_right(x_right) 171 | else: 172 | x_comb_iter_4_right = x_right 173 | x_comb_iter_4 = x_comb_iter_4_left + x_comb_iter_4_right 174 | 175 | x_out = torch.cat( 176 | [x_comb_iter_0, x_comb_iter_1, x_comb_iter_2, x_comb_iter_3, 177 | x_comb_iter_4], 1) 178 | return x_out 179 | 180 | 181 | class CellStem0(CellBase): 182 | 183 | def __init__(self, in_channels_left, out_channels_left, in_channels_right, 184 | out_channels_right): 185 | super(CellStem0, self).__init__() 186 | self.conv_1x1 = ReluConvBn(in_channels_right, out_channels_right, 187 | kernel_size=1) 188 | self.comb_iter_0_left = BranchSeparables(in_channels_left, 189 | out_channels_left, 190 | kernel_size=5, stride=2, 191 | stem_cell=True) 192 | self.comb_iter_0_right = nn.Sequential(OrderedDict([ 193 | ('max_pool', MaxPool(3, stride=2)), 194 | ('conv', nn.Conv2d(in_channels_left, out_channels_left, 195 | kernel_size=1, bias=False)), 196 | ('bn', nn.BatchNorm2d(out_channels_left, eps=0.001)), 197 | ])) 198 | self.comb_iter_1_left = BranchSeparables(out_channels_right, 199 | out_channels_right, 200 | kernel_size=7, stride=2) 201 | self.comb_iter_1_right = MaxPool(3, stride=2) 202 | self.comb_iter_2_left = BranchSeparables(out_channels_right, 203 | out_channels_right, 204 | kernel_size=5, stride=2) 205 | self.comb_iter_2_right = BranchSeparables(out_channels_right, 206 | out_channels_right, 207 | kernel_size=3, stride=2) 208 | self.comb_iter_3_left = BranchSeparables(out_channels_right, 209 | out_channels_right, 210 | kernel_size=3) 211 | self.comb_iter_3_right = MaxPool(3, stride=2) 212 | self.comb_iter_4_left = BranchSeparables(in_channels_right, 213 | out_channels_right, 214 | kernel_size=3, stride=2, 215 | stem_cell=True) 216 | self.comb_iter_4_right = ReluConvBn(out_channels_right, 217 | out_channels_right, 218 | kernel_size=1, stride=2) 219 | 220 | def forward(self, x_left): 221 | x_right = self.conv_1x1(x_left) 222 | x_out = self.cell_forward(x_left, x_right) 223 | return x_out 224 | 225 | 226 | class Cell(CellBase): 227 | 228 | def __init__(self, in_channels_left, out_channels_left, in_channels_right, 229 | out_channels_right, is_reduction=False, zero_pad=False, 230 | match_prev_layer_dimensions=False): 231 | super(Cell, self).__init__() 232 | 233 | # If `is_reduction` is set to `True` stride 2 is used for 234 | # convolutional and pooling layers to reduce the spatial size of 235 | # the output of a cell approximately by a factor of 2. 236 | stride = 2 if is_reduction else 1 237 | 238 | # If `match_prev_layer_dimensions` is set to `True` 239 | # `FactorizedReduction` is used to reduce the spatial size 240 | # of the left input of a cell approximately by a factor of 2. 241 | self.match_prev_layer_dimensions = match_prev_layer_dimensions 242 | if match_prev_layer_dimensions: 243 | self.conv_prev_1x1 = FactorizedReduction(in_channels_left, 244 | out_channels_left) 245 | else: 246 | self.conv_prev_1x1 = ReluConvBn(in_channels_left, 247 | out_channels_left, kernel_size=1) 248 | 249 | self.conv_1x1 = ReluConvBn(in_channels_right, out_channels_right, 250 | kernel_size=1) 251 | self.comb_iter_0_left = BranchSeparables(out_channels_left, 252 | out_channels_left, 253 | kernel_size=5, stride=stride, 254 | zero_pad=zero_pad) 255 | self.comb_iter_0_right = MaxPool(3, stride=stride, zero_pad=zero_pad) 256 | self.comb_iter_1_left = BranchSeparables(out_channels_right, 257 | out_channels_right, 258 | kernel_size=7, stride=stride, 259 | zero_pad=zero_pad) 260 | self.comb_iter_1_right = MaxPool(3, stride=stride, zero_pad=zero_pad) 261 | self.comb_iter_2_left = BranchSeparables(out_channels_right, 262 | out_channels_right, 263 | kernel_size=5, stride=stride, 264 | zero_pad=zero_pad) 265 | self.comb_iter_2_right = BranchSeparables(out_channels_right, 266 | out_channels_right, 267 | kernel_size=3, stride=stride, 268 | zero_pad=zero_pad) 269 | self.comb_iter_3_left = BranchSeparables(out_channels_right, 270 | out_channels_right, 271 | kernel_size=3) 272 | self.comb_iter_3_right = MaxPool(3, stride=stride, zero_pad=zero_pad) 273 | self.comb_iter_4_left = BranchSeparables(out_channels_left, 274 | out_channels_left, 275 | kernel_size=3, stride=stride, 276 | zero_pad=zero_pad) 277 | if is_reduction: 278 | self.comb_iter_4_right = ReluConvBn(out_channels_right, 279 | out_channels_right, 280 | kernel_size=1, stride=stride) 281 | else: 282 | self.comb_iter_4_right = None 283 | 284 | def forward(self, x_left, x_right): 285 | x_left = self.conv_prev_1x1(x_left) 286 | x_right = self.conv_1x1(x_right) 287 | x_out = self.cell_forward(x_left, x_right) 288 | return x_out 289 | 290 | 291 | class PNASNet5Large(nn.Module): 292 | def __init__(self, num_classes=1001): 293 | super(PNASNet5Large, self).__init__() 294 | self.num_classes = num_classes 295 | self.conv_0 = nn.Sequential(OrderedDict([ 296 | ('conv', nn.Conv2d(3, 96, kernel_size=3, stride=2, bias=False)), 297 | ('bn', nn.BatchNorm2d(96, eps=0.001)) 298 | ])) 299 | self.cell_stem_0 = CellStem0(in_channels_left=96, out_channels_left=54, 300 | in_channels_right=96, 301 | out_channels_right=54) 302 | self.cell_stem_1 = Cell(in_channels_left=96, out_channels_left=108, 303 | in_channels_right=270, out_channels_right=108, 304 | match_prev_layer_dimensions=True, 305 | is_reduction=True) 306 | self.cell_0 = Cell(in_channels_left=270, out_channels_left=216, 307 | in_channels_right=540, out_channels_right=216, 308 | match_prev_layer_dimensions=True) 309 | self.cell_1 = Cell(in_channels_left=540, out_channels_left=216, 310 | in_channels_right=1080, out_channels_right=216) 311 | self.cell_2 = Cell(in_channels_left=1080, out_channels_left=216, 312 | in_channels_right=1080, out_channels_right=216) 313 | self.cell_3 = Cell(in_channels_left=1080, out_channels_left=216, 314 | in_channels_right=1080, out_channels_right=216) 315 | self.cell_4 = Cell(in_channels_left=1080, out_channels_left=432, 316 | in_channels_right=1080, out_channels_right=432, 317 | is_reduction=True, zero_pad=True) 318 | self.cell_5 = Cell(in_channels_left=1080, out_channels_left=432, 319 | in_channels_right=2160, out_channels_right=432, 320 | match_prev_layer_dimensions=True) 321 | self.cell_6 = Cell(in_channels_left=2160, out_channels_left=432, 322 | in_channels_right=2160, out_channels_right=432) 323 | self.cell_7 = Cell(in_channels_left=2160, out_channels_left=432, 324 | in_channels_right=2160, out_channels_right=432) 325 | self.cell_8 = Cell(in_channels_left=2160, out_channels_left=864, 326 | in_channels_right=2160, out_channels_right=864, 327 | is_reduction=True) 328 | self.cell_9 = Cell(in_channels_left=2160, out_channels_left=864, 329 | in_channels_right=4320, out_channels_right=864, 330 | match_prev_layer_dimensions=True) 331 | self.cell_10 = Cell(in_channels_left=4320, out_channels_left=864, 332 | in_channels_right=4320, out_channels_right=864) 333 | self.cell_11 = Cell(in_channels_left=4320, out_channels_left=864, 334 | in_channels_right=4320, out_channels_right=864) 335 | self.relu = nn.ReLU() 336 | self.avg_pool = nn.AvgPool2d(11, stride=1, padding=0) 337 | self.dropout = nn.Dropout(0.5) 338 | self.last_linear = nn.Linear(4320, num_classes) 339 | 340 | def features(self, x): 341 | x_conv_0 = self.conv_0(x) 342 | x_stem_0 = self.cell_stem_0(x_conv_0) 343 | x_stem_1 = self.cell_stem_1(x_conv_0, x_stem_0) 344 | x_cell_0 = self.cell_0(x_stem_0, x_stem_1) 345 | x_cell_1 = self.cell_1(x_stem_1, x_cell_0) 346 | x_cell_2 = self.cell_2(x_cell_0, x_cell_1) 347 | x_cell_3 = self.cell_3(x_cell_1, x_cell_2) 348 | x_cell_4 = self.cell_4(x_cell_2, x_cell_3) 349 | x_cell_5 = self.cell_5(x_cell_3, x_cell_4) 350 | x_cell_6 = self.cell_6(x_cell_4, x_cell_5) 351 | x_cell_7 = self.cell_7(x_cell_5, x_cell_6) 352 | x_cell_8 = self.cell_8(x_cell_6, x_cell_7) 353 | x_cell_9 = self.cell_9(x_cell_7, x_cell_8) 354 | x_cell_10 = self.cell_10(x_cell_8, x_cell_9) 355 | x_cell_11 = self.cell_11(x_cell_9, x_cell_10) 356 | return x_cell_11 357 | 358 | def logits(self, features): 359 | x = self.relu(features) 360 | x = self.avg_pool(x) 361 | x = x.view(x.size(0), -1) 362 | x = self.dropout(x) 363 | x = self.last_linear(x) 364 | return x 365 | 366 | def forward(self, input): 367 | x = self.features(input) 368 | x = self.logits(x) 369 | return x 370 | 371 | 372 | def pnasnet5large(num_classes=1001, pretrained='imagenet'): 373 | r"""PNASNet-5 model architecture from the 374 | `"Progressive Neural Architecture Search" 375 | `_ paper. 376 | """ 377 | if pretrained: 378 | settings = pretrained_settings['pnasnet5large'][pretrained] 379 | assert num_classes == settings[ 380 | 'num_classes'], 'num_classes should be {}, but is {}'.format( 381 | settings['num_classes'], num_classes) 382 | 383 | # both 'imagenet'&'imagenet+background' are loaded from same parameters 384 | model = PNASNet5Large(num_classes=1001) 385 | model.load_state_dict(model_zoo.load_url(settings['url'])) 386 | 387 | if pretrained == 'imagenet': 388 | new_last_linear = nn.Linear(model.last_linear.in_features, 1000) 389 | new_last_linear.weight.data = model.last_linear.weight.data[1:] 390 | new_last_linear.bias.data = model.last_linear.bias.data[1:] 391 | model.last_linear = new_last_linear 392 | 393 | model.input_space = settings['input_space'] 394 | model.input_size = settings['input_size'] 395 | model.input_range = settings['input_range'] 396 | 397 | model.mean = settings['mean'] 398 | model.std = settings['std'] 399 | else: 400 | model = PNASNet5Large(num_classes=num_classes) 401 | return model 402 | -------------------------------------------------------------------------------- /pretrainedmodels/models/polynet.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function, division, absolute_import 2 | import torch 3 | import torch.nn as nn 4 | from torch.utils import model_zoo 5 | 6 | __all__ = ['PolyNet', 'polynet'] 7 | 8 | pretrained_settings = { 9 | 'polynet': { 10 | 'imagenet': { 11 | 'url': 'http://data.lip6.fr/cadene/pretrainedmodels/polynet-f71d82a5.pth', 12 | 'input_space': 'RGB', 13 | 'input_size': [3, 331, 331], 14 | 'input_range': [0, 1], 15 | 'mean': [0.485, 0.456, 0.406], 16 | 'std': [0.229, 0.224, 0.225], 17 | 'num_classes': 1000 18 | }, 19 | } 20 | } 21 | 22 | 23 | class BasicConv2d(nn.Module): 24 | 25 | def __init__(self, in_planes, out_planes, kernel_size, stride=1, padding=0, 26 | output_relu=True): 27 | super(BasicConv2d, self).__init__() 28 | self.conv = nn.Conv2d(in_planes, out_planes, kernel_size=kernel_size, 29 | stride=stride, padding=padding, bias=False) 30 | self.bn = nn.BatchNorm2d(out_planes) 31 | self.relu = nn.ReLU() if output_relu else None 32 | 33 | def forward(self, x): 34 | x = self.conv(x) 35 | x = self.bn(x) 36 | if self.relu: 37 | x = self.relu(x) 38 | return x 39 | 40 | 41 | class PolyConv2d(nn.Module): 42 | """A block that is used inside poly-N (poly-2, poly-3, and so on) modules. 43 | The Convolution layer is shared between all Inception blocks inside 44 | a poly-N module. BatchNorm layers are not shared between Inception blocks 45 | and therefore the number of BatchNorm layers is equal to the number of 46 | Inception blocks inside a poly-N module. 47 | """ 48 | 49 | def __init__(self, in_planes, out_planes, kernel_size, num_blocks, 50 | stride=1, padding=0): 51 | super(PolyConv2d, self).__init__() 52 | self.conv = nn.Conv2d(in_planes, out_planes, kernel_size=kernel_size, 53 | stride=stride, padding=padding, bias=False) 54 | self.bn_blocks = nn.ModuleList([ 55 | nn.BatchNorm2d(out_planes) for _ in range(num_blocks) 56 | ]) 57 | self.relu = nn.ReLU() 58 | 59 | def forward(self, x, block_index): 60 | x = self.conv(x) 61 | bn = self.bn_blocks[block_index] 62 | x = bn(x) 63 | x = self.relu(x) 64 | return x 65 | 66 | 67 | class Stem(nn.Module): 68 | 69 | def __init__(self): 70 | super(Stem, self).__init__() 71 | self.conv1 = nn.Sequential( 72 | BasicConv2d(3, 32, kernel_size=3, stride=2), 73 | BasicConv2d(32, 32, kernel_size=3), 74 | BasicConv2d(32, 64, kernel_size=3, padding=1), 75 | ) 76 | self.conv1_pool_branch = nn.MaxPool2d(3, stride=2) 77 | self.conv1_branch = BasicConv2d(64, 96, kernel_size=3, stride=2) 78 | self.conv2_short = nn.Sequential( 79 | BasicConv2d(160, 64, kernel_size=1), 80 | BasicConv2d(64, 96, kernel_size=3), 81 | ) 82 | self.conv2_long = nn.Sequential( 83 | BasicConv2d(160, 64, kernel_size=1), 84 | BasicConv2d(64, 64, kernel_size=(7, 1), padding=(3, 0)), 85 | BasicConv2d(64, 64, kernel_size=(1, 7), padding=(0, 3)), 86 | BasicConv2d(64, 96, kernel_size=3), 87 | ) 88 | self.conv2_pool_branch = nn.MaxPool2d(3, stride=2) 89 | self.conv2_branch = BasicConv2d(192, 192, kernel_size=3, stride=2) 90 | 91 | def forward(self, x): 92 | x = self.conv1(x) 93 | 94 | x0 = self.conv1_pool_branch(x) 95 | x1 = self.conv1_branch(x) 96 | x = torch.cat((x0, x1), 1) 97 | 98 | x0 = self.conv2_short(x) 99 | x1 = self.conv2_long(x) 100 | x = torch.cat((x0, x1), 1) 101 | 102 | x0 = self.conv2_pool_branch(x) 103 | x1 = self.conv2_branch(x) 104 | out = torch.cat((x0, x1), 1) 105 | return out 106 | 107 | 108 | class BlockA(nn.Module): 109 | """Inception-ResNet-A block.""" 110 | 111 | def __init__(self): 112 | super(BlockA, self).__init__() 113 | self.path0 = nn.Sequential( 114 | BasicConv2d(384, 32, kernel_size=1), 115 | BasicConv2d(32, 48, kernel_size=3, padding=1), 116 | BasicConv2d(48, 64, kernel_size=3, padding=1), 117 | ) 118 | self.path1 = nn.Sequential( 119 | BasicConv2d(384, 32, kernel_size=1), 120 | BasicConv2d(32, 32, kernel_size=3, padding=1), 121 | ) 122 | self.path2 = BasicConv2d(384, 32, kernel_size=1) 123 | self.conv2d = BasicConv2d(128, 384, kernel_size=1, output_relu=False) 124 | 125 | def forward(self, x): 126 | x0 = self.path0(x) 127 | x1 = self.path1(x) 128 | x2 = self.path2(x) 129 | out = torch.cat((x0, x1, x2), 1) 130 | out = self.conv2d(out) 131 | return out 132 | 133 | 134 | class BlockB(nn.Module): 135 | """Inception-ResNet-B block.""" 136 | 137 | def __init__(self): 138 | super(BlockB, self).__init__() 139 | self.path0 = nn.Sequential( 140 | BasicConv2d(1152, 128, kernel_size=1), 141 | BasicConv2d(128, 160, kernel_size=(1, 7), padding=(0, 3)), 142 | BasicConv2d(160, 192, kernel_size=(7, 1), padding=(3, 0)), 143 | ) 144 | self.path1 = BasicConv2d(1152, 192, kernel_size=1) 145 | self.conv2d = BasicConv2d(384, 1152, kernel_size=1, output_relu=False) 146 | 147 | def forward(self, x): 148 | x0 = self.path0(x) 149 | x1 = self.path1(x) 150 | out = torch.cat((x0, x1), 1) 151 | out = self.conv2d(out) 152 | return out 153 | 154 | 155 | class BlockC(nn.Module): 156 | """Inception-ResNet-C block.""" 157 | 158 | def __init__(self): 159 | super(BlockC, self).__init__() 160 | self.path0 = nn.Sequential( 161 | BasicConv2d(2048, 192, kernel_size=1), 162 | BasicConv2d(192, 224, kernel_size=(1, 3), padding=(0, 1)), 163 | BasicConv2d(224, 256, kernel_size=(3, 1), padding=(1, 0)), 164 | ) 165 | self.path1 = BasicConv2d(2048, 192, kernel_size=1) 166 | self.conv2d = BasicConv2d(448, 2048, kernel_size=1, output_relu=False) 167 | 168 | def forward(self, x): 169 | x0 = self.path0(x) 170 | x1 = self.path1(x) 171 | out = torch.cat((x0, x1), 1) 172 | out = self.conv2d(out) 173 | return out 174 | 175 | 176 | class ReductionA(nn.Module): 177 | """A dimensionality reduction block that is placed after stage-a 178 | Inception-ResNet blocks. 179 | """ 180 | 181 | def __init__(self): 182 | super(ReductionA, self).__init__() 183 | self.path0 = nn.Sequential( 184 | BasicConv2d(384, 256, kernel_size=1), 185 | BasicConv2d(256, 256, kernel_size=3, padding=1), 186 | BasicConv2d(256, 384, kernel_size=3, stride=2), 187 | ) 188 | self.path1 = BasicConv2d(384, 384, kernel_size=3, stride=2) 189 | self.path2 = nn.MaxPool2d(3, stride=2) 190 | 191 | def forward(self, x): 192 | x0 = self.path0(x) 193 | x1 = self.path1(x) 194 | x2 = self.path2(x) 195 | out = torch.cat((x0, x1, x2), 1) 196 | return out 197 | 198 | 199 | class ReductionB(nn.Module): 200 | """A dimensionality reduction block that is placed after stage-b 201 | Inception-ResNet blocks. 202 | """ 203 | def __init__(self): 204 | super(ReductionB, self).__init__() 205 | self.path0 = nn.Sequential( 206 | BasicConv2d(1152, 256, kernel_size=1), 207 | BasicConv2d(256, 256, kernel_size=3, padding=1), 208 | BasicConv2d(256, 256, kernel_size=3, stride=2), 209 | ) 210 | self.path1 = nn.Sequential( 211 | BasicConv2d(1152, 256, kernel_size=1), 212 | BasicConv2d(256, 256, kernel_size=3, stride=2), 213 | ) 214 | self.path2 = nn.Sequential( 215 | BasicConv2d(1152, 256, kernel_size=1), 216 | BasicConv2d(256, 384, kernel_size=3, stride=2), 217 | ) 218 | self.path3 = nn.MaxPool2d(3, stride=2) 219 | 220 | def forward(self, x): 221 | x0 = self.path0(x) 222 | x1 = self.path1(x) 223 | x2 = self.path2(x) 224 | x3 = self.path3(x) 225 | out = torch.cat((x0, x1, x2, x3), 1) 226 | return out 227 | 228 | 229 | class InceptionResNetBPoly(nn.Module): 230 | """Base class for constructing poly-N Inception-ResNet-B modules. 231 | When `num_blocks` is equal to 1, a module will have only a first-order path 232 | and will be equal to a standard Inception-ResNet-B block. 233 | When `num_blocks` is equal to 2, a module will have first-order and 234 | second-order paths and will be called Inception-ResNet-B poly-2 module. 235 | Increasing value of the `num_blocks` parameter will produce a higher order 236 | Inception-ResNet-B poly-N modules. 237 | """ 238 | 239 | def __init__(self, scale, num_blocks): 240 | super(InceptionResNetBPoly, self).__init__() 241 | assert num_blocks >= 1, 'num_blocks should be greater or equal to 1' 242 | self.scale = scale 243 | self.num_blocks = num_blocks 244 | self.path0_1x1 = PolyConv2d(1152, 128, kernel_size=1, 245 | num_blocks=self.num_blocks) 246 | self.path0_1x7 = PolyConv2d(128, 160, kernel_size=(1, 7), 247 | num_blocks=self.num_blocks, padding=(0, 3)) 248 | self.path0_7x1 = PolyConv2d(160, 192, kernel_size=(7, 1), 249 | num_blocks=self.num_blocks, padding=(3, 0)) 250 | self.path1 = PolyConv2d(1152, 192, kernel_size=1, 251 | num_blocks=self.num_blocks) 252 | # conv2d blocks are not shared between Inception-ResNet-B blocks 253 | self.conv2d_blocks = nn.ModuleList([ 254 | BasicConv2d(384, 1152, kernel_size=1, output_relu=False) 255 | for _ in range(self.num_blocks) 256 | ]) 257 | self.relu = nn.ReLU() 258 | 259 | def forward_block(self, x, block_index): 260 | x0 = self.path0_1x1(x, block_index) 261 | x0 = self.path0_1x7(x0, block_index) 262 | x0 = self.path0_7x1(x0, block_index) 263 | x1 = self.path1(x, block_index) 264 | out = torch.cat((x0, x1), 1) 265 | conv2d_block = self.conv2d_blocks[block_index] 266 | out = conv2d_block(out) 267 | return out 268 | 269 | def forward(self, x): 270 | out = x 271 | for block_index in range(self.num_blocks): 272 | x = self.forward_block(x, block_index) 273 | out = out + x * self.scale 274 | x = self.relu(x) 275 | out = self.relu(out) 276 | return out 277 | 278 | 279 | class InceptionResNetCPoly(nn.Module): 280 | """Base class for constructing poly-N Inception-ResNet-C modules. 281 | When `num_blocks` is equal to 1, a module will have only a first-order path 282 | and will be equal to a standard Inception-ResNet-C block. 283 | When `num_blocks` is equal to 2, a module will have first-order and 284 | second-order paths and will be called Inception-ResNet-C poly-2 module. 285 | Increasing value of the `num_blocks` parameter will produce a higher order 286 | Inception-ResNet-C poly-N modules. 287 | """ 288 | 289 | def __init__(self, scale, num_blocks): 290 | super(InceptionResNetCPoly, self).__init__() 291 | assert num_blocks >= 1, 'num_blocks should be greater or equal to 1' 292 | self.scale = scale 293 | self.num_blocks = num_blocks 294 | self.path0_1x1 = PolyConv2d(2048, 192, kernel_size=1, 295 | num_blocks=self.num_blocks) 296 | self.path0_1x3 = PolyConv2d(192, 224, kernel_size=(1, 3), 297 | num_blocks=self.num_blocks, padding=(0, 1)) 298 | self.path0_3x1 = PolyConv2d(224, 256, kernel_size=(3, 1), 299 | num_blocks=self.num_blocks, padding=(1, 0)) 300 | self.path1 = PolyConv2d(2048, 192, kernel_size=1, 301 | num_blocks=self.num_blocks) 302 | # conv2d blocks are not shared between Inception-ResNet-C blocks 303 | self.conv2d_blocks = nn.ModuleList([ 304 | BasicConv2d(448, 2048, kernel_size=1, output_relu=False) 305 | for _ in range(self.num_blocks) 306 | ]) 307 | self.relu = nn.ReLU() 308 | 309 | def forward_block(self, x, block_index): 310 | x0 = self.path0_1x1(x, block_index) 311 | x0 = self.path0_1x3(x0, block_index) 312 | x0 = self.path0_3x1(x0, block_index) 313 | x1 = self.path1(x, block_index) 314 | out = torch.cat((x0, x1), 1) 315 | conv2d_block = self.conv2d_blocks[block_index] 316 | out = conv2d_block(out) 317 | return out 318 | 319 | def forward(self, x): 320 | out = x 321 | for block_index in range(self.num_blocks): 322 | x = self.forward_block(x, block_index) 323 | out = out + x * self.scale 324 | x = self.relu(x) 325 | out = self.relu(out) 326 | return out 327 | 328 | 329 | class MultiWay(nn.Module): 330 | """Base class for constructing N-way modules (2-way, 3-way, and so on).""" 331 | 332 | def __init__(self, scale, block_cls, num_blocks): 333 | super(MultiWay, self).__init__() 334 | assert num_blocks >= 1, 'num_blocks should be greater or equal to 1' 335 | self.scale = scale 336 | self.blocks = nn.ModuleList([block_cls() for _ in range(num_blocks)]) 337 | self.relu = nn.ReLU() 338 | 339 | def forward(self, x): 340 | out = x 341 | for block in self.blocks: 342 | out = out + block(x) * self.scale 343 | out = self.relu(out) 344 | return out 345 | 346 | 347 | # Some helper classes to simplify the construction of PolyNet 348 | 349 | class InceptionResNetA2Way(MultiWay): 350 | 351 | def __init__(self, scale): 352 | super(InceptionResNetA2Way, self).__init__(scale, block_cls=BlockA, 353 | num_blocks=2) 354 | 355 | 356 | class InceptionResNetB2Way(MultiWay): 357 | 358 | def __init__(self, scale): 359 | super(InceptionResNetB2Way, self).__init__(scale, block_cls=BlockB, 360 | num_blocks=2) 361 | 362 | 363 | class InceptionResNetC2Way(MultiWay): 364 | 365 | def __init__(self, scale): 366 | super(InceptionResNetC2Way, self).__init__(scale, block_cls=BlockC, 367 | num_blocks=2) 368 | 369 | 370 | class InceptionResNetBPoly3(InceptionResNetBPoly): 371 | 372 | def __init__(self, scale): 373 | super(InceptionResNetBPoly3, self).__init__(scale, num_blocks=3) 374 | 375 | 376 | class InceptionResNetCPoly3(InceptionResNetCPoly): 377 | 378 | def __init__(self, scale): 379 | super(InceptionResNetCPoly3, self).__init__(scale, num_blocks=3) 380 | 381 | 382 | class PolyNet(nn.Module): 383 | 384 | def __init__(self, num_classes=1000): 385 | super(PolyNet, self).__init__() 386 | self.stem = Stem() 387 | self.stage_a = nn.Sequential( 388 | InceptionResNetA2Way(scale=1), 389 | InceptionResNetA2Way(scale=0.992308), 390 | InceptionResNetA2Way(scale=0.984615), 391 | InceptionResNetA2Way(scale=0.976923), 392 | InceptionResNetA2Way(scale=0.969231), 393 | InceptionResNetA2Way(scale=0.961538), 394 | InceptionResNetA2Way(scale=0.953846), 395 | InceptionResNetA2Way(scale=0.946154), 396 | InceptionResNetA2Way(scale=0.938462), 397 | InceptionResNetA2Way(scale=0.930769), 398 | ) 399 | self.reduction_a = ReductionA() 400 | self.stage_b = nn.Sequential( 401 | InceptionResNetBPoly3(scale=0.923077), 402 | InceptionResNetB2Way(scale=0.915385), 403 | InceptionResNetBPoly3(scale=0.907692), 404 | InceptionResNetB2Way(scale=0.9), 405 | InceptionResNetBPoly3(scale=0.892308), 406 | InceptionResNetB2Way(scale=0.884615), 407 | InceptionResNetBPoly3(scale=0.876923), 408 | InceptionResNetB2Way(scale=0.869231), 409 | InceptionResNetBPoly3(scale=0.861538), 410 | InceptionResNetB2Way(scale=0.853846), 411 | InceptionResNetBPoly3(scale=0.846154), 412 | InceptionResNetB2Way(scale=0.838462), 413 | InceptionResNetBPoly3(scale=0.830769), 414 | InceptionResNetB2Way(scale=0.823077), 415 | InceptionResNetBPoly3(scale=0.815385), 416 | InceptionResNetB2Way(scale=0.807692), 417 | InceptionResNetBPoly3(scale=0.8), 418 | InceptionResNetB2Way(scale=0.792308), 419 | InceptionResNetBPoly3(scale=0.784615), 420 | InceptionResNetB2Way(scale=0.776923), 421 | ) 422 | self.reduction_b = ReductionB() 423 | self.stage_c = nn.Sequential( 424 | InceptionResNetCPoly3(scale=0.769231), 425 | InceptionResNetC2Way(scale=0.761538), 426 | InceptionResNetCPoly3(scale=0.753846), 427 | InceptionResNetC2Way(scale=0.746154), 428 | InceptionResNetCPoly3(scale=0.738462), 429 | InceptionResNetC2Way(scale=0.730769), 430 | InceptionResNetCPoly3(scale=0.723077), 431 | InceptionResNetC2Way(scale=0.715385), 432 | InceptionResNetCPoly3(scale=0.707692), 433 | InceptionResNetC2Way(scale=0.7), 434 | ) 435 | self.avg_pool = nn.AvgPool2d(9, stride=1) 436 | self.dropout = nn.Dropout(0.2) 437 | self.last_linear = nn.Linear(2048, num_classes) 438 | 439 | def features(self, x): 440 | x = self.stem(x) 441 | x = self.stage_a(x) 442 | x = self.reduction_a(x) 443 | x = self.stage_b(x) 444 | x = self.reduction_b(x) 445 | x = self.stage_c(x) 446 | return x 447 | 448 | def logits(self, x): 449 | x = self.avg_pool(x) 450 | x = self.dropout(x) 451 | x = x.view(x.size(0), -1) 452 | x = self.last_linear(x) 453 | return x 454 | 455 | def forward(self, x): 456 | x = self.features(x) 457 | x = self.logits(x) 458 | return x 459 | 460 | 461 | def polynet(num_classes=1000, pretrained='imagenet'): 462 | """PolyNet architecture from the paper 463 | 'PolyNet: A Pursuit of Structural Diversity in Very Deep Networks' 464 | https://arxiv.org/abs/1611.05725 465 | """ 466 | if pretrained: 467 | settings = pretrained_settings['polynet'][pretrained] 468 | assert num_classes == settings['num_classes'], \ 469 | 'num_classes should be {}, but is {}'.format( 470 | settings['num_classes'], num_classes) 471 | model = PolyNet(num_classes=num_classes) 472 | model.load_state_dict(model_zoo.load_url(settings['url'])) 473 | model.input_space = settings['input_space'] 474 | model.input_size = settings['input_size'] 475 | model.input_range = settings['input_range'] 476 | model.mean = settings['mean'] 477 | model.std = settings['std'] 478 | else: 479 | model = PolyNet(num_classes=num_classes) 480 | return model 481 | -------------------------------------------------------------------------------- /pretrainedmodels/models/resnext.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function, division, absolute_import 2 | import os 3 | import torch 4 | import torch.nn as nn 5 | import torch.utils.model_zoo as model_zoo 6 | from .resnext_features import resnext101_32x4d_features 7 | from .resnext_features import resnext101_64x4d_features 8 | 9 | __all__ = ['ResNeXt101_32x4d', 'resnext101_32x4d', 10 | 'ResNeXt101_64x4d', 'resnext101_64x4d'] 11 | 12 | pretrained_settings = { 13 | 'resnext101_32x4d': { 14 | 'imagenet': { 15 | 'url': 'http://data.lip6.fr/cadene/pretrainedmodels/resnext101_32x4d-29e315fa.pth', 16 | 'input_space': 'RGB', 17 | 'input_size': [3, 224, 224], 18 | 'input_range': [0, 1], 19 | 'mean': [0.485, 0.456, 0.406], 20 | 'std': [0.229, 0.224, 0.225], 21 | 'num_classes': 1000 22 | } 23 | }, 24 | 'resnext101_64x4d': { 25 | 'imagenet': { 26 | 'url': 'http://data.lip6.fr/cadene/pretrainedmodels/resnext101_64x4d-e77a0586.pth', 27 | 'input_space': 'RGB', 28 | 'input_size': [3, 224, 224], 29 | 'input_range': [0, 1], 30 | 'mean': [0.485, 0.456, 0.406], 31 | 'std': [0.229, 0.224, 0.225], 32 | 'num_classes': 1000 33 | } 34 | } 35 | } 36 | 37 | class ResNeXt101_32x4d(nn.Module): 38 | 39 | def __init__(self, num_classes=1000): 40 | super(ResNeXt101_32x4d, self).__init__() 41 | self.num_classes = num_classes 42 | self.features = resnext101_32x4d_features 43 | self.avg_pool = nn.AvgPool2d((7, 7), (1, 1)) 44 | self.last_linear = nn.Linear(2048, num_classes) 45 | 46 | def logits(self, input): 47 | x = self.avg_pool(input) 48 | x = x.view(x.size(0), -1) 49 | x = self.last_linear(x) 50 | return x 51 | 52 | def forward(self, input): 53 | x = self.features(input) 54 | x = self.logits(x) 55 | return x 56 | 57 | 58 | class ResNeXt101_64x4d(nn.Module): 59 | 60 | def __init__(self, num_classes=1000): 61 | super(ResNeXt101_64x4d, self).__init__() 62 | self.num_classes = num_classes 63 | self.features = resnext101_64x4d_features 64 | self.avg_pool = nn.AvgPool2d((7, 7), (1, 1)) 65 | self.last_linear = nn.Linear(2048, num_classes) 66 | 67 | def logits(self, input): 68 | x = self.avg_pool(input) 69 | x = x.view(x.size(0), -1) 70 | x = self.last_linear(x) 71 | return x 72 | 73 | def forward(self, input): 74 | x = self.features(input) 75 | x = self.logits(x) 76 | return x 77 | 78 | 79 | def resnext101_32x4d(num_classes=1000, pretrained='imagenet'): 80 | model = ResNeXt101_32x4d(num_classes=num_classes) 81 | if pretrained is not None: 82 | settings = pretrained_settings['resnext101_32x4d'][pretrained] 83 | assert num_classes == settings['num_classes'], \ 84 | "num_classes should be {}, but is {}".format(settings['num_classes'], num_classes) 85 | model.load_state_dict(model_zoo.load_url(settings['url'])) 86 | model.input_space = settings['input_space'] 87 | model.input_size = settings['input_size'] 88 | model.input_range = settings['input_range'] 89 | model.mean = settings['mean'] 90 | model.std = settings['std'] 91 | return model 92 | 93 | def resnext101_64x4d(num_classes=1000, pretrained='imagenet'): 94 | model = ResNeXt101_64x4d(num_classes=num_classes) 95 | if pretrained is not None: 96 | settings = pretrained_settings['resnext101_64x4d'][pretrained] 97 | assert num_classes == settings['num_classes'], \ 98 | "num_classes should be {}, but is {}".format(settings['num_classes'], num_classes) 99 | model.load_state_dict(model_zoo.load_url(settings['url'])) 100 | model.input_space = settings['input_space'] 101 | model.input_size = settings['input_size'] 102 | model.input_range = settings['input_range'] 103 | model.mean = settings['mean'] 104 | model.std = settings['std'] 105 | return model 106 | -------------------------------------------------------------------------------- /pretrainedmodels/models/resnext_features/__init__.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function, division, absolute_import 2 | from .resnext101_32x4d_features import resnext101_32x4d_features 3 | from .resnext101_64x4d_features import resnext101_64x4d_features -------------------------------------------------------------------------------- /pretrainedmodels/models/senet.py: -------------------------------------------------------------------------------- 1 | """ 2 | ResNet code gently borrowed from 3 | https://github.com/pytorch/vision/blob/master/torchvision/models/resnet.py 4 | """ 5 | from __future__ import print_function, division, absolute_import 6 | from collections import OrderedDict 7 | import math 8 | 9 | import torch.nn as nn 10 | from torch.utils import model_zoo 11 | 12 | __all__ = ['SENet', 'senet154', 'se_resnet50', 'se_resnet101', 'se_resnet152', 13 | 'se_resnext50_32x4d', 'se_resnext101_32x4d'] 14 | 15 | pretrained_settings = { 16 | 'senet154': { 17 | 'imagenet': { 18 | 'url': 'http://data.lip6.fr/cadene/pretrainedmodels/senet154-c7b49a05.pth', 19 | 'input_space': 'RGB', 20 | 'input_size': [3, 224, 224], 21 | 'input_range': [0, 1], 22 | 'mean': [0.485, 0.456, 0.406], 23 | 'std': [0.229, 0.224, 0.225], 24 | 'num_classes': 1000 25 | } 26 | }, 27 | 'se_resnet50': { 28 | 'imagenet': { 29 | 'url': 'http://data.lip6.fr/cadene/pretrainedmodels/se_resnet50-ce0d4300.pth', 30 | 'input_space': 'RGB', 31 | 'input_size': [3, 224, 224], 32 | 'input_range': [0, 1], 33 | 'mean': [0.485, 0.456, 0.406], 34 | 'std': [0.229, 0.224, 0.225], 35 | 'num_classes': 1000 36 | } 37 | }, 38 | 'se_resnet101': { 39 | 'imagenet': { 40 | 'url': 'http://data.lip6.fr/cadene/pretrainedmodels/se_resnet101-7e38fcc6.pth', 41 | 'input_space': 'RGB', 42 | 'input_size': [3, 224, 224], 43 | 'input_range': [0, 1], 44 | 'mean': [0.485, 0.456, 0.406], 45 | 'std': [0.229, 0.224, 0.225], 46 | 'num_classes': 1000 47 | } 48 | }, 49 | 'se_resnet152': { 50 | 'imagenet': { 51 | 'url': 'http://data.lip6.fr/cadene/pretrainedmodels/se_resnet152-d17c99b7.pth', 52 | 'input_space': 'RGB', 53 | 'input_size': [3, 224, 224], 54 | 'input_range': [0, 1], 55 | 'mean': [0.485, 0.456, 0.406], 56 | 'std': [0.229, 0.224, 0.225], 57 | 'num_classes': 1000 58 | } 59 | }, 60 | 'se_resnext50_32x4d': { 61 | 'imagenet': { 62 | 'url': 'http://data.lip6.fr/cadene/pretrainedmodels/se_resnext50_32x4d-a260b3a4.pth', 63 | 'input_space': 'RGB', 64 | 'input_size': [3, 224, 224], 65 | 'input_range': [0, 1], 66 | 'mean': [0.485, 0.456, 0.406], 67 | 'std': [0.229, 0.224, 0.225], 68 | 'num_classes': 1000 69 | } 70 | }, 71 | 'se_resnext101_32x4d': { 72 | 'imagenet': { 73 | 'url': 'http://data.lip6.fr/cadene/pretrainedmodels/se_resnext101_32x4d-3b2fe3d8.pth', 74 | 'input_space': 'RGB', 75 | 'input_size': [3, 224, 224], 76 | 'input_range': [0, 1], 77 | 'mean': [0.485, 0.456, 0.406], 78 | 'std': [0.229, 0.224, 0.225], 79 | 'num_classes': 1000 80 | } 81 | }, 82 | } 83 | 84 | 85 | class SEModule(nn.Module): 86 | 87 | def __init__(self, channels, reduction): 88 | super(SEModule, self).__init__() 89 | self.avg_pool = nn.AdaptiveAvgPool2d(1) 90 | self.fc1 = nn.Conv2d(channels, channels // reduction, kernel_size=1, 91 | padding=0) 92 | self.relu = nn.ReLU(inplace=True) 93 | self.fc2 = nn.Conv2d(channels // reduction, channels, kernel_size=1, 94 | padding=0) 95 | self.sigmoid = nn.Sigmoid() 96 | 97 | def forward(self, x): 98 | module_input = x 99 | x = self.avg_pool(x) 100 | x = self.fc1(x) 101 | x = self.relu(x) 102 | x = self.fc2(x) 103 | x = self.sigmoid(x) 104 | return module_input * x 105 | 106 | 107 | class Bottleneck(nn.Module): 108 | """ 109 | Base class for bottlenecks that implements `forward()` method. 110 | """ 111 | def forward(self, x): 112 | residual = x 113 | 114 | out = self.conv1(x) 115 | out = self.bn1(out) 116 | out = self.relu(out) 117 | 118 | out = self.conv2(out) 119 | out = self.bn2(out) 120 | out = self.relu(out) 121 | 122 | out = self.conv3(out) 123 | out = self.bn3(out) 124 | 125 | if self.downsample is not None: 126 | residual = self.downsample(x) 127 | 128 | out = self.se_module(out) + residual 129 | out = self.relu(out) 130 | 131 | return out 132 | 133 | 134 | class SEBottleneck(Bottleneck): 135 | """ 136 | Bottleneck for SENet154. 137 | """ 138 | expansion = 4 139 | 140 | def __init__(self, inplanes, planes, groups, reduction, stride=1, 141 | downsample=None): 142 | super(SEBottleneck, self).__init__() 143 | self.conv1 = nn.Conv2d(inplanes, planes * 2, kernel_size=1, bias=False) 144 | self.bn1 = nn.BatchNorm2d(planes * 2) 145 | self.conv2 = nn.Conv2d(planes * 2, planes * 4, kernel_size=3, 146 | stride=stride, padding=1, groups=groups, 147 | bias=False) 148 | self.bn2 = nn.BatchNorm2d(planes * 4) 149 | self.conv3 = nn.Conv2d(planes * 4, planes * 4, kernel_size=1, 150 | bias=False) 151 | self.bn3 = nn.BatchNorm2d(planes * 4) 152 | self.relu = nn.ReLU(inplace=True) 153 | self.se_module = SEModule(planes * 4, reduction=reduction) 154 | self.downsample = downsample 155 | self.stride = stride 156 | 157 | 158 | class SEResNetBottleneck(Bottleneck): 159 | """ 160 | ResNet bottleneck with a Squeeze-and-Excitation module. It follows Caffe 161 | implementation and uses `stride=stride` in `conv1` and not in `conv2` 162 | (the latter is used in the torchvision implementation of ResNet). 163 | """ 164 | expansion = 4 165 | 166 | def __init__(self, inplanes, planes, groups, reduction, stride=1, 167 | downsample=None): 168 | super(SEResNetBottleneck, self).__init__() 169 | self.conv1 = nn.Conv2d(inplanes, planes, kernel_size=1, bias=False, 170 | stride=stride) 171 | self.bn1 = nn.BatchNorm2d(planes) 172 | self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, padding=1, 173 | groups=groups, bias=False) 174 | self.bn2 = nn.BatchNorm2d(planes) 175 | self.conv3 = nn.Conv2d(planes, planes * 4, kernel_size=1, bias=False) 176 | self.bn3 = nn.BatchNorm2d(planes * 4) 177 | self.relu = nn.ReLU(inplace=True) 178 | self.se_module = SEModule(planes * 4, reduction=reduction) 179 | self.downsample = downsample 180 | self.stride = stride 181 | 182 | 183 | class SEResNeXtBottleneck(Bottleneck): 184 | """ 185 | ResNeXt bottleneck type C with a Squeeze-and-Excitation module. 186 | """ 187 | expansion = 4 188 | 189 | def __init__(self, inplanes, planes, groups, reduction, stride=1, 190 | downsample=None, base_width=4): 191 | super(SEResNeXtBottleneck, self).__init__() 192 | width = math.floor(planes * (base_width / 64)) * groups 193 | self.conv1 = nn.Conv2d(inplanes, width, kernel_size=1, bias=False, 194 | stride=1) 195 | self.bn1 = nn.BatchNorm2d(width) 196 | self.conv2 = nn.Conv2d(width, width, kernel_size=3, stride=stride, 197 | padding=1, groups=groups, bias=False) 198 | self.bn2 = nn.BatchNorm2d(width) 199 | self.conv3 = nn.Conv2d(width, planes * 4, kernel_size=1, bias=False) 200 | self.bn3 = nn.BatchNorm2d(planes * 4) 201 | self.relu = nn.ReLU(inplace=True) 202 | self.se_module = SEModule(planes * 4, reduction=reduction) 203 | self.downsample = downsample 204 | self.stride = stride 205 | 206 | 207 | class SENet(nn.Module): 208 | 209 | def __init__(self, block, layers, groups, reduction, dropout_p=0.2, 210 | inplanes=128, input_3x3=True, downsample_kernel_size=3, 211 | downsample_padding=1, num_classes=1000): 212 | """ 213 | Parameters 214 | ---------- 215 | block (nn.Module): Bottleneck class. 216 | - For SENet154: SEBottleneck 217 | - For SE-ResNet models: SEResNetBottleneck 218 | - For SE-ResNeXt models: SEResNeXtBottleneck 219 | layers (list of ints): Number of residual blocks for 4 layers of the 220 | network (layer1...layer4). 221 | groups (int): Number of groups for the 3x3 convolution in each 222 | bottleneck block. 223 | - For SENet154: 64 224 | - For SE-ResNet models: 1 225 | - For SE-ResNeXt models: 32 226 | reduction (int): Reduction ratio for Squeeze-and-Excitation modules. 227 | - For all models: 16 228 | dropout_p (float or None): Drop probability for the Dropout layer. 229 | If `None` the Dropout layer is not used. 230 | - For SENet154: 0.2 231 | - For SE-ResNet models: None 232 | - For SE-ResNeXt models: None 233 | inplanes (int): Number of input channels for layer1. 234 | - For SENet154: 128 235 | - For SE-ResNet models: 64 236 | - For SE-ResNeXt models: 64 237 | input_3x3 (bool): If `True`, use three 3x3 convolutions instead of 238 | a single 7x7 convolution in layer0. 239 | - For SENet154: True 240 | - For SE-ResNet models: False 241 | - For SE-ResNeXt models: False 242 | downsample_kernel_size (int): Kernel size for downsampling convolutions 243 | in layer2, layer3 and layer4. 244 | - For SENet154: 3 245 | - For SE-ResNet models: 1 246 | - For SE-ResNeXt models: 1 247 | downsample_padding (int): Padding for downsampling convolutions in 248 | layer2, layer3 and layer4. 249 | - For SENet154: 1 250 | - For SE-ResNet models: 0 251 | - For SE-ResNeXt models: 0 252 | num_classes (int): Number of outputs in `last_linear` layer. 253 | - For all models: 1000 254 | """ 255 | super(SENet, self).__init__() 256 | self.inplanes = inplanes 257 | if input_3x3: 258 | layer0_modules = [ 259 | ('conv1', nn.Conv2d(3, 64, 3, stride=2, padding=1, 260 | bias=False)), 261 | ('bn1', nn.BatchNorm2d(64)), 262 | ('relu1', nn.ReLU(inplace=True)), 263 | ('conv2', nn.Conv2d(64, 64, 3, stride=1, padding=1, 264 | bias=False)), 265 | ('bn2', nn.BatchNorm2d(64)), 266 | ('relu2', nn.ReLU(inplace=True)), 267 | ('conv3', nn.Conv2d(64, inplanes, 3, stride=1, padding=1, 268 | bias=False)), 269 | ('bn3', nn.BatchNorm2d(inplanes)), 270 | ('relu3', nn.ReLU(inplace=True)), 271 | ] 272 | else: 273 | layer0_modules = [ 274 | ('conv1', nn.Conv2d(3, inplanes, kernel_size=7, stride=2, 275 | padding=3, bias=False)), 276 | ('bn1', nn.BatchNorm2d(inplanes)), 277 | ('relu1', nn.ReLU(inplace=True)), 278 | ] 279 | # To preserve compatibility with Caffe weights `ceil_mode=True` 280 | # is used instead of `padding=1`. 281 | layer0_modules.append(('pool', nn.MaxPool2d(3, stride=2, 282 | ceil_mode=True))) 283 | self.layer0 = nn.Sequential(OrderedDict(layer0_modules)) 284 | self.layer1 = self._make_layer( 285 | block, 286 | planes=64, 287 | blocks=layers[0], 288 | groups=groups, 289 | reduction=reduction, 290 | downsample_kernel_size=1, 291 | downsample_padding=0 292 | ) 293 | self.layer2 = self._make_layer( 294 | block, 295 | planes=128, 296 | blocks=layers[1], 297 | stride=2, 298 | groups=groups, 299 | reduction=reduction, 300 | downsample_kernel_size=downsample_kernel_size, 301 | downsample_padding=downsample_padding 302 | ) 303 | self.layer3 = self._make_layer( 304 | block, 305 | planes=256, 306 | blocks=layers[2], 307 | stride=2, 308 | groups=groups, 309 | reduction=reduction, 310 | downsample_kernel_size=downsample_kernel_size, 311 | downsample_padding=downsample_padding 312 | ) 313 | self.layer4 = self._make_layer( 314 | block, 315 | planes=512, 316 | blocks=layers[3], 317 | stride=2, 318 | groups=groups, 319 | reduction=reduction, 320 | downsample_kernel_size=downsample_kernel_size, 321 | downsample_padding=downsample_padding 322 | ) 323 | self.avg_pool = nn.AvgPool2d(7, stride=1) 324 | self.dropout = nn.Dropout(dropout_p) if dropout_p is not None else None 325 | self.last_linear = nn.Linear(512 * block.expansion, num_classes) 326 | 327 | def _make_layer(self, block, planes, blocks, groups, reduction, stride=1, 328 | downsample_kernel_size=1, downsample_padding=0): 329 | downsample = None 330 | if stride != 1 or self.inplanes != planes * block.expansion: 331 | downsample = nn.Sequential( 332 | nn.Conv2d(self.inplanes, planes * block.expansion, 333 | kernel_size=downsample_kernel_size, stride=stride, 334 | padding=downsample_padding, bias=False), 335 | nn.BatchNorm2d(planes * block.expansion), 336 | ) 337 | 338 | layers = [] 339 | layers.append(block(self.inplanes, planes, groups, reduction, stride, 340 | downsample)) 341 | self.inplanes = planes * block.expansion 342 | for i in range(1, blocks): 343 | layers.append(block(self.inplanes, planes, groups, reduction)) 344 | 345 | return nn.Sequential(*layers) 346 | 347 | def features(self, x): 348 | x = self.layer0(x) 349 | x = self.layer1(x) 350 | x = self.layer2(x) 351 | x = self.layer3(x) 352 | x = self.layer4(x) 353 | return x 354 | 355 | def logits(self, x): 356 | x = self.avg_pool(x) 357 | if self.dropout is not None: 358 | x = self.dropout(x) 359 | x = x.view(x.size(0), -1) 360 | x = self.last_linear(x) 361 | return x 362 | 363 | def forward(self, x): 364 | x = self.features(x) 365 | x = self.logits(x) 366 | return x 367 | 368 | 369 | def initialize_pretrained_model(model, num_classes, settings): 370 | assert num_classes == settings['num_classes'], \ 371 | 'num_classes should be {}, but is {}'.format( 372 | settings['num_classes'], num_classes) 373 | model.load_state_dict(model_zoo.load_url(settings['url'])) 374 | model.input_space = settings['input_space'] 375 | model.input_size = settings['input_size'] 376 | model.input_range = settings['input_range'] 377 | model.mean = settings['mean'] 378 | model.std = settings['std'] 379 | 380 | 381 | def senet154(num_classes=1000, pretrained='imagenet'): 382 | model = SENet(SEBottleneck, [3, 8, 36, 3], groups=64, reduction=16, 383 | dropout_p=0.2, num_classes=num_classes) 384 | if pretrained is not None: 385 | settings = pretrained_settings['senet154'][pretrained] 386 | initialize_pretrained_model(model, num_classes, settings) 387 | return model 388 | 389 | 390 | def se_resnet50(num_classes=1000, pretrained='imagenet'): 391 | model = SENet(SEResNetBottleneck, [3, 4, 6, 3], groups=1, reduction=16, 392 | dropout_p=None, inplanes=64, input_3x3=False, 393 | downsample_kernel_size=1, downsample_padding=0, 394 | num_classes=num_classes) 395 | if pretrained is not None: 396 | settings = pretrained_settings['se_resnet50'][pretrained] 397 | initialize_pretrained_model(model, num_classes, settings) 398 | return model 399 | 400 | 401 | def se_resnet101(num_classes=1000, pretrained='imagenet'): 402 | model = SENet(SEResNetBottleneck, [3, 4, 23, 3], groups=1, reduction=16, 403 | dropout_p=None, inplanes=64, input_3x3=False, 404 | downsample_kernel_size=1, downsample_padding=0, 405 | num_classes=num_classes) 406 | if pretrained is not None: 407 | settings = pretrained_settings['se_resnet101'][pretrained] 408 | initialize_pretrained_model(model, num_classes, settings) 409 | return model 410 | 411 | 412 | def se_resnet152(num_classes=1000, pretrained='imagenet'): 413 | model = SENet(SEResNetBottleneck, [3, 8, 36, 3], groups=1, reduction=16, 414 | dropout_p=None, inplanes=64, input_3x3=False, 415 | downsample_kernel_size=1, downsample_padding=0, 416 | num_classes=num_classes) 417 | if pretrained is not None: 418 | settings = pretrained_settings['se_resnet152'][pretrained] 419 | initialize_pretrained_model(model, num_classes, settings) 420 | return model 421 | 422 | 423 | def se_resnext50_32x4d(num_classes=1000, pretrained='imagenet'): 424 | model = SENet(SEResNeXtBottleneck, [3, 4, 6, 3], groups=32, reduction=16, 425 | dropout_p=None, inplanes=64, input_3x3=False, 426 | downsample_kernel_size=1, downsample_padding=0, 427 | num_classes=num_classes) 428 | if pretrained is not None: 429 | settings = pretrained_settings['se_resnext50_32x4d'][pretrained] 430 | initialize_pretrained_model(model, num_classes, settings) 431 | return model 432 | 433 | 434 | def se_resnext101_32x4d(num_classes=1000, pretrained='imagenet'): 435 | model = SENet(SEResNeXtBottleneck, [3, 4, 23, 3], groups=32, reduction=16, 436 | dropout_p=None, inplanes=64, input_3x3=False, 437 | downsample_kernel_size=1, downsample_padding=0, 438 | num_classes=num_classes) 439 | if pretrained is not None: 440 | settings = pretrained_settings['se_resnext101_32x4d'][pretrained] 441 | initialize_pretrained_model(model, num_classes, settings) 442 | return model 443 | -------------------------------------------------------------------------------- /pretrainedmodels/models/utils.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function, division, absolute_import 2 | from .fbresnet import pretrained_settings as fbresnet_settings 3 | from .bninception import pretrained_settings as bninception_settings 4 | from .resnext import pretrained_settings as resnext_settings 5 | from .inceptionv4 import pretrained_settings as inceptionv4_settings 6 | from .inceptionresnetv2 import pretrained_settings as inceptionresnetv2_settings 7 | from .torchvision_models import pretrained_settings as torchvision_models_settings 8 | from .nasnet_mobile import pretrained_settings as nasnet_mobile_settings 9 | from .nasnet import pretrained_settings as nasnet_settings 10 | from .dpn import pretrained_settings as dpn_settings 11 | from .xception import pretrained_settings as xception_settings 12 | from .senet import pretrained_settings as senet_settings 13 | from .cafferesnet import pretrained_settings as cafferesnet_settings 14 | from .pnasnet import pretrained_settings as pnasnet_settings 15 | from .polynet import pretrained_settings as polynet_settings 16 | 17 | all_settings = [ 18 | fbresnet_settings, 19 | bninception_settings, 20 | resnext_settings, 21 | inceptionv4_settings, 22 | inceptionresnetv2_settings, 23 | torchvision_models_settings, 24 | nasnet_mobile_settings, 25 | nasnet_settings, 26 | dpn_settings, 27 | xception_settings, 28 | senet_settings, 29 | cafferesnet_settings, 30 | pnasnet_settings, 31 | polynet_settings 32 | ] 33 | 34 | model_names = [] 35 | pretrained_settings = {} 36 | for settings in all_settings: 37 | for model_name, model_settings in settings.items(): 38 | pretrained_settings[model_name] = model_settings 39 | model_names.append(model_name) 40 | -------------------------------------------------------------------------------- /pretrainedmodels/models/vggm.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function, division, absolute_import 2 | import torch 3 | import torch.nn as nn 4 | from torch.autograd import Variable 5 | #from torch.legacy import nn as nnl 6 | import torch.utils.model_zoo as model_zoo 7 | 8 | __all__ = ['vggm'] 9 | 10 | pretrained_settings = { 11 | 'vggm': { 12 | 'imagenet': { 13 | 'url': 'http://data.lip6.fr/cadene/pretrainedmodels/vggm-786f2434.pth', 14 | 'input_space': 'BGR', 15 | 'input_size': [3, 221, 221], 16 | 'input_range': [0, 255], 17 | 'mean': [123.68, 116.779, 103.939], 18 | 'std': [1, 1, 1], 19 | 'num_classes': 1000 20 | } 21 | } 22 | } 23 | 24 | class SpatialCrossMapLRN(nn.Module): 25 | def __init__(self, local_size=1, alpha=1.0, beta=0.75, k=1, ACROSS_CHANNELS=True): 26 | super(SpatialCrossMapLRN, self).__init__() 27 | self.ACROSS_CHANNELS = ACROSS_CHANNELS 28 | if ACROSS_CHANNELS: 29 | self.average=nn.AvgPool3d(kernel_size=(local_size, 1, 1), 30 | stride=1, 31 | padding=(int((local_size-1.0)/2), 0, 0)) 32 | else: 33 | self.average=nn.AvgPool2d(kernel_size=local_size, 34 | stride=1, 35 | padding=int((local_size-1.0)/2)) 36 | self.alpha = alpha 37 | self.beta = beta 38 | self.k = k 39 | 40 | def forward(self, x): 41 | if self.ACROSS_CHANNELS: 42 | div = x.pow(2).unsqueeze(1) 43 | div = self.average(div).squeeze(1) 44 | div = div.mul(self.alpha).add(self.k).pow(self.beta) 45 | else: 46 | div = x.pow(2) 47 | div = self.average(div) 48 | div = div.mul(self.alpha).add(self.k).pow(self.beta) 49 | x = x.div(div) 50 | return x 51 | 52 | class LambdaBase(nn.Sequential): 53 | def __init__(self, fn, *args): 54 | super(LambdaBase, self).__init__(*args) 55 | self.lambda_func = fn 56 | 57 | def forward_prepare(self, input): 58 | output = [] 59 | for module in self._modules.values(): 60 | output.append(module(input)) 61 | return output if output else input 62 | 63 | class Lambda(LambdaBase): 64 | def forward(self, input): 65 | return self.lambda_func(self.forward_prepare(input)) 66 | 67 | class VGGM(nn.Module): 68 | 69 | def __init__(self, num_classes=1000): 70 | super(VGGM, self).__init__() 71 | self.num_classes = num_classes 72 | self.features = nn.Sequential( 73 | nn.Conv2d(3,96,(7, 7),(2, 2)), 74 | nn.ReLU(), 75 | SpatialCrossMapLRN(5, 0.0005, 0.75, 2), 76 | nn.MaxPool2d((3, 3),(2, 2),(0, 0),ceil_mode=True), 77 | nn.Conv2d(96,256,(5, 5),(2, 2),(1, 1)), 78 | nn.ReLU(), 79 | SpatialCrossMapLRN(5, 0.0005, 0.75, 2), 80 | nn.MaxPool2d((3, 3),(2, 2),(0, 0),ceil_mode=True), 81 | nn.Conv2d(256,512,(3, 3),(1, 1),(1, 1)), 82 | nn.ReLU(), 83 | nn.Conv2d(512,512,(3, 3),(1, 1),(1, 1)), 84 | nn.ReLU(), 85 | nn.Conv2d(512,512,(3, 3),(1, 1),(1, 1)), 86 | nn.ReLU(), 87 | nn.MaxPool2d((3, 3),(2, 2),(0, 0),ceil_mode=True) 88 | ) 89 | self.classif = nn.Sequential( 90 | nn.Linear(18432,4096), 91 | nn.ReLU(), 92 | nn.Dropout(0.5), 93 | nn.Linear(4096,4096), 94 | nn.ReLU(), 95 | nn.Dropout(0.5), 96 | nn.Linear(4096,num_classes) 97 | ) 98 | 99 | def forward(self, x): 100 | x = self.features(x) 101 | x = x.view(x.size(0), -1) 102 | x = self.classif(x) 103 | return x 104 | 105 | def vggm(num_classes=1000, pretrained='imagenet'): 106 | if pretrained: 107 | settings = pretrained_settings['vggm'][pretrained] 108 | assert num_classes == settings['num_classes'], \ 109 | "num_classes should be {}, but is {}".format(settings['num_classes'], num_classes) 110 | 111 | model = VGGM(num_classes=1000) 112 | model.load_state_dict(model_zoo.load_url(settings['url'])) 113 | 114 | model.input_space = settings['input_space'] 115 | model.input_size = settings['input_size'] 116 | model.input_range = settings['input_range'] 117 | model.mean = settings['mean'] 118 | model.std = settings['std'] 119 | else: 120 | model = VGGM(num_classes=num_classes) 121 | return model -------------------------------------------------------------------------------- /pretrainedmodels/models/wideresnet.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function, division, absolute_import 2 | import os 3 | from os.path import expanduser 4 | import hickle as hkl 5 | import torch 6 | import torch.nn.functional as F 7 | from torch.autograd import Variable 8 | 9 | __all__ = ['wideresnet50'] 10 | 11 | model_urls = { 12 | 'wideresnet152': 'https://s3.amazonaws.com/pytorch/h5models/wide-resnet-50-2-export.hkl' 13 | } 14 | 15 | def define_model(params): 16 | def conv2d(input, params, base, stride=1, pad=0): 17 | return F.conv2d(input, params[base + '.weight'], 18 | params[base + '.bias'], stride, pad) 19 | 20 | def group(input, params, base, stride, n): 21 | o = input 22 | for i in range(0,n): 23 | b_base = ('%s.block%d.conv') % (base, i) 24 | x = o 25 | o = conv2d(x, params, b_base + '0') 26 | o = F.relu(o) 27 | o = conv2d(o, params, b_base + '1', stride=i==0 and stride or 1, pad=1) 28 | o = F.relu(o) 29 | o = conv2d(o, params, b_base + '2') 30 | if i == 0: 31 | o += conv2d(x, params, b_base + '_dim', stride=stride) 32 | else: 33 | o += x 34 | o = F.relu(o) 35 | return o 36 | 37 | # determine network size by parameters 38 | blocks = [sum([re.match('group%d.block\d+.conv0.weight'%j, k) is not None 39 | for k in params.keys()]) for j in range(4)] 40 | 41 | def f(input, params, pooling_classif=True): 42 | o = F.conv2d(input, params['conv0.weight'], params['conv0.bias'], 2, 3) 43 | o = F.relu(o) 44 | o = F.max_pool2d(o, 3, 2, 1) 45 | o_g0 = group(o, params, 'group0', 1, blocks[0]) 46 | o_g1 = group(o_g0, params, 'group1', 2, blocks[1]) 47 | o_g2 = group(o_g1, params, 'group2', 2, blocks[2]) 48 | o_g3 = group(o_g2, params, 'group3', 2, blocks[3]) 49 | if pooling_classif: 50 | o = F.avg_pool2d(o_g3, 7, 1, 0) 51 | o = o.view(o.size(0), -1) 52 | o = F.linear(o, params['fc.weight'], params['fc.bias']) 53 | return o 54 | 55 | return f 56 | 57 | 58 | class WideResNet(nn.Module): 59 | 60 | def __init__(self, pooling): 61 | super(WideResNet, self).__init__() 62 | self.pooling = pooling 63 | self.params = params 64 | 65 | def forward(self, x): 66 | x = f(x, self.params, self.pooling) 67 | return x 68 | 69 | 70 | def wideresnet50(pooling): 71 | dir_models = os.path.join(expanduser("~"), '.torch/wideresnet') 72 | path_hkl = os.path.join(dir_models, 'wideresnet50.hkl') 73 | if os.path.isfile(path_hkl): 74 | params = hkl.load(path_hkl) 75 | # convert numpy arrays to torch Variables 76 | for k,v in sorted(params.items()): 77 | print(k, v.shape) 78 | params[k] = Variable(torch.from_numpy(v), requires_grad=True) 79 | else: 80 | os.system('mkdir -p ' + dir_models) 81 | os.system('wget {} -O {}'.format(model_urls['wideresnet50'], path_hkl)) 82 | f = define_model(params) 83 | model = WideResNet(pooling) 84 | return model 85 | 86 | 87 | -------------------------------------------------------------------------------- /pretrainedmodels/models/xception.py: -------------------------------------------------------------------------------- 1 | """ 2 | Ported to pytorch thanks to [tstandley](https://github.com/tstandley/Xception-PyTorch) 3 | 4 | @author: tstandley 5 | Adapted by cadene 6 | 7 | Creates an Xception Model as defined in: 8 | 9 | Francois Chollet 10 | Xception: Deep Learning with Depthwise Separable Convolutions 11 | https://arxiv.org/pdf/1610.02357.pdf 12 | 13 | This weights ported from the Keras implementation. Achieves the following performance on the validation set: 14 | 15 | Loss:0.9173 Prec@1:78.892 Prec@5:94.292 16 | 17 | REMEMBER to set your image size to 3x299x299 for both test and validation 18 | 19 | normalize = transforms.Normalize(mean=[0.5, 0.5, 0.5], 20 | std=[0.5, 0.5, 0.5]) 21 | 22 | The resize parameter of the validation transform should be 333, and make sure to center crop at 299x299 23 | """ 24 | from __future__ import print_function, division, absolute_import 25 | import math 26 | import torch 27 | import torch.nn as nn 28 | import torch.nn.functional as F 29 | import torch.utils.model_zoo as model_zoo 30 | from torch.nn import init 31 | 32 | __all__ = ['xception'] 33 | 34 | pretrained_settings = { 35 | 'xception': { 36 | 'imagenet': { 37 | 'url': 'http://data.lip6.fr/cadene/pretrainedmodels/xception-43020ad28.pth', 38 | 'input_space': 'RGB', 39 | 'input_size': [3, 299, 299], 40 | 'input_range': [0, 1], 41 | 'mean': [0.5, 0.5, 0.5], 42 | 'std': [0.5, 0.5, 0.5], 43 | 'num_classes': 1000, 44 | 'scale': 0.8975 # The resize parameter of the validation transform should be 333, and make sure to center crop at 299x299 45 | } 46 | } 47 | } 48 | 49 | 50 | class SeparableConv2d(nn.Module): 51 | def __init__(self,in_channels,out_channels,kernel_size=1,stride=1,padding=0,dilation=1,bias=False): 52 | super(SeparableConv2d,self).__init__() 53 | 54 | self.conv1 = nn.Conv2d(in_channels,in_channels,kernel_size,stride,padding,dilation,groups=in_channels,bias=bias) 55 | self.pointwise = nn.Conv2d(in_channels,out_channels,1,1,0,1,1,bias=bias) 56 | 57 | def forward(self,x): 58 | x = self.conv1(x) 59 | x = self.pointwise(x) 60 | return x 61 | 62 | 63 | class Block(nn.Module): 64 | def __init__(self,in_filters,out_filters,reps,strides=1,start_with_relu=True,grow_first=True): 65 | super(Block, self).__init__() 66 | 67 | if out_filters != in_filters or strides!=1: 68 | self.skip = nn.Conv2d(in_filters,out_filters,1,stride=strides, bias=False) 69 | self.skipbn = nn.BatchNorm2d(out_filters) 70 | else: 71 | self.skip=None 72 | 73 | rep=[] 74 | 75 | filters=in_filters 76 | if grow_first: 77 | rep.append(nn.ReLU(inplace=True)) 78 | rep.append(SeparableConv2d(in_filters,out_filters,3,stride=1,padding=1,bias=False)) 79 | rep.append(nn.BatchNorm2d(out_filters)) 80 | filters = out_filters 81 | 82 | for i in range(reps-1): 83 | rep.append(nn.ReLU(inplace=True)) 84 | rep.append(SeparableConv2d(filters,filters,3,stride=1,padding=1,bias=False)) 85 | rep.append(nn.BatchNorm2d(filters)) 86 | 87 | if not grow_first: 88 | rep.append(nn.ReLU(inplace=True)) 89 | rep.append(SeparableConv2d(in_filters,out_filters,3,stride=1,padding=1,bias=False)) 90 | rep.append(nn.BatchNorm2d(out_filters)) 91 | 92 | if not start_with_relu: 93 | rep = rep[1:] 94 | else: 95 | rep[0] = nn.ReLU(inplace=False) 96 | 97 | if strides != 1: 98 | rep.append(nn.MaxPool2d(3,strides,1)) 99 | self.rep = nn.Sequential(*rep) 100 | 101 | def forward(self,inp): 102 | x = self.rep(inp) 103 | 104 | if self.skip is not None: 105 | skip = self.skip(inp) 106 | skip = self.skipbn(skip) 107 | else: 108 | skip = inp 109 | 110 | x+=skip 111 | return x 112 | 113 | 114 | class Xception(nn.Module): 115 | """ 116 | Xception optimized for the ImageNet dataset, as specified in 117 | https://arxiv.org/pdf/1610.02357.pdf 118 | """ 119 | def __init__(self, num_classes=1000): 120 | """ Constructor 121 | Args: 122 | num_classes: number of classes 123 | """ 124 | super(Xception, self).__init__() 125 | self.num_classes = num_classes 126 | 127 | self.conv1 = nn.Conv2d(3, 32, 3,2, 0, bias=False) 128 | self.bn1 = nn.BatchNorm2d(32) 129 | self.relu1 = nn.ReLU(inplace=True) 130 | 131 | self.conv2 = nn.Conv2d(32,64,3,bias=False) 132 | self.bn2 = nn.BatchNorm2d(64) 133 | self.relu2 = nn.ReLU(inplace=True) 134 | #do relu here 135 | 136 | self.block1=Block(64,128,2,2,start_with_relu=False,grow_first=True) 137 | self.block2=Block(128,256,2,2,start_with_relu=True,grow_first=True) 138 | self.block3=Block(256,728,2,2,start_with_relu=True,grow_first=True) 139 | 140 | self.block4=Block(728,728,3,1,start_with_relu=True,grow_first=True) 141 | self.block5=Block(728,728,3,1,start_with_relu=True,grow_first=True) 142 | self.block6=Block(728,728,3,1,start_with_relu=True,grow_first=True) 143 | self.block7=Block(728,728,3,1,start_with_relu=True,grow_first=True) 144 | 145 | self.block8=Block(728,728,3,1,start_with_relu=True,grow_first=True) 146 | self.block9=Block(728,728,3,1,start_with_relu=True,grow_first=True) 147 | self.block10=Block(728,728,3,1,start_with_relu=True,grow_first=True) 148 | self.block11=Block(728,728,3,1,start_with_relu=True,grow_first=True) 149 | 150 | self.block12=Block(728,1024,2,2,start_with_relu=True,grow_first=False) 151 | 152 | self.conv3 = SeparableConv2d(1024,1536,3,1,1) 153 | self.bn3 = nn.BatchNorm2d(1536) 154 | self.relu3 = nn.ReLU(inplace=True) 155 | 156 | #do relu here 157 | self.conv4 = SeparableConv2d(1536,2048,3,1,1) 158 | self.bn4 = nn.BatchNorm2d(2048) 159 | 160 | self.fc = nn.Linear(2048, num_classes) 161 | 162 | # #------- init weights -------- 163 | # for m in self.modules(): 164 | # if isinstance(m, nn.Conv2d): 165 | # n = m.kernel_size[0] * m.kernel_size[1] * m.out_channels 166 | # m.weight.data.normal_(0, math.sqrt(2. / n)) 167 | # elif isinstance(m, nn.BatchNorm2d): 168 | # m.weight.data.fill_(1) 169 | # m.bias.data.zero_() 170 | # #----------------------------- 171 | 172 | def features(self, input): 173 | x = self.conv1(input) 174 | x = self.bn1(x) 175 | x = self.relu1(x) 176 | 177 | x = self.conv2(x) 178 | x = self.bn2(x) 179 | x = self.relu2(x) 180 | 181 | x = self.block1(x) 182 | x = self.block2(x) 183 | x = self.block3(x) 184 | x = self.block4(x) 185 | x = self.block5(x) 186 | x = self.block6(x) 187 | x = self.block7(x) 188 | x = self.block8(x) 189 | x = self.block9(x) 190 | x = self.block10(x) 191 | x = self.block11(x) 192 | x = self.block12(x) 193 | 194 | x = self.conv3(x) 195 | x = self.bn3(x) 196 | x = self.relu3(x) 197 | 198 | x = self.conv4(x) 199 | x = self.bn4(x) 200 | return x 201 | 202 | def logits(self, features): 203 | x = nn.ReLU(inplace=True)(features) 204 | 205 | x = F.adaptive_avg_pool2d(x, (1, 1)) 206 | x = x.view(x.size(0), -1) 207 | x = self.last_linear(x) 208 | return x 209 | 210 | def forward(self, input): 211 | x = self.features(input) 212 | x = self.logits(x) 213 | return x 214 | 215 | 216 | def xception(num_classes=1000, pretrained='imagenet'): 217 | model = Xception(num_classes=num_classes) 218 | if pretrained: 219 | settings = pretrained_settings['xception'][pretrained] 220 | assert num_classes == settings['num_classes'], \ 221 | "num_classes should be {}, but is {}".format(settings['num_classes'], num_classes) 222 | 223 | model = Xception(num_classes=num_classes) 224 | model.load_state_dict(model_zoo.load_url(settings['url'])) 225 | 226 | model.input_space = settings['input_space'] 227 | model.input_size = settings['input_size'] 228 | model.input_range = settings['input_range'] 229 | model.mean = settings['mean'] 230 | model.std = settings['std'] 231 | 232 | # TODO: ugly 233 | model.last_linear = model.fc 234 | del model.fc 235 | return model 236 | -------------------------------------------------------------------------------- /pretrainedmodels/utils.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function, division, absolute_import 2 | import math 3 | import torch 4 | import torch.nn as nn 5 | import torchvision.transforms as transforms 6 | from PIL import Image 7 | from munch import munchify 8 | 9 | class ToSpaceBGR(object): 10 | 11 | def __init__(self, is_bgr): 12 | self.is_bgr = is_bgr 13 | 14 | def __call__(self, tensor): 15 | if self.is_bgr: 16 | new_tensor = tensor.clone() 17 | new_tensor[0] = tensor[2] 18 | new_tensor[2] = tensor[0] 19 | tensor = new_tensor 20 | return tensor 21 | 22 | 23 | class ToRange255(object): 24 | 25 | def __init__(self, is_255): 26 | self.is_255 = is_255 27 | 28 | def __call__(self, tensor): 29 | if self.is_255: 30 | tensor.mul_(255) 31 | return tensor 32 | 33 | 34 | class TransformImage(object): 35 | 36 | def __init__(self, opts, scale=0.875, random_crop=False, 37 | random_hflip=False, random_vflip=False, 38 | preserve_aspect_ratio=True): 39 | if type(opts) == dict: 40 | opts = munchify(opts) 41 | self.input_size = opts.input_size 42 | self.input_space = opts.input_space 43 | self.input_range = opts.input_range 44 | self.mean = opts.mean 45 | self.std = opts.std 46 | 47 | # https://github.com/tensorflow/models/blob/master/research/inception/inception/image_processing.py#L294 48 | self.scale = scale 49 | self.random_crop = random_crop 50 | self.random_hflip = random_hflip 51 | self.random_vflip = random_vflip 52 | 53 | tfs = [] 54 | if preserve_aspect_ratio: 55 | tfs.append(transforms.Resize(int(math.floor(max(self.input_size)/self.scale)))) 56 | else: 57 | height = int(self.input_size[1] / self.scale) 58 | width = int(self.input_size[2] / self.scale) 59 | tfs.append(transforms.Resize((height, width))) 60 | 61 | if random_crop: 62 | tfs.append(transforms.RandomCrop(max(self.input_size))) 63 | else: 64 | tfs.append(transforms.CenterCrop(max(self.input_size))) 65 | 66 | if random_hflip: 67 | tfs.append(transforms.RandomHorizontalFlip()) 68 | 69 | if random_vflip: 70 | tfs.append(transforms.RandomVerticalFlip()) 71 | 72 | tfs.append(transforms.ToTensor()) 73 | tfs.append(ToSpaceBGR(self.input_space=='BGR')) 74 | tfs.append(ToRange255(max(self.input_range)==255)) 75 | tfs.append(transforms.Normalize(mean=self.mean, std=self.std)) 76 | 77 | self.tf = transforms.Compose(tfs) 78 | 79 | def __call__(self, img): 80 | tensor = self.tf(img) 81 | return tensor 82 | 83 | 84 | class LoadImage(object): 85 | 86 | def __init__(self, space='RGB'): 87 | self.space = space 88 | 89 | def __call__(self, path_img): 90 | with open(path_img, 'rb') as f: 91 | with Image.open(f) as img: 92 | img = img.convert(self.space) 93 | return img 94 | 95 | 96 | class LoadTransformImage(object): 97 | 98 | def __init__(self, model, scale=0.875): 99 | self.load = LoadImage() 100 | self.tf = TransformImage(model, scale=scale) 101 | 102 | def __call__(self, path_img): 103 | img = self.load(path_img) 104 | tensor = self.tf(img) 105 | return tensor 106 | 107 | 108 | class Identity(nn.Module): 109 | 110 | def __init__(self): 111 | super(Identity, self).__init__() 112 | 113 | def forward(self, x): 114 | return x -------------------------------------------------------------------------------- /pretrainedmodels/version.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function, division, absolute_import 2 | __version__ = '0.7.4' 3 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | torch 2 | torchvision 3 | munch 4 | tqdm 5 | scipy 6 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [metadata] 2 | description-file = README.md -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function, division, absolute_import 2 | """A setuptools based setup module. 3 | 4 | See: 5 | https://packaging.python.org/en/latest/distributing.html 6 | https://github.com/pypa/sampleproject 7 | """ 8 | 9 | # Always prefer setuptools over distutils 10 | from setuptools import setup, find_packages 11 | # To use a consistent encoding 12 | from codecs import open 13 | from os import path 14 | 15 | here = path.abspath(path.dirname(__file__)) 16 | 17 | # Get the long description from the README file 18 | with open(path.join(here, 'README.md'), encoding='utf-8') as f: 19 | long_description = f.read() 20 | 21 | # Arguments marked as "Required" below must be included for upload to PyPI. 22 | # Fields marked as "Optional" may be commented out. 23 | 24 | # https://stackoverflow.com/questions/458550/standard-way-to-embed-version-into-python-package/16084844#16084844 25 | exec(open('pretrainedmodels/version.py').read()) 26 | setup( 27 | # This is the name of your project. The first time you publish this 28 | # package, this name will be registered for you. It will determine how 29 | # users can install this project, e.g.: 30 | # 31 | # $ pip install sampleproject 32 | # 33 | # And where it will live on PyPI: https://pypi.org/project/sampleproject/ 34 | # 35 | # There are some restrictions on what makes a valid project name 36 | # specification here: 37 | # https://packaging.python.org/specifications/core-metadata/#name 38 | name='pretrainedmodels', # Required 39 | 40 | # Versions should comply with PEP 440: 41 | # https://www.python.org/dev/peps/pep-0440/ 42 | # 43 | # For a discussion on single-sourcing the version across setup.py and the 44 | # project code, see 45 | # https://packaging.python.org/en/latest/single_source_version.html 46 | version=__version__, # Required 47 | 48 | # This is a one-line description or tagline of what your project does. This 49 | # corresponds to the "Summary" metadata field: 50 | # https://packaging.python.org/specifications/core-metadata/#summary 51 | description='Pretrained models for Pytorch', # Required 52 | 53 | # This is an optional longer description of your project that represents 54 | # the body of text which users will see when they visit PyPI. 55 | # 56 | # Often, this is the same as your README, so you can just read it in from 57 | # that file directly (as we have already done above) 58 | # 59 | # This field corresponds to the "Description" metadata field: 60 | # https://packaging.python.org/specifications/core-metadata/#description-optional 61 | long_description=long_description, # Optional 62 | 63 | # This should be a valid link to your project's main homepage. 64 | # 65 | # This field corresponds to the "Home-Page" metadata field: 66 | # https://packaging.python.org/specifications/core-metadata/#home-page-optional 67 | url='https://github.com/cadene/pretrained-models.pytorch', # Optional 68 | 69 | # This should be your name or the name of the organization which owns the 70 | # project. 71 | author='Remi Cadene', # Optional 72 | 73 | # This should be a valid email address corresponding to the author listed 74 | # above. 75 | author_email='remi.cadene@icloud.com', # Optional 76 | 77 | # Classifiers help users find your project by categorizing it. 78 | # 79 | # For a list of valid classifiers, see 80 | # https://pypi.python.org/pypi?%3Aaction=list_classifiers 81 | classifiers=[ # Optional 82 | # How mature is this project? Common values are 83 | # 3 - Alpha 84 | # 4 - Beta 85 | # 5 - Production/Stable 86 | 'Development Status :: 3 - Alpha', 87 | 88 | # Indicate who your project is intended for 89 | 'Intended Audience :: Developers', 90 | 'Topic :: Software Development :: Build Tools', 91 | 92 | # Pick your license as you wish 93 | 'License :: OSI Approved :: MIT License', 94 | 95 | # Specify the Python versions you support here. In particular, ensure 96 | # that you indicate whether you support Python 2, Python 3 or both. 97 | 'Programming Language :: Python :: 3.6', 98 | ], 99 | 100 | # This field adds keywords for your project which will appear on the 101 | # project page. What does your project relate to? 102 | # 103 | # Note that this is a string of words separated by whitespace, not a list. 104 | keywords='pytorch pretrained models deep learning', # Optional 105 | 106 | # You can just specify package directories manually here if your project is 107 | # simple. Or you can use find_packages(). 108 | # 109 | # Alternatively, if you just want to distribute a single Python file, use 110 | # the `py_modules` argument instead as follows, which will expect a file 111 | # called `my_module.py` to exist: 112 | # 113 | # py_modules=["my_module"], 114 | # 115 | packages=find_packages(exclude=['data', 'examples']), # Required 116 | 117 | # This field lists other packages that your project depends on to run. 118 | # Any package you put here will be installed by pip when your project is 119 | # installed, so they must be valid existing projects. 120 | # 121 | # For an analysis of "install_requires" vs pip's requirements files see: 122 | # https://packaging.python.org/en/latest/requirements.html 123 | install_requires=['torch', 'torchvision', 'munch', 'tqdm'], # Optional 124 | 125 | # List additional groups of dependencies here (e.g. development 126 | # dependencies). Users will be able to install these using the "extras" 127 | # syntax, for example: 128 | # 129 | # $ pip install sampleproject[dev] 130 | # 131 | # Similar to `install_requires` above, these must be valid existing 132 | # projects. 133 | # extras_require={ # Optional 134 | # 'dev': ['check-manifest'], 135 | # 'test': ['coverage'], 136 | # }, 137 | 138 | # If there are data files included in your packages that need to be 139 | # installed, specify them here. 140 | # 141 | # If using Python 2.6 or earlier, then these have to be included in 142 | # MANIFEST.in as well. 143 | # package_data={ # Optional 144 | # 'sample': ['package_data.dat'], 145 | # }, 146 | 147 | # Although 'package_data' is the preferred approach, in some case you may 148 | # need to place data files outside of your packages. See: 149 | # http://docs.python.org/3.4/distutils/setupscript.html#installing-additional-files 150 | # 151 | # In this case, 'data_file' will be installed into '/my_data' 152 | #data_files=[('my_data', ['data/data_file'])], # Optional 153 | 154 | # To provide executable scripts, use entry points in preference to the 155 | # "scripts" keyword. Entry points provide cross-platform support and allow 156 | # `pip` to create the appropriate form of executable for the target 157 | # platform. 158 | # 159 | # For example, the following would provide a command called `sample` which 160 | # executes the function `main` from this package when invoked: 161 | # entry_points={ # Optional 162 | # 'console_scripts': [ 163 | # 'sample=sample:main', 164 | # ], 165 | # }, 166 | ) 167 | -------------------------------------------------------------------------------- /tests/test_pm_imagenet.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | import torch 3 | import torch.nn as nn 4 | from torch.autograd import Variable 5 | import pretrainedmodels as pm 6 | import pretrainedmodels.utils as utils 7 | 8 | # torch 1.0.x 9 | set_grad_enabled = getattr(torch.autograd, 'set_grad_enabled', None) 10 | 11 | pm_args = [] 12 | for model_name in pm.model_names: 13 | for pretrained in pm.pretrained_settings[model_name]: 14 | if pretrained in ['imagenet', 'imagenet+5k']: 15 | pm_args.append((model_name, pretrained)) 16 | 17 | img = utils.LoadImage()('data/cat.jpg') 18 | 19 | 20 | def equal(x,y): 21 | return torch.all(torch.lt(torch.abs(torch.add(x, -y)), 1e-12)) 22 | 23 | @pytest.mark.parametrize('model_name, pretrained', pm_args) 24 | def test_pm_imagenet(model_name, pretrained): 25 | if set_grad_enabled: set_grad_enabled(False) 26 | 27 | print('test_pm_imagenet("{}")'.format(model_name)) 28 | net = pm.__dict__[model_name]( 29 | num_classes=1000, 30 | pretrained=pretrained) 31 | net.eval() 32 | 33 | tensor = utils.TransformImage(net)(img) 34 | tensor = tensor.unsqueeze(0) 35 | x = Variable(tensor, requires_grad=False) 36 | 37 | out_logits = net(x) 38 | if 'squeezenet' in model_name: 39 | # Conv2d without view at the end 40 | assert out_logits.shape == torch.Size([1,1000,1,1]) 41 | return 42 | 43 | assert out_logits.shape == torch.Size([1,1000]) 44 | 45 | out_feats = net.features(x) 46 | out_logits_2 = net.logits(out_feats) 47 | assert equal(out_logits, out_logits_2) 48 | 49 | if 'dpn' in model_name: 50 | # Conv2d instead of Linear 51 | return 52 | net.last_linear = nn.Linear( 53 | net.last_linear.in_features, 54 | 10) 55 | 56 | out_logits_3 = net.logits(out_feats) 57 | assert out_logits_3.shape == torch.Size([1,10]) 58 | 59 | if set_grad_enabled: set_grad_enabled(True) 60 | -------------------------------------------------------------------------------- /tests/test_torch_save.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | import torch 3 | import pretrainedmodels as pm 4 | 5 | 6 | # TODO: put "pm_args" into fixture to share with all tests? 7 | pm_args = [] 8 | for model_name in pm.model_names: 9 | for pretrained in pm.pretrained_settings[model_name]: 10 | if pretrained in ['imagenet', 'imagenet+5k']: 11 | pm_args.append((model_name, pretrained)) 12 | 13 | 14 | @pytest.mark.parametrize('model_name, pretrained', pm_args) 15 | def test_torch_save(model_name, pretrained, tmp_path): 16 | print('test_torch_save("{}")'.format(model_name)) 17 | net = pm.__dict__[model_name]( 18 | num_classes=1000, 19 | pretrained=pretrained) 20 | 21 | tmp_file = tmp_path/'{}.pkl'.format(model_name) 22 | torch.save(net, tmp_file.open('wb')) 23 | tmp_file.unlink() 24 | --------------------------------------------------------------------------------