split
birdnet_stm32.conversion.split
¶
Split a trained model into a fixed backbone and a swappable classifier head.
The backbone maps audio to an embedding vector and is flashed once. The head maps that embedding to per-class probabilities and is the only part that has to change when the species list changes, so it is the part that travels over a narrowband satellite link. Keeping it a separate artifact means an update costs kilobytes instead of the whole model.
The split point is the pooling layer that produces the embedding vector. In a
DS-CNN everything after it is a short chain (dropout, then the classifier
Dense), which is rebuilt onto a clean embeddings input so the head is a
standalone model with its own weights.
find_embedding_layer(model)
¶
Return the layer whose output is the model's embedding vector.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
Model
|
Functional classifier model. |
required |
Returns:
| Type | Description |
|---|---|
Layer
|
The last pooling layer in the graph. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If no pooling layer is present. |
Source code in birdnet_stm32/conversion/split.py
split_model(model)
¶
Split model into a backbone and an independent classifier head.
The backbone shares layers with model; the head is rebuilt from cloned layers so neither model mutates the source graph.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
Model
|
Trained functional classifier. |
required |
Returns:
| Type | Description |
|---|---|
Model
|
Tuple of |
Model
|
to the embedding vector; the classifier maps an |
tuple[Model, Model]
|
the class probabilities. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If the model has no embedding layer or a branched head. |
Source code in birdnet_stm32/conversion/split.py
embedding_dimension(backbone)
¶
backbone_fingerprint(backbone)
¶
Return a SHA-256 over a backbone's float weights in graph order.
A head shipped over the air only works if the receiver's flashed backbone is the one the head was calibrated against. Comparing this fingerprint is how a later head-only conversion proves the backbone did not move: weight values are hashed together with each tensor's name and shape, so a reordered or resized graph cannot collide with the original.
Source code in birdnet_stm32/conversion/split.py
file_sha256(path)
¶
Return the SHA-256 digest of a file's exact bytes.
Source code in birdnet_stm32/conversion/split.py
write_fingerprint(backbone_path, fingerprint, embedding_dim)
¶
Record a backbone's fingerprint beside the artifact it identifies.
Source code in birdnet_stm32/conversion/split.py
read_fingerprint(backbone_path)
¶
Return the recorded fingerprint for a backbone, or None if absent.
Source code in birdnet_stm32/conversion/split.py
count_parameters(model)
¶
gzip_file(source_path, output_path='')
¶
Write a deterministic maximum-compression gzip copy of a file.
The timestamp is zeroed and the source name is left out of the header, so repeated compressions of identical bytes produce identical archives and an over-the-air update stays diffable.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
source_path
|
str
|
File to compress. |
required |
output_path
|
str
|
Destination; defaults to |
''
|
Returns:
| Type | Description |
|---|---|
str
|
The path written. |
Source code in birdnet_stm32/conversion/split.py
weight_sparsity(model_path, min_tensor_size=256)
¶
Measure the fraction of zero INT8 weights inside a TFLite model.
A sparse head compresses well precisely because these bytes are zero, so the split report records the number the compression ratio follows from.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model_path
|
str
|
Path to a .tflite model. |
required |
min_tensor_size
|
int
|
Ignore tensors smaller than this (biases, shapes). |
256
|
Returns:
| Type | Description |
|---|---|
dict[str, float | int]
|
Dict with the counted weights, the zeros among them, and their ratio. |
Source code in birdnet_stm32/conversion/split.py
size_record(model_path)
¶
Return raw and gzipped sizes plus INT8 sparsity for a TFLite artifact.