From bb62ad767d2bd2916f1afc14422974724ef82fc9 Mon Sep 17 00:00:00 2001 From: Francesco Paissan <46992226+fpaissan@users.noreply.github.com> Date: Sat, 3 Jun 2023 17:24:33 +0200 Subject: [PATCH] Release 0.0.5 (#26) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Extended unit tests to classifier and fixed pooling (#17) * Extended unit tests to classifier and fixed pooling * Changed trigger of doctest workflow * Fixing issue #18 * fixed linters * Add pre-commit hooks * Doctest only on PRs * Fixed network conversion from GPU Also tested on Windows machine. * Create python_versions.yml * Update and rename python_versions.yml to tests.yml * Update export.yaml * CI fix (#21) * Create pre-commit.yaml * remove code.yaml * fixing pre-commit * Doctest with pytest * change trigger * change trigger * Delete LICENSE * checkpoint from filesystem (#20) * checkpoint from filesystem * fixed deps * Update README.md * Update LICENSE * Updating LICENSE --------- Co-authored-by: fpaissan Co-authored-by: Francesco Paissan <46992226+fpaissan@users.noreply.github.com> * Create LICENSE (#22) * Update README.md (#23) * new min python version to 3.8 * 🐛 extra_requirements now have a version - fixed CI (#24) * 🐛 extra_requirements now have a version * fixed linter errors * testing actions * fixed linter * removing tf_probability * fixed tf prob version --------- Co-authored-by: fpaissan * Documentation upgrade - guide for contribution (#25) * add contribution guide to docs * documentation with contribution guide --------- Co-authored-by: Matteo Beltrami <71525176+matteobeltrami@users.noreply.github.com> Co-authored-by: SebastianCavada --- .github/workflows/code.yaml | 27 --- .github/workflows/doctest.yaml | 27 --- .github/workflows/export.yaml | 28 --- .github/workflows/pre-commit.yaml | 12 + .github/workflows/pypi.yml | 2 +- .github/workflows/tests.yml | 35 +++ .pre-commit-config.yaml | 15 ++ CHANGELOG | 7 + LICENSE | 222 ++++++++++++++++-- README.md | 73 +++--- docs/docs-requirements.txt | 2 +- docs/source/contribution.rst | 94 ++++++++ docs/source/index.rst | 7 + micromind/__init__.py | 2 +- micromind/conversion/convert.py | 43 ++-- micromind/networks/phinet.py | 77 +++--- pyproject.toml | 16 +- recipes/image_classification/README.md | 2 +- .../extra_requirements.txt | 2 +- requirements.txt | 2 +- tests/test_networks.py | 12 +- 21 files changed, 505 insertions(+), 202 deletions(-) delete mode 100644 .github/workflows/code.yaml delete mode 100644 .github/workflows/doctest.yaml delete mode 100644 .github/workflows/export.yaml create mode 100644 .github/workflows/pre-commit.yaml create mode 100644 .github/workflows/tests.yml create mode 100644 .pre-commit-config.yaml create mode 100644 CHANGELOG create mode 100644 docs/source/contribution.rst diff --git a/.github/workflows/code.yaml b/.github/workflows/code.yaml deleted file mode 100644 index 8b5735e..0000000 --- a/.github/workflows/code.yaml +++ /dev/null @@ -1,27 +0,0 @@ -name: code_style - -on: push - -jobs: - style: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: Black - uses: psf/black@stable - with: - options: "--check --verbose" - - name: Setup Python for flake8 - uses: actions/setup-python@v1 - with: - python-version: 3.9 - architecture: x64 - - uses: actions/checkout@master - - name: Install flake8 - run: pip install flake8 - - name: Run flake8 - uses: suo/flake8-github-action@releases/v1 - with: - checkName: 'flake8_py3' # NOTE: this needs to be the same as the job name - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/doctest.yaml b/.github/workflows/doctest.yaml deleted file mode 100644 index 62b07b0..0000000 --- a/.github/workflows/doctest.yaml +++ /dev/null @@ -1,27 +0,0 @@ -name: Verify docs generation - -# Runs on pushes to master and all pull requests -on: # yamllint disable-line rule:truthy - push: - pull_request: - -jobs: - docs: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: Setup Python 3.9 - uses: actions/setup-python@v2 - with: - python-version: '3.9' - - name: Full dependencies - run: | - pip install -r requirements.txt - pip install --editable . - pip install -r docs/docs-requirements.txt - - name: Generate docs - run: | - cd docs - make doctest - make html - diff --git a/.github/workflows/export.yaml b/.github/workflows/export.yaml deleted file mode 100644 index 5855a25..0000000 --- a/.github/workflows/export.yaml +++ /dev/null @@ -1,28 +0,0 @@ -name: Unit tests - -on: push - -permissions: - contents: read - -jobs: - build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - name: Set up Python 3.10 - uses: actions/setup-python@v3 - with: - python-version: "3.10" - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install pytest torch - pip install . - - name: set PYTHONPATH - run: | - echo "PYTHONPATH=$PYTHONPATH:`pwd`" >> $GITHUB_ENV - - name: pytest - run: | - pytest tests - diff --git a/.github/workflows/pre-commit.yaml b/.github/workflows/pre-commit.yaml new file mode 100644 index 0000000..073325c --- /dev/null +++ b/.github/workflows/pre-commit.yaml @@ -0,0 +1,12 @@ +name: pre-commit + +on: + push: + +jobs: + pre-commit: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-python@v3 + - uses: pre-commit/action@v3.0.0 diff --git a/.github/workflows/pypi.yml b/.github/workflows/pypi.yml index 961c9b3..efc887b 100644 --- a/.github/workflows/pypi.yml +++ b/.github/workflows/pypi.yml @@ -1,4 +1,4 @@ -name: Publish distributions to PyPI +name: Publish distributions to PyPI on: push: diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 0000000..c28d562 --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,35 @@ +# This workflow will install Python dependencies, run tests and lint with a variety of Python versions +# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python + +name: micromind[conversion] CI + +on: + push: + +jobs: + build: + + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + python-version: ["3.8", "3.9", "3.10"] + + steps: + - uses: actions/checkout@v3 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v3 + with: + python-version: ${{ matrix.python-version }} + - name: Install dependencies + run: | + python -m pip install --upgrade pip + python -m pip install pytest + if [ -f requirements.txt ]; then pip install -r requirements.txt; fi + python -m pip install -e .[conversion] + - name: Unit tests + run: | + pytest tests/ + - name: Doctest + run: | + pytest --doctest-modules micromind diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..2696a36 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,15 @@ +repos: +- repo: https://github.com/pre-commit/pre-commit-hooks + rev: v2.3.0 + hooks: + - id: check-yaml + - id: end-of-file-fixer + - id: trailing-whitespace +- repo: https://github.com/psf/black + rev: 22.10.0 + hooks: + - id: black +- repo: https://github.com/pycqa/flake8 + rev: '6.0.0' # pick a git hash / tag to point to + hooks: + - id: flake8 diff --git a/CHANGELOG b/CHANGELOG new file mode 100644 index 0000000..ede4804 --- /dev/null +++ b/CHANGELOG @@ -0,0 +1,7 @@ +# Release 0.0.5 + +1. Improved unit tests; +2. Extended CI to multiple python versions (including 3.8 compatibility); +3. Updated LICENSE to Apache 2.0; +4. Minor fixes to image classification recipes; +5. Added guide to contribution in the documentation; diff --git a/LICENSE b/LICENSE index 8aa2645..091686c 100644 --- a/LICENSE +++ b/LICENSE @@ -1,21 +1,201 @@ -MIT License - -Copyright (c) [year] [fullname] - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [2023] [Francesco Paissan] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README.md b/README.md index bc55aa0..b3e0fd2 100644 --- a/README.md +++ b/README.md @@ -1,53 +1,54 @@ -
- -[![Paper](http://img.shields.io/badge/paper-arxiv.1001.2234-B31B1B.svg)](https://arxiv.org/abs/2110.00337) +[![Python version: 3.8 | 3.9 | 3.10](https://img.shields.io/badge/python-3.9%20|%203.10-blue)](https://www.python.org/downloads/) +[![License](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://github.com/fpaissan/micromind/blob/main/LICENSE) +![PyPI version](https://img.shields.io/pypi/v/micromind) -
+This is the official repo of `micromind`, a toolkit that aims at bridging two communities: artificial intelligence and embedded systems. `micromind` is based on [PyTorch](https://pytorch.org) and provides exportability for the supported models in ONNX, Intel OpenVINO, and TFLite. -This repository is a collection of our efforts towards the design, implementation and evaluation of ML techniques in the field of tinyML. +--------------------------------------------------------------------------------------------------------- -Here is a list of things you can do with the `phinet` package: - - [image classification](recipes/image_classification) +## 💡 Key features -## To install the package +- Smooth flow from research to deployment; +- Support for multimedia analytics recipes (image classification, sound event detection, etc); +- Detailed API documentation; +- Tutorials for embedded deployment; -```setup -pip install git+https://github.com/fpaissan/phinet -``` +--------------------------------------------------------------------------------------------------------- + +## 🛠️️ Installation + +### Using Pip + +First of all, install [Python 3.8 or later](https://www.python.org). Open a terminal and run: -## Cite us ``` -@article{10.1145/3510832, - author = {Paissan, Francesco and Ancilotto, Alberto and Farella, Elisabetta}, - title = {PhiNets: A Scalable Backbone for Low-Power AI at the Edge}, - year = {2022}, - publisher = {Association for Computing Machinery}, - address = {New York, NY, USA}, - url = {https://doi.org/10.1145/3510832}, - doi = {10.1145/3510832}, - journal = {ACM Trans. Embed. Comput. Syst.}, -} +pip install micromind ``` - +--------------------------------------------------------------------------------------------------------- diff --git a/docs/docs-requirements.txt b/docs/docs-requirements.txt index 6265068..a47b25b 100644 --- a/docs/docs-requirements.txt +++ b/docs/docs-requirements.txt @@ -1,2 +1,2 @@ sphinx-rtd-theme>=0.4.3 -Sphinx>=3.4.3 \ No newline at end of file +Sphinx>=3.4.3 diff --git a/docs/source/contribution.rst b/docs/source/contribution.rst new file mode 100644 index 0000000..e47f9bb --- /dev/null +++ b/docs/source/contribution.rst @@ -0,0 +1,94 @@ +Guide for Contributing to micromind +=================================== + +Step 0 - Preparing the Environment +---------------------------------- + +To ensure there are no conflicts between different library versions, +and that the CI pipeline works the same both locally and online, +it's recommended to create a dedicated environment for micromind. +After installing `Anaconda `_, you can achieve this with: + +.. code-block:: shell + + conda create -n micromind python=3.8 + +Optionally, you can replace "micromind" with a name that you prefer for the environment. + +Step 1 - Creating a Fork from the Original Repository +----------------------------------------------------- + +Fork (and star! ⭐) the micromind repository to work on the project without any limitations +related to accesses to the official repository. + + +Step 2 - Installation +--------------------- + +After you have cloned the forked repository locally, navigate to the root folder and install +``micromind`` in editable mode, using the following command: + +.. code-block:: shell + + pip install -e .[conversion] + +Step 3 - Creating a New Branch +------------------------------ + +To contribute with new features in micromind, create a new branch and give it a significant name. +This might pertain to a new feature, patch, or bug fix that you're working on. + +.. code-block:: shell + + git checkout -b your-branch-name + +Step 4 - Implementing Changes +----------------------------- + +On the new branch, unleash your creativity and commit all the changes modifications as you +normally would. + +Step 5 - Unit tests and linters check +------------------------------------- + +Linters +~~~~~~~ +Before being merged, the code needs to pass unit tests and linters check. +To check if your modified codebase does so, you can install pre-commit hooks: + +.. code-block:: shell + + pip install pre-commit + +To configure pre-commit with the same settings decided for micromind, you should run + +.. code-block:: shell + + pre-commit install + +from inside the micromind root folder. pre-commit will check linters every time you +make a commit to the repo. + +Unit tests +~~~~~~~~~~ +To run unit tests, you should run + +.. code-block:: shell + + pytest tests/ + +**Moreover, you should write additional tests if your contribution requires so.** + +Step 6 - Making a Pull Request +------------------------------ + +Once your changes are complete, please contribute to the toolkit by creating a pull request. +Here are some guidelines for a good pull request, adapted from +`GitHub's blog post `_: + +* **Reason for the Pull Request**: clearly explain why you're making this pull request and what value it brings to the project; + +* **Changes Made**: Describe the new behaviors, error fixes, or features that have been added. + +By following these steps, you'll be well-equipped to make meaningful contributions to the project. +Happy coding! diff --git a/docs/source/index.rst b/docs/source/index.rst index 692d6f5..9f114f7 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -19,3 +19,10 @@ Indices and tables * :ref:`genindex` * :ref:`modindex` * :ref:`search` + + +.. toctree:: + :maxdepth: 2 + :caption: How To Contribute + + contribution diff --git a/micromind/__init__.py b/micromind/__init__.py index 9eda0ea..3711e9f 100644 --- a/micromind/__init__.py +++ b/micromind/__init__.py @@ -3,7 +3,7 @@ # Package version -__version__ = "0.0.4" +__version__ = "0.0.5" """datasets_info is a dictionary that contains information about the attributes of the datasets. diff --git a/micromind/conversion/convert.py b/micromind/conversion/convert.py index 197d005..f8be0aa 100644 --- a/micromind/conversion/convert.py +++ b/micromind/conversion/convert.py @@ -6,29 +6,35 @@ - Francesco Paissan, 2023 - Alberto Ancilotto, 2023 """ -import os -import shutil -import sys -from pathlib import Path - -import numpy as np -import onnx -import onnxsim -import tensorflow as tf -import torch -import torch.nn as nn -from onnx_tf.backend import prepare -from openvino.tools.mo import main as mo_main +try: + import os + import shutil + import sys + from pathlib import Path + + import numpy as np + import onnx + import onnxsim + import tensorflow as tf + import torch + import torch.nn as nn + from onnx_tf.backend import prepare + from openvino.tools.mo import main as mo_main +except Exception as e: + print(str(e)) + print("Did you install micromind with conversion capabilities?") + print("Please try again after pip install micromind[conversion].") + quit() @torch.no_grad() def convert_to_onnx(net: nn.Module, save_path: Path, simplify: bool = True): """Converts nn.Module to onnx and saves it to save_path. Optionally simplifies it.""" - x = torch.zeros([1] + net.input_shape) + x = torch.zeros([1] + list(net.input_shape)) torch.onnx.export( - net, + net.cpu(), x, save_path, verbose=False, @@ -88,13 +94,18 @@ def convert_to_tflite( if not isinstance(save_path, Path): save_path = Path(save_path) + if not (batch_quant is None): + batch_quant = batch_quant.cpu() + vino_sub = save_path.joinpath("vino") os.makedirs(vino_sub, exist_ok=True) vino_path = convert_to_openvino(net, vino_sub) if os.name == "nt": openvino2tensorflow_exe_cmd = [ sys.executable, - os.path.join(os.path.dirname(sys.executable), "openvino2tensorflow"), + os.path.join( + os.path.dirname(sys.executable), "Scripts", "openvino2tensorflow" + ), ] else: openvino2tensorflow_exe_cmd = ["openvino2tensorflow"] diff --git a/micromind/networks/phinet.py b/micromind/networks/phinet.py index 916b5b0..96dd119 100644 --- a/micromind/networks/phinet.py +++ b/micromind/networks/phinet.py @@ -17,6 +17,7 @@ from huggingface_hub import hf_hub_download from huggingface_hub.utils import EntryNotFoundError from torchinfo import summary +import os import micromind @@ -419,13 +420,15 @@ def from_pretrained( t_zero, num_layers, resolution, + path=None, num_classes=None, classifier=True, device=None, ): - """Loads parameters from checkpoint through Hugging Face Hub. - This function constructs two strings, "repo_dir" to find the model on Hugging - Face Hub and "file_to_choose" to select the correct file inside the repo, and + """Loads parameters from checkpoint through Hugging Face Hub or through local + file system. + This function constructs two strings, `repo_dir` to find the model on Hugging + Face Hub and `file_to_choose` to select the correct file inside the repo, and use them to download the pretrained model and initialize the PhiNet. Arguments @@ -442,6 +445,9 @@ def from_pretrained( The number of layers. resolution : int The resolution of the images used during training. + path : string + The directory path or file path pointing to the checkpoint. + If None, the checkpoint is searched on HuggingFace. num_classes : int The number of classes that the model has been trained for. If None, it gets the specific value determined by the dataset used. @@ -461,6 +467,7 @@ def from_pretrained( >>> from micromind import PhiNet >>> model = PhiNet.from_pretrained("CIFAR-10", 3.0, 0.75, 6.0, 7, 160) + Checkpoint taken from HuggingHace hub. Checkpoint loaded successfully. """ if num_classes is None: @@ -484,25 +491,41 @@ def from_pretrained( else: device = "cpu" - try: - downloaded_file_path = hf_hub_download( - repo_id=repo_dir, filename=file_to_choose - ) - state_dict = torch.load(str(downloaded_file_path), map_location=device) - model_found = True - - except EntryNotFoundError: - state_dict = { - "args": SimpleNamespace( - alpha=alpha, - beta=beta, - t_zero=t_zero, - num_layers=num_layers, - num_classes=num_classes, + if path is not None: + path_to_search = os.path.join(path, file_to_choose) + if os.path.isfile(path): + path_to_search = path + if os.path.isfile(path_to_search): + state_dict = torch.load(str(path_to_search), map_location=device) + model_found = True + print("Checkpoint taken from local file system.") + else: + model_found = False + print( + "Checkpoint not taken from local file system." + + f"{path_to_search} is not a valid checkpoint." ) - } - model_found = False - logging.warning("Model initialized without loading checkpoint.") + if (path is None) or not model_found: + try: + downloaded_file_path = hf_hub_download( + repo_id=repo_dir, filename=file_to_choose + ) + state_dict = torch.load(str(downloaded_file_path), map_location=device) + print("Checkpoint taken from HuggingHace hub.") + model_found = True + + except EntryNotFoundError: + state_dict = { + "args": SimpleNamespace( + alpha=alpha, + beta=beta, + t_zero=t_zero, + num_layers=num_layers, + num_classes=num_classes, + ) + } + model_found = False + logging.warning("Model initialized without loading checkpoint.") # model initialized model = cls( @@ -829,10 +852,10 @@ def __init__( if include_top: # Includes classification head if required - self.glob_pooling = lambda x: nn.functional.avg_pool2d(x, x.size()[2:]) - - self.new_convolution = nn.Conv2d( - int(block_filters * alpha), num_classes, kernel_size=1, bias=True + self.classifier = nn.Sequential( + nn.AdaptiveAvgPool2d((1, 1)), + nn.Flatten(), + nn.Linear(int(block_filters * alpha), num_classes, bias=True), ) def forward(self, x): @@ -851,8 +874,6 @@ def forward(self, x): x = layers(x) if self.classify: - x = self.glob_pooling(x) - x = self.new_convolution(x) - x = x.view(-1, x.shape[1]) + x = self.classifier(x) return x diff --git a/pyproject.toml b/pyproject.toml index 3821327..d149ffd 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -14,7 +14,7 @@ readme = "README.md" authors = [{ name = "Francesco Paissan & others", email = "francescopaissan@gmail.com" }] license = { file = "LICENSE" } classifiers = [ - "License :: OSI Approved :: MIT License", + "License :: OSI Approved :: Apache License", "Programming Language :: Python", "Programming Language :: Python :: 3", ] @@ -23,6 +23,12 @@ dependencies = [ "torch", "torchinfo", "huggingface_hub", +] +requires-python = ">=3.8" + +[project.optional-dependencies] +dev = ["black", "bumpver", "flake8", "isort", "pip-tools", "pytest", "pre-commit"] +conversion = [ "onnx", "onnx_tf==1.10.0", "onnx-simplifier==0.4.13", @@ -31,12 +37,8 @@ dependencies = [ "openvino2tensorflow==1.34.0", "tensorflow_datasets==4.8.1", "tensorflow==2.11.0", - "tensorflow_probability" + "tensorflow_probability==0.19.0" ] -requires-python = ">=3.9" - -[project.optional-dependencies] -dev = ["black", "bumpver", "flake8", "isort", "pip-tools", "pytest"] [project.urls] Homepage = "https://github.com/fpaissan/micromind" @@ -51,7 +53,7 @@ profile = "black" py-modules = [] [tool.bumpver] -current_version = "0.0.4" +current_version = "0.0.5" version_pattern = "MAJOR.MINOR.PATCH" commit_message = "bump version {old_version} -> {new_version}" commit = true diff --git a/recipes/image_classification/README.md b/recipes/image_classification/README.md index 6840db0..50dd16c 100644 --- a/recipes/image_classification/README.md +++ b/recipes/image_classification/README.md @@ -7,7 +7,7 @@ To reproduce our results, you can follow these steps: 1. install PhiNets with `pip install git+https://github.com/fpaissan/micromind` 2. install the additional dependencies for this recipe with `pip install -r extra_requirements.txt` -2. launch the training script on the dataset you want +2. launch the training script on the dataset you want ### MNIST ``` diff --git a/recipes/image_classification/extra_requirements.txt b/recipes/image_classification/extra_requirements.txt index 281c8ae..bdbf074 100644 --- a/recipes/image_classification/extra_requirements.txt +++ b/recipes/image_classification/extra_requirements.txt @@ -1 +1 @@ -timm +timm==0.6.13 diff --git a/requirements.txt b/requirements.txt index 43f1056..ce51b70 100644 --- a/requirements.txt +++ b/requirements.txt @@ -28,7 +28,7 @@ packaging==23.0 # via huggingface-hub pyyaml==6.0 # via huggingface-hub -requests==2.28.2 +requests==2.31.0 # via huggingface-hub torch==1.13.1 # via micromind (pyproject.toml) diff --git a/tests/test_networks.py b/tests/test_networks.py index f6599bf..09c87f5 100644 --- a/tests/test_networks.py +++ b/tests/test_networks.py @@ -13,8 +13,8 @@ def test_onnx(): save_path = "temp.onnx" - in_shape = list((3, 224, 224)) - net = PhiNet(in_shape, compatibility=False) + in_shape = (3, 224, 224) + net = PhiNet(in_shape, compatibility=False, include_top=True) convert_to_onnx(net, save_path, simplify=True) import os @@ -34,8 +34,8 @@ def test_openvino(): save_dir = "vino" - in_shape = list((3, 224, 224)) - net = PhiNet(in_shape, compatibility=False) + in_shape = (3, 224, 224) + net = PhiNet(in_shape, compatibility=False, include_top=True) convert_to_openvino(net, save_dir) @@ -50,8 +50,8 @@ def test_tflite(): save_path = "tflite" - in_shape = list((3, 224, 224)) - net = PhiNet(in_shape, compatibility=False) + in_shape = (3, 224, 224) + net = PhiNet(in_shape, compatibility=False, include_top=True) convert_to_tflite(net, save_path)