Skip to content
This repository was archived by the owner on Nov 13, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions .flake8
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#########################
# Flake8 Configuration #
# (.flake8) #
#########################
[flake8]
ignore =
# asserts are ok when testing.
S101
# pickle
S301
# pickle
S403
S404
S603
# Line break before binary operator (flake8 is wrong)
W503
# Ignore the spaces black puts before columns.
E203
# allow path extensions for testing.
E402
DAR101
DAR201
# flake and pylance disagree on linebreaks in strings.
N400
N806
exclude =
.tox,
.git,
__pycache__,
docs/source/conf.py,
build,
dist,
tests/fixtures/*,
*.pyc,
*.bib,
*.egg-info,
.cache,
.eggs,
data.
max-line-length = 120
max-complexity = 20
import-order-style = pycharm
application-import-names =
seleqt
tests
33 changes: 33 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: Tests
on: [ push, pull_request ]
jobs:
tests:
name: Tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install uv
uses: astral-sh/setup-uv@v3
- name: Set up Python 3.8.20
run: uv python install 3.8.20
- name: Install dependencies (CPU only)
run: uv sync --extra cpu --no-dev
- name: Test with pytest
run: uv run pytest

lint:
name: Lint
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.8.20"]
steps:
- uses: actions/checkout@v4
- name: Install uv
uses: astral-sh/setup-uv@v3
- name: Set up Python ${{ matrix.python-version }}
run: uv python install ${{ matrix.python-version }}
- name: Install dependencies
run: uv tool install flake8
- name: Run flake8
run: uv tool run flake8 src/ tests/
170 changes: 170 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/

# Translations
*.mo
*.pot

# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal

# Flask stuff:
instance/
.webassets-cache

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
.pybuilder/
target/

# Jupyter Notebook
.ipynb_checkpoints

# IPython
profile_default/
ipython_config.py

# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version

# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock

# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock

# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm.fming.dev/latest/usage/project/#working-with-version-control
.pdm.toml
.pdm-python
.pdm-build/

# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/

# Celery stuff
celerybeat-schedule
celerybeat.pid

# SageMath parsed files
*.sage.py

# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# Spyder project settings
.spyderproject
.spyproject

# Rope project settings
.ropeproject

# mkdocs documentation
/site

# mypy
.mypy_cache/
.dmypy.json
dmypy.json

# Pyre type checker
.pyre/

# pytype static type analyzer
.pytype/

# Cython debug symbols
cython_debug/

# PyCharm
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
data/
*.npz
*.out
*.pt

vtab-1k/
wandb/
.vscode/
33 changes: 33 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
repos:
- repo: local
hooks:
- id: isort
name: isort
entry: uv run isort
language: system
args: ["--profile", "black"]
files: ^(src/|tests/)
types: [python]

- id: black
name: black
entry: uv run black
language: system
args: ["--target-version", "py312"]
files: ^(src/|tests/)
types: [python]

- id: flake8
name: flake8
entry: uv run flake8
language: system
files: ^(src/|tests/)$
types: [python]

- id: pytest
name: pytest
entry: uv run pytest
language: system
files: ^(tests/)$
pass_filenames: false
always_run: true
1 change: 1 addition & 0 deletions .python-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3.8.20
27 changes: 27 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
.PHONY: format check-format test lint check-all typing all

# Format code
format:
uv run isort tests/ src/
uv run black tests/ src/

# Check formatting (without making changes)
check-format:
uv run isort --check-only --diff tests/ src/
uv run black --check --diff tests/ src/

lint:
uv run flake8 tests/ src/

test:
uv run pytest

# Run all pre-commit checks manually
check-all:
uv run pre-commit run --all-files

install-precommit:
uv run pre-commit install --hook-type pre-push

all: format test lint
@echo "All checks passed!"
60 changes: 55 additions & 5 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,60 @@ Gall <https://pages.iai.uni-bonn.de/gall_juergen/>`__\ :sup:`1,3`
**Abstract:** Modern methods for fine-tuning a Vision Transformer (ViT) like Low-Rank Adaptation (LoRA) and its variants demonstrate impressive performance. However, these methods ignore the high-dimensional nature of Multi-Head Attention (MHA) weight tensors. To address this limitation, we propose Canonical Rank Adaptation (CaRA). CaRA leverages tensor mathematics, first by tensorising the transformer into two different tensors; one for projection layers in MHA and the other for feed-forward layers. Second, the tensorised formulation is fine-tuned using the low-rank adaptation in Canonical-Polyadic Decomposition (CPD) form. Employing CaRA efficiently minimizes the number of trainable parameters. Experimentally, CaRA outperforms existing Parameter-Efficient Fine-Tuning (PEFT) methods in visual classification benchmarks such as Visual Task Adaptation Benchmark (VTAB)-1k and Fine-Grained Visual Categorization (FGVC).


Note
****
We are commited to providing thoroughly tested and well-packaged code.
The code will be soon released once the process is completed.
.. image:: https://raw.githubusercontent.com/BonnBytes/CaRA/refs/heads/dev/images/tensorisation.jpg
:width: 100%
:alt: Alternative text


Installation
============

Use `UV <https://docs.astral.sh/uv/>`_ to install the requirements

For CPU based pytorch

.. code:: bash

uv sync --extra cpu

For CUDA based pytorch

.. code:: bash

uv sync --extra cu118


Datasets
=======

In the case of VTAB-1k benchmark, refer to the dataset download instructions from `NOAH <https://github.com/ZhangYuanhan-AI/NOAH>`_. We download the datasets for FGVC benchmark from their respective sources.

Note: Create a ``data`` folder in the root and place the datasets inside this folder.


Pretrained models
=================
Please refer to the download links provided in the paper.


Training
========
For fine-tuning ViT use the following command.

.. code:: bash

export PYTHONPATH=.
python image_classification/vit_cp.py --dataset=<choice_of_dataset> --dim=<rank>


Evaluation
==========
We provide the link for fine-tuned models for each dataset in VTAB-1k benchmark `here <https://uni-bonn.sciebo.de/s/YAtcRDHxdwnBGq7>`_. To reproduce results from the paper, download the model and execute the following command

.. code:: bash

export PYTHONPATH=.
python image_classification/vit_cp.py --dataset=<choice_of_dataset> --dim=<rank> --evaluate=<path_to_model>


Acknowledgments
Expand All @@ -38,4 +88,4 @@ The code is built on the implementation of `FacT <https://github.com/JieShibo/PE
:alt: Project Page
.. |Arxiv| image:: https://img.shields.io/badge/OpenReview-Paper-blue
:target: https://openreview.net/pdf?id=vexHifrbJg
:alt: Paper
:alt: Paper
Loading