Skip to content

Inference artifact saving#453

Open
addobosz wants to merge 19 commits into
mainfrom
inference-artifact-saving
Open

Inference artifact saving#453
addobosz wants to merge 19 commits into
mainfrom
inference-artifact-saving

Conversation

@addobosz

@addobosz addobosz commented Apr 8, 2026

Copy link
Copy Markdown
Contributor

This pull request introduces several improvements and new features across the codebase, focusing on data augmentation, configuration flexibility, training/inference workflow, and code robustness. The most significant changes include adding configurable data augmentation, improving model checkpointing and artifact logging, and refactoring accuracy tracking and model freezing logic.

Data pipeline and augmentation improvements:

  • Added a configurable data augmentation section to src/config.yaml, enabling options such as random flips, rotation, brightness, contrast, saturation, and hue adjustments. The augmentation pipeline is implemented in get_train_transform() in src/dataset.py and applied during training dataset setup. [1] [2] [3]
  • Added ONNX as a dependency in pyproject.toml to support ONNX model export during inference.

Training and inference workflow enhancements:

  • Introduced an inference section in src/config.yaml to control mask size, ONNX export, checkpoint paths, artifact tracking, and device selection. Device handling in dataloader parameters is now more robust to "cuda"/"gpu" string variants. [1] [2]
  • Added a new SegmentationWrapper module for wrapping classifiers to produce segmentation-style outputs, supporting normalization and optional input rescaling.

Model and metrics tracking improvements:

  • Refactored accuracy tracking in src/models/classifier_module.py to maintain separate accuracy metrics for training, validation, and test phases, and improved logging granularity. [1] [2]
  • Updated the fine-grained model to support freezing the feature extractor backbone based on config, and fixed the forward pass to respect training/eval mode. [1] [2] [3]

Experiment tracking and artifact logging:

  • Enhanced experiment reproducibility and tracking by saving the label map alongside the best checkpoint, logging model artifacts to Weights & Biases (wandb), and improving run metadata handling. [1] [2] [3]
  • Improved dataset split reporting with a new summary function to check class distribution and missing classes in each split. [1] [2]

Miscellaneous:

  • Adjusted default batch size in config to 1 for training, likely for debugging or memory constraints.
  • Improved ModelCheckpoint/EarlyStopping handling for more flexible monitoring and mode selection.

These changes collectively improve the flexibility, robustness, and traceability of the training and inference pipeline.

@github-actions

github-actions Bot commented Apr 8, 2026

Copy link
Copy Markdown

Dependency Review

The following issues were found:
  • ❌ 2 vulnerable package(s)
  • ✅ 0 package(s) with incompatible licenses
  • ✅ 0 package(s) with invalid SPDX license definitions
  • ✅ 0 package(s) with unknown licenses.
See the Details below.

Snapshot Warnings

⚠️: No snapshots were found for the head SHA 3c494f0.
Ensure that dependencies are being submitted on PR branches and consider enabling retry-on-snapshot-warnings. See the documentation for more information and troubleshooting advice.

Vulnerabilities

uv.lock

NameVersionVulnerabilitySeverity
onnx1.20.0ONNX Untrusted Model Repository Warnings Suppressed by silent=True in onnx.hub.load() — Silent Supply-Chain Attackhigh
onnx Vulnerable to Path Traversal via Symlinkhigh
ONNX: Malicious ONNX models can crash servers by exploiting unprotected object settings.high
ONNX: TOCTOU arbitrary file read/write in save_external_dat high
ONNX: Arbitrary File Read via ExternalData Hardlink Bypass in ONNX loadmoderate
ONNX: External Data Symlink Traversalmoderate
filelock3.20.1filelock Time-of-Check-Time-of-Use (TOCTOU) Symlink Vulnerability in SoftFileLockmoderate

OpenSSF Scorecard

PackageVersionScoreDetails
pip/onnx 1.20.0 UnknownUnknown
pip/filelock 3.20.1 UnknownUnknown
pip/ml-dtypes 0.5.4 UnknownUnknown

Scanned Files

  • uv.lock

@rojberr rojberr requested a review from Copilot April 9, 2026 10:40

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds end-to-end inference artifact saving and ONNX export support by logging the best checkpoint (plus label map) to W&B, introducing a segmentation-style wrapper for classifiers, and adding a standalone inference script.

Changes:

  • Added SegmentationWrapper to convert classifier logits into a dense per-pixel mask for ONNX/segmentation-like outputs.
  • Updated training flow to select/log the best checkpoint as a W&B artifact and persist a .label_map.json next to it.
  • Added an inference entrypoint with optional W&B artifact download + ONNX export, plus configurable train-time augmentation.

Reviewed changes

Copilot reviewed 9 out of 588 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
src/models/segmentation_wrapper.py New wrapper module that normalizes inputs and expands class probabilities into a (B, C, H, W) mask.
src/models/model_factory.py Passes freeze through to FineGrainedModel.
src/models/diversified_model.py Stabilizes top-k selection and pooling behavior; adds optional freezing of backbone.
src/models/classifier_module.py Splits accuracy metrics by stage and aligns fine-grained training behavior with self.training.
src/main.py Logs best checkpoint + label map as explicit W&B artifact; makes checkpoint monitor configurable; prints split summary.
src/inference.py New inference script: load checkpoint (local or W&B artifact), run inference, optionally export/upload ONNX.
src/dataset.py Adds configurable train augmentation pipeline and improves pin_memory device detection.
src/config.yaml Adds inference config and augmentation config; changes defaults (e.g., batch size, device).
pyproject.toml Adds onnx dependency required for export/metadata writing.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/main.py
Comment on lines +28 to +36
def _wandb_safe_metadata_value(value):
if isinstance(value, float) and not math.isfinite(value):
return None
if isinstance(value, torch.Tensor):
if value.numel() == 1:
scalar = value.item()
return None if isinstance(scalar, float) and not math.isfinite(scalar) else scalar
return value.tolist()
return value

Copilot AI Apr 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

math.isfinite is used but math is not imported in the shown imports at the top of main.py, which will raise NameError at runtime. Add import math near the top of the file (or replace math.isfinite with an equivalent already-imported utility).

Copilot uses AI. Check for mistakes.
Comment thread src/config.yaml

training:
batch_size: 32
batch_size: 1

Copilot AI Apr 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The committed defaults make the repo configuration brittle/non-portable: (1) raw_images_path is an absolute, user-specific filesystem path; (2) wandb_artifact points to a specific run artifact; (3) export_onnx: true enables export by default; and (4) training.batch_size changed from 32 to 1. Recommend reverting these to safe, portable defaults (e.g., comment out run-specific values, use relative example paths, set export_onnx: false by default, and restore a reasonable default batch_size).

Copilot uses AI. Check for mistakes.
Comment thread src/config.yaml
Comment on lines +87 to +101
inference:
mask_size: 224
export_onnx: true
checkpoint_path: "checkpoints/model.ckpt"
# wandb_artifact: "ghost-irim/ghost-irim/model-kx2co2o3:v0"
wandb_artifact: "ghost-irim/ghost-irim/best-model-inference-artifact-saving-vft1nd:v0"
wandb_project: "ghost-irim"
# Set to true to run inference on raw images (ONNX-style testing)
# Set to false to run inference on test dataset split
use_raw_images: false
# Path to directory containing raw images (relative to project root)
# raw_images_path: "test_images_qgis/10122025_193353"
# raw_images_path: "/home/adam/Documents/programming/tree-classification-irim/src/data/Abies_alba/train"
raw_images_path: "/home/adam/Documents/programming/tree-classification-irim/src/data/Robinia_pseudoacacia/train"
device: "cuda"

Copilot AI Apr 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The committed defaults make the repo configuration brittle/non-portable: (1) raw_images_path is an absolute, user-specific filesystem path; (2) wandb_artifact points to a specific run artifact; (3) export_onnx: true enables export by default; and (4) training.batch_size changed from 32 to 1. Recommend reverting these to safe, portable defaults (e.g., comment out run-specific values, use relative example paths, set export_onnx: false by default, and restore a reasonable default batch_size).

Copilot uses AI. Check for mistakes.
Comment thread src/inference.py
Comment on lines +97 to +101
run = wandb.init(project=project_name, job_type="inference")

artifact = run.use_artifact(artifact_path, type="model")
artifact_dir = artifact.download()

Copilot AI Apr 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

download_checkpoint_from_wandb() creates and finishes a W&B run immediately. As a result, later sections guarded by if wandb.run is not None: (ONNX artifact upload and metric logging) will never execute in the common 'download-from-artifact' path. Consider either (a) keeping the run open and finishing at the end of main(), or (b) moving W&B initialization to main() (optionally behind a config flag like inference.log_to_wandb), and having download_checkpoint_from_wandb() reuse the active run.

Copilot uses AI. Check for mistakes.
Comment thread src/inference.py
Comment on lines +111 to +113
run.finish()

return checkpoint_path

Copilot AI Apr 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

download_checkpoint_from_wandb() creates and finishes a W&B run immediately. As a result, later sections guarded by if wandb.run is not None: (ONNX artifact upload and metric logging) will never execute in the common 'download-from-artifact' path. Consider either (a) keeping the run open and finishing at the end of main(), or (b) moving W&B initialization to main() (optionally behind a config flag like inference.log_to_wandb), and having download_checkpoint_from_wandb() reuse the active run.

Copilot uses AI. Check for mistakes.

def __init__(self, classifier: nn.Module, mask_size: int = 224, mean=None, std=None, input_rescale=False):
super().__init__()
self.classifier = classifier.eval()

Copilot AI Apr 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Calling .eval() on the passed-in classifier mutates external state as a side effect of constructing SegmentationWrapper. This can be surprising if the caller expects to control train/eval mode (or reuses the classifier elsewhere). Prefer storing self.classifier = classifier and letting the caller set .eval() (as is already done in inference.py), or documenting clearly that the wrapper forces eval mode.

Copilot uses AI. Check for mistakes.
Comment thread src/inference.py
import wandb
from omegaconf import OmegaConf
from tqdm import tqdm
from torchvision.utils import save_image

Copilot AI Apr 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

save_image is imported but never used anywhere in this file. Removing it avoids dead imports and reduces lint noise.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants