[ok] ccaim_card :: cloud classification ai model :: v0.0.6
serbekun @ ccaim ~/src $ cat ccaim.py
ccaim.py
"""CCAiM — cloud classification (WMO International Cloud Atlas, 10 classes)"""
import torch.nn as nn
​
class CCAiMModel(nn.Module):
"""compact CNN trained from scratch — the project baseline line"""
​
def __init__(self, num_classes: int = 10, width_mult: int = 1):
super().__init__()
base_channels = [64, 128, 256, 512, 512] # 9,907,530 params
self.stem = ConvBlock(3, base_channels[0])
self.classifier = nn.Linear(1024, num_classes)
self._init_weights() # kaiming_normal_ (fan_out)
serbekun @ ccaim ~/src $ python3 train.py
train.log
[INFO] using device: cuda
[INFO] gpu : NVIDIA Quadro P2200 — 5 GB GDDR5X, Pascal (sm_61)
[INFO] env : python 3.14, torch 2.14 (cu126), cuda 12.6
[INFO] data : serbekun/CCAiM-CloudsDataset — 10 classes
[INFO] cfg : 224x224, batch 16, epochs 100, lr 1e-5, seed 42
[INFO] lines : scratch (CCAiMModel) + resnet18 (ImageNet head start)
val accuracy 50.34% | macro-F1 0.390 — best model so far (resnet18, V0.0.6)
serbekun @ ccaim ~/src $ cat results.txt
resnet18 · V0.0.6 50.34%
macro-F1 0.390 // transfer learning — practical line
resnet18 · V0.0.5 42.95%
macro-F1 0.314
scratch · V0.0.6 35.57%
macro-F1 0.237 // from scratch — the honest baseline
scratch · V0.0.5 27.52%
macro-F1 0.123
validation accuracy on a fixed seed-42 split // 10 cloud classes, ground-level photos
resnet18 starts from ImageNet weights — a one-time head start, not progress. the scratch line is what measures the dataset growing.
serbekun @ ccaim ~/src $ cat dataset.txt
Cumulus (Cu)398 · 43.45%
Cirrus (Ci)102 · 11.14%
Altocumulus (Ac)96 · 10.48%
Stratocumulus (Sc)94 · 10.26%
Altostratus (As)63 · 6.88%
Cirrostratus (Cs)42 · 4.59%
Stratus (St)38 · 4.15%
Cirrocumulus (Cc)33 · 3.60%
Cumulonimbus (Cb)33 · 3.60%
Nimbostratus (Ns)17 · 1.86%
916 ground-level cloud photographs, MIT, all photos licensed CC0 1.0. classes are heavily unbalanced — that is why the loss is class-weighted and macro-F1 is reported next to accuracy.
serbekun @ ccaim ~/src $ cat hardware.txt
host home server, Arch Linux — not a rented box
gpu NVIDIA Quadro P2200 — 5120 MiB GDDR5X, Pascal (sm_61), 1280 CUDA cores, ~3.8 TFLOPS FP32, 75 W cap, driver 580.178.04, no tensor cores
cpu Intel Core i7-7700K — 4 cores / 8 threads @ 4.2 (4.5) GHz, 8 MB cache, 91 W
ram 16 GiB
storage 256 GB NVMe (Samsung) + 2 x 1 TB HDD (Toshiba)
runtime Python 3.14 // PyTorch 2.14 (cu126) // CUDA 12.6 — torch.cuda.is_available() = True
one machine, one consumer GPU from 2019, all of it at home: dataset download, training, validation metrics, inference. no Colab, no rented A100, no cloud bill.
on Pascal sm_61 the speed is honest, just slow — so the model stays small and the epochs few enough to finish overnight.
training has moved off the desktop onto node3, the box that owns the GPU. the V0.0.5 / V0.0.6 metrics above were set before that move.
serbekun @ ccaim ~/src $ cat links.txt
00 GitHub code: train, evaluate, predict → 01 Hugging Face model card, weights, metrics → 02 CloudsDataset 916 photos, 10 classes, MIT → 03 HF Collection model + datasets in one place →