head_finetune
birdnet_stm32.training.head_finetune
¶
Fine-tune the classifier head on a frozen backbone, on every training file.
A post-training step: after train, the backbone's pooled embedding of every
training file is computed once (one chunk per file, cut and targeted as the
training loader does: crop policy, teacher targets, label sidecar) and cached on
disk. Then only the classifier (pred) is refitted, starting from its trained
weights: each epoch draws the cached files class-capped (ClassCappedPasses,
with the field table, as training draws), fits sigmoid cross-entropy against the
cached targets, and keeps the epoch with the best validation score (class-mean
AP plus micro AP, one chunk per validation file, hard labels). The backbone, the
frontend and the config are untouched. With the backbone frozen every output is
an independent logistic regression, so an epoch over two million cached files
takes seconds to minutes.
Optional co-occurrence weighting: each output's negatives from species it never
shares a region with count far_weight (regions from a CSV of label,group
rows; labels not listed, such as non-bird outputs, co-occur with everything).
With a range filter at inference those species never compete; the head then
spends its capacity on the confusions that remain, and without a filter it
costs nothing.
Measured on 2.1 Raw (1,013 outputs; INT8; 61 WABAD sites, no species mask): micro window AP +3.3% for the refit alone, +3.9% with co-occurrence weighting 0.3; with each region's species mask, +10% (North America, Europe) and +16% to +19% (Neotropics) over the unrefitted head.
micro_ap(y, s)
¶
Average precision over all (row, output) pairs pooled; NaN without positives.
Source code in birdnet_stm32/training/head_finetune.py
class_mean_ap(y, s)
¶
Mean over outputs with positives of each output's average precision.
Source code in birdnet_stm32/training/head_finetune.py
embedding_model(model)
¶
The model up to the input of pred (the pooled embedding; dropout is inactive at inference).
class_index(file_paths, classes)
¶
Folder class index per file; -1 for noise folders (all-zero negatives).
Source code in birdnet_stm32/training/head_finetune.py
embed_files(model, file_paths, classes, cache_dir, chunk_kwargs, num_workers=8, block=4096, log=print)
¶
Embed one chunk per file into cache_dir (memory-mapped, resumable); returns cache_dir.
Writes files.txt, cls.npy (folder class, -1 noise), emb.npy [files, dim] and y.npy
[files, classes] (float16), ok.npy (0 to do, 1 done, 2 failed to load) and meta.json. A cache
made for other files, classes or chunk settings is refused rather than silently reused.
Source code in birdnet_stm32/training/head_finetune.py
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 | |
load_cooccurrence(path, classes)
¶
[classes, classes] bool from a label,group CSV: True where two labels share a group.
A label may appear in several groups. Labels not in the CSV (e.g. non-bird outputs) co-occur with everything.
Source code in birdnet_stm32/training/head_finetune.py
negative_weights(cooccurrence, far_weight)
¶
Per (sample class, output) weight: 1 where the two co-occur, far_weight elsewhere.
Source code in birdnet_stm32/training/head_finetune.py
fit_head(emb, targets, cls, epoch_rows, val_emb, val_targets, w0, b0, *, learning_rate=0.0003, epochs=30, patience=5, weights=None, seed=42, log=print)
¶
Refit a dense sigmoid head from (w0, b0); returns the best weights by validation and the history.
emb/targets are indexable by row arrays (memory maps work); epoch_rows() returns one epoch's rows;
weights [classes, classes] scales each sample's negatives by its class (rows of class -1, noise, and
every positive > 0.5 keep weight 1).
Source code in birdnet_stm32/training/head_finetune.py
223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 | |
capped_epochs(cache_files, ok, cap, field_kwargs=None, seed=42)
¶
An epoch_rows callable: each call one class-capped pass (ClassCappedPasses) over the cached files.
Source code in birdnet_stm32/training/head_finetune.py
replace_head(model, w, b)
¶
Set pred's weights in place (shapes must match) and return the model.