Getting Started
Get Vyntri up and running in under 5 minutes.
Get Vyntri up and running in under 5 minutes.
Installation
pip install vyntriThis installs Vyntri and all required dependencies (PyTorch ≥ 2.0, torchvision ≥ 0.15, NumPy ≥ 1.24, Pillow ≥ 10.0). Requires Python ≥ 3.9.
Requirements
- Python 3.9 or higher
- No GPU required — works on CPU by default
- ~500 MB disk for PyTorch + backbone weights (downloaded on first use)
- Tested on Windows, macOS, Linux, and Raspberry Pi OS
Prepare Your Dataset
Organize your images into folders where each folder name is the class label:
my_dataset/
├── cat/
│ ├── photo1.jpg
│ ├── photo2.jpg
│ └── ...
├── dog/
│ ├── photo1.jpg
│ └── ...
└── bird/
└── ...Vyntri supports JPG, JPEG, PNG, BMP, TIFF, and WebP image formats.
Split Your Data
Before fitting, explicitly split your dataset into train, validation, and test sets:
from vyntri.data import split
# Split into train (70%), test (20%), validation is computed as 10%
s = split("./my_dataset", train=0.7, test=0.2, seed=42)
print(f"Train: {s.counts['train']} images")
print(f"Val: {s.counts['val']} images")
print(f"Test: {s.counts['test']} images")The split is deterministic — same seed always produces the same partition. The split manifest is stored for reproducibility.
Why split? Vyntri does not automatically create a validation split. Using split() gives you full control over your train/val/test roles.
Fit Your First Model
Option A: Default Config
from vyntri import Vyntri
from vyntri.data import split
# Split your dataset
s = split("./my_dataset", train=0.7, test=0.2, seed=42)
# Initialize with default config (CPU, MobileNetV3, FK adaptation)
model = Vyntri()
# Fit: pass train and val explicitly
model.fit(train=s.train, val=s.val)
# View training summary
model.summary()
# Save the trained model
model.save("my_model.vyntri")Option B: Training Only (No Validation)
If you don't need validation (e.g. you have a separate test set and want all training data used):
from vyntri import Vyntri
# All images in this folder become training data
model = Vyntri()
model.fit("./my_dataset")
# All images are used for fitting — no automatic split
model.summary()Option C: Auto Backbone Selection
from vyntri import Vyntri
from vyntri.data import split
s = split("./my_dataset", train=0.7, test=0.2, seed=42)
# Auto-select the best backbone for your dataset
model = Vyntri(backbone="auto")
model.fit(train=s.train, val=s.val)
# Selection results are logged and stored
print(model.summary())Note: backbone="auto" requires a validation dataset. Pass val=... to fit(), or use vyntri.data.split() to create one.
Option D: Auto with Candidate Control
Limit which backbones are evaluated during auto-selection. Excluded backbones are never initialized or evaluated.
from vyntri import Vyntri
from vyntri.data import split
s = split("./my_dataset", train=0.7, test=0.2, seed=42)
# Only evaluate two fast backbones
model = Vyntri(
backbone="auto",
candidates=["mobilenet_v3_small", "resnet18"],
)
model.fit(train=s.train, val=s.val)
# View which backbone was selected
sel = model.metadata_["selection"]
print(f"Selected: {sel['selected']}")Supported Backbones
| Backbone | Features | Speed | Notes |
|---|---|---|---|
mobilenet_v3_small | 576 | ⚡ Fast | Default. Great for edge devices. |
resnet18 | 512 | Fast | Good balance of speed and accuracy. |
resnet50 | 2048 | Moderate | Higher capacity. |
efficientnet_b0 | 1280 | Fast | Efficient architecture. |
convnext_tiny | 768 | Fast | ConvNeXt architecture. |
auto | — | Varies | Selects the best for your data. |
Evaluate
from vyntri import Vyntri
from vyntri.data import split
s = split("./my_dataset", train=0.7, test=0.2, seed=42)
model = Vyntri()
model.fit(train=s.train, val=s.val)
# Evaluate on the test set
result = model.evaluate(s.test)
print(f"Accuracy: {result.accuracy:.1%}")
print(f"Macro F1: {result.macro_f1:.3f}")Make Predictions
from vyntri import Vyntri
# Load trained model
model = Vyntri.load("my_model.vyntri")
# Predict single image
prediction = model.predict("test_photo.jpg")
print(f"Predicted class: {prediction.label}")
print(f"Confidence: {prediction.confidence}")
# Batch predictions
result = model.predict_batch("./images")
print(result.labels) # list of predicted labelsAdd New Data (Continual Learning)
Vyntri supports incremental updates — add new images or even new classes without retraining from scratch:
from vyntri import Vyntri
model = Vyntri.load("my_model.vyntri")
# Update with new data (adds new classes automatically)
result = model.update("./new_data")
print(f"New classes: {result.new_classes}")
# Save updated model
model.save("my_model.vyntri")The update() method maintains sufficient statistics and re-solves — sequential matches joint.
Inspect Your Model
After fitting, you can inspect what the model learned:
from vyntri import Vyntri
from vyntri.data import split
s = split("./my_dataset", train=0.7, test=0.2, seed=42)
model = Vyntri()
model.fit(train=s.train, val=s.val)
# What classes does the model know?
print(model.classes_) # ['cats', 'dogs', 'birds']
print(model.class_to_idx_) # {'cats': 0, 'dogs': 1, 'birds': 2}
# Model details
print(model.feature_dim_) # 576 (backbone feature dimension)
print(model.validation_accuracy_) # 0.92 (None if no validation set)
print(model.state) # 'fitted'
# Full summary
print(model.summary())Next Steps
- Explore solvers — Compare adaptation and shrinkage options in the Solvers Guide
- Full API — See all classes and methods in the API Reference
- Fine-tuning — Optional gradient fine-tuning for higher accuracy (see API Reference)