Constraint-based CNN generator and trainer. Describe what you need — not how to build it.
Project description
coldet
Describe constraints, not networks.
coldet is a minimal Python package for building and training vision models without touching a single line of architecture code. You express what you need — size, speed, accuracy tradeoff — and the system generates a valid CNN for you.
coldet is classification-only. All detection, segmentation, and open-vocabulary tasks have been intentionally removed to keep the surface area small and the output format predictable.
Why constraint-based modelling?
Traditional ML frameworks ask you to design networks: choose a backbone, wire up layers, pick kernel sizes, set strides. This works when you have expertise and time. Most of the time, you just need a model that is fast enough and accurate enough for your problem.
coldet flips the question. Instead of:
"I want ResNet-50 with a 4-layer head…"
You say:
"I want something medium-sized that leans toward speed."
The architecture is derived automatically from those constraints. You never see layer names, channel counts, or backbone identifiers — because they are not your concern.
Benefits:
- No architecture expertise required.
- Constraints are reproducible: same inputs → same model.
- Easier to reason about tradeoffs (
speed_bias=0.9is faster thanspeed_bias=0.3— always).
Installation
pip install coldet
Or from source:
git clone https://github.com/yourorg/coldet
cd coldet
pip install -e .
Dataset formats
coldet supports two dataset layouts. The right one is auto-detected.
1. Flat — subfolder-per-class
Each subfolder is a class. Simple and fast to set up.
dataset/
red/
img001.jpg
img002.png
...
blue/
img001.jpg
...
green/
...
Supported image formats: .jpg, .jpeg, .png, .ppm, .bmp, .tiff, .webp.
2. Hierarchical — parent/sub-class layout
Use this when your classes have natural sub-categories (e.g. "red" → "crimson", "scarlet"). Each parent folder contains one or more sub-class folders.
dataset/
red/
crimson/
img001.jpg
...
scarlet/
img001.jpg
...
blue/
img001.jpg ← images directly in a parent are labelled with the parent name
...
green/
olive/
img001.jpg
...
How labels are assigned:
- Each unique sub-class folder name becomes a label (e.g.
crimson,scarlet,olive). - Images placed directly inside a parent folder (not in any sub-class folder) are assigned a synthetic sub-class label identical to the parent name (e.g.
blue). - The hierarchy
{parent: [sub, ...]}is saved in every.coldetcheckpoint and used at inference time to aggregate parent-level probabilities.
Inference output for a hierarchical model (see coldet.infer):**
predicted_class: crimson
confidence: 61.2%
probabilities: {crimson: 61.2%, scarlet: 13.3%, red: 10.1%, ...}
predicted_parent: red
parent_probabilities: {red: 74.5%, blue: 18.2%, green: 7.3%}
The parent_probabilities are computed by summing all sub-class probabilities that belong to each parent. They always sum to 1.0.
Quickstart
Classification — flat layout
import coldet
trainer = coldet.Trainer(
size="medium", # "nano" | "small" | "medium" | "large"
speed_bias=0.7, # 0 = prefer accuracy, 1 = prefer speed
dataset="dataset/",
batch_size=32,
image_size=224,
)
# [coldet] dataset 'dataset/' — 3 classes discovered: ['blue', 'green', 'red']
trainer.train(epochs=10)
trainer.summary()
trainer.save("checkpoints/run1.coldet")
Classification — hierarchical layout
import coldet
trainer = coldet.Trainer(
size="medium",
speed_bias=0.5,
dataset="hier_dataset/", # contains sub-class subfolders → hierarchical mode
batch_size=16,
image_size=256,
)
# [coldet] hierarchical dataset 'hier_dataset/' — 5 sub-classes across 3 parent classes: ['blue', 'green', 'red']
trainer.train(epochs=20)
trainer.summary()
trainer.save("checkpoints/hier_run.coldet")
Manual DataLoader
import coldet
from torch.utils.data import DataLoader
trainer = coldet.Trainer(size="medium", speed_bias=0.7, num_classes=3)
trainer.train(my_dataloader, epochs=10)
trainer.summary()
Loading a checkpoint
# Load into an existing Trainer (constraints must match)
trainer.load("checkpoints/run1.coldet")
# Reconstruct from scratch — no constructor arguments needed.
# Use this in inference scripts.
trainer = coldet.Trainer.from_checkpoint("checkpoints/run1.coldet")
import torch
images = torch.rand(4, 3, 224, 224)
logits = trainer.predict(images) # shape (4, num_classes)
Inference — coldet.infer
The recommended way to run a trained model on a single image. No Trainer setup needed.
import coldet
result = coldet.infer(
image_path="photo.jpg",
model_path="checkpoints/run1.coldet",
temperature=1.0, # optional, default 1.0
)
print(result["predicted_class"]) # e.g. "crimson"
print(f"{result['confidence']:.1%}") # e.g. "61.2%"
# Full probability breakdown
for cls, prob in result["probabilities"].items():
print(f" {cls}: {prob:.1%}")
# Hierarchical models also include parent-level aggregation
if result["parent_probabilities"]:
print(f"\nParent: {result['predicted_parent']}")
for par, prob in result["parent_probabilities"].items():
print(f" {par}: {prob:.1%}")
Temperature
The temperature parameter scales the logits before the final softmax:
| Value | Effect |
|---|---|
< 1.0 |
Sharper distribution — the top prediction dominates more. Use when you want decisive, high-confidence outputs. |
1.0 (default) |
Standard softmax probabilities. |
> 1.0 |
Flatter distribution — probabilities are more spread out. Use to see how uncertain the model is across all classes. |
Useful range: 0.1 – 5.0.
Return value
| Key | Type | Description |
|---|---|---|
predicted_class |
str | Sub-class with the highest probability |
confidence |
float | Probability of the predicted class (0–1) |
probabilities |
dict[str, float] | All sub-class probabilities, sorted descending |
parent_probabilities |
dict[str, float] or None | Parent-class probabilities (hierarchical models only) |
predicted_parent |
str or None | Parent of the predicted sub-class (hierarchical only) |
temperature |
float | Temperature used |
image_path |
str | Echoed input path |
API Reference
coldet.load_dataset
loader, class_names, hierarchy = coldet.load_dataset(
dataset_path, # root folder
image_size=224,
batch_size=32,
shuffle=True,
num_workers=0,
)
Returns a (DataLoader, list[str], dict or None) tuple.
class_names— sorted list of all leaf (sub-class) labels; index = integer label.hierarchy—{parent: [sub, ...]}for hierarchical datasets,Nonefor flat.
Called internally by Trainer when dataset= is supplied.
coldet.Trainer
Trainer(
size="small", # capacity tier
speed_bias=0.5, # float [0, 1]
accuracy_bias=None, # float [0, 1] — defaults to 1 - speed_bias
dataset=None, # path to dataset (either layout)
image_size=224,
batch_size=32,
num_classes=1000, # ignored when dataset= is supplied
lr=1e-3,
device=None, # auto-detected (CUDA if available)
)
| Method | Description |
|---|---|
train(dataloader=None, epochs=1, verbose=True) |
Train for N epochs. Returns list of epoch losses. Cosine annealing is applied automatically. |
summary(output_dir=".") |
Writes sum.md and graph.png. Returns info dict. |
predict(images) |
Forward pass, eval mode. images is (B, 3, H, W). Returns (B, num_classes) logits. |
save(path) |
Save checkpoint as a .coldet file. |
load(path) |
Restore weights and training state into an already-constructed Trainer. |
Trainer.from_checkpoint(path, device=None) |
Class method. Reconstruct a complete Trainer from a .coldet file — no other arguments needed. |
summary() return value
{
'size_label': 'medium',
'total_params': 214_832,
'trainable_params': 214_832,
'model_size_mb': 0.859,
'speed_tier': 'balanced',
'trained_epochs': 10,
'num_classes': 5,
'class_names': ['blue', 'crimson', 'green', 'red', 'scarlet'],
'hierarchy': {'blue': ['blue'], 'green': ['green'], 'red': ['crimson', 'red', 'scarlet']},
# hierarchy is None for flat datasets
}
summary() output files
| File | Contents |
|---|---|
sum.md |
Constraints, parameter counts, class list (with parent column for hierarchical models), training history. |
graph.png |
Training loss curve. Written only after at least one epoch. |
coldet.infer
result = coldet.infer(
image_path, # str — path to image file
model_path, # str — path to .coldet file
temperature=1.0, # float > 0
device=None, # str or None
)
See the Inference section above for full documentation.
coldet.build_model
Lower-level function for the raw nn.Module:
model = coldet.build_model(
size="large",
speed_bias=0.3,
accuracy_bias=0.8,
num_classes=10,
)
Returns a torch.nn.Module. Architecture is generated, not predefined.
The .coldet file format
.coldet files are PyTorch checkpoints (readable with torch.load). They contain:
- Model weights and optimiser state.
- All constraint parameters (
size,speed_bias,accuracy_bias,lr,image_size). - The resolved architecture dict (so the model can be reconstructed exactly, even if the constraint-to-arch mapping ever changes).
- Class names and the hierarchy dict (if applicable).
- Full training loss history.
The extension .coldet is conventional. You can use any extension — torch.save / torch.load don't care.
Constraint guide
| Goal | Recommended settings |
|---|---|
| Edge / mobile deployment | size="small", speed_bias=0.9 |
| Balanced production model | size="medium", speed_bias=0.5 |
| Maximum accuracy, offline | size="large", speed_bias=0.1, accuracy_bias=0.9 |
| Rapid prototyping | size="small", speed_bias=0.7 |
| Hierarchical fine-grained recognition | size="medium", speed_bias=0.4 |
What is hidden (intentionally)
coldet deliberately does not expose:
- Layer names, channel counts, or kernel sizes.
- Backbone / neck / head terminology.
- Depthwise vs standard convolution choices.
- Dropout values or batch norm parameters.
These are implementation details derived from your constraints. Exposing them would reintroduce the complexity the package is designed to remove.
Philosophy
Describe constraints, not networks.
Good abstractions hide decisions that don't belong to the user. Network architecture is an implementation concern — it should be derived from requirements, not specified by them. coldet treats the model as an output of a constraint-solving process, not an input from the user.
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file coldet_trainer-0.1.2.tar.gz.
File metadata
- Download URL: coldet_trainer-0.1.2.tar.gz
- Upload date:
- Size: 19.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5b1bac2f89364193a2942b42d825c076f882eb4dd3662d9bf2bdc57abf2e3b95
|
|
| MD5 |
e606627281e15718fa252c29818501af
|
|
| BLAKE2b-256 |
aedf34d0a31b6d42ba4417e6723a36cf300f888760b087e5cd71af9ac6486b9f
|
File details
Details for the file coldet_trainer-0.1.2-py3-none-any.whl.
File metadata
- Download URL: coldet_trainer-0.1.2-py3-none-any.whl
- Upload date:
- Size: 16.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c5001c6d8c88d96459fe3253a5abcd73407df20740ada783c27f0eaf64c10dc0
|
|
| MD5 |
2e92cbaa885123fea3f39237b3ce322a
|
|
| BLAKE2b-256 |
f2af3f54dbf7f2fc4158286411788f2b1ceeaae3975c9586794be7af5f557aac
|