Back to archive
#ai#deep-learning#forensics#computer-vision

Zastosowanie Deep Learning w Identyfikacji Narzędzi na Podstawie Śladów Narzędziowych

Zastosowanie Deep Learning w Wspomaganiu Porównywania Śladów Narzędziowych

Rozwój metod deep learning i uczenia metryk podobieństwa umożliwia budowę systemów wspierających ekspertów kryminalistyki w analizie śladów narzędziowych, takich jak ślady striacyjne, odciski narzędzi, zadrapania, ślady cięcia oraz mikrostruktury powierzchni. Celem takiego systemu nie powinno być automatyczne „wydanie werdyktu”, lecz wspomaganie porównywania śladów poprzez generowanie rankingu potencjalnych dopasowań, obliczanie miary podobieństwa oraz wskazywanie przypadków wymagających dalszej oceny eksperckiej.

W praktyce system deep learning może pełnić trzy funkcje:

  1. Retrieval, czyli wyszukiwanie najbardziej podobnych śladów w bazie.

  2. Verification, czyli porównanie pary śladów i wygenerowanie score'u podobieństwa.

  3. Decision support, czyli wsparcie eksperta przez ranking, wizualizacje, metryki niepewności i raport techniczny.

W kryminalistyce szczególnie ważne jest, aby wynik modelu był interpretowany ostrożnie. Współczesne podejście do toolmarków przesuwa się od subiektywnych ocen typu match/no-match w stronę obiektywnych metryk, 3D topografii powierzchni, statystycznego opisu siły dowodu i oszacowania niepewności.

Spis treści


1. Założenia i ograniczenia systemu

System opisywany w tym artykule nie jest samodzielnym narzędziem do ostatecznej identyfikacji narzędzia. Jest to system wspomagający, który może pomóc ekspertowi szybciej znaleźć potencjalnie podobne ślady, porównać pary śladów oraz uporządkować wyniki według miary podobieństwa.

Bezpieczniejsza teza brzmi więc:

System deep learning może generować embeddingi, ranking kandydatów oraz score podobieństwa dla śladów narzędziowych. Wynik powinien być traktowany jako wsparcie dla eksperta i interpretowany wyłącznie w granicach zwalidowanego zakresu zastosowania.

Jest to ważne, ponieważ w analizie toolmarków wnioski źródłowe są zwykle przedstawiane jako opinie eksperckie, a nie jako absolutne, nieomylne stwierdzenia. Standardy i dobre praktyki w obszarze forensic science wymagają ostrożnego formułowania wniosków, znajomości ograniczeń metody, raportowania poziomów błędów oraz wskazywania, w jakim zakresie dana metoda została zwalidowana.


2. Charakter śladów narzędziowych

Ślady narzędziowe mogą powstawać, gdy twarde narzędzie oddziałuje na miększy materiał. W zależności od typu kontaktu mogą to być:

  • ślady striacyjne, czyli układy równoległych rowków, linii i zadrapań;
  • ślady wgłębione, czyli odciski powierzchni roboczej narzędzia;
  • ślady cięcia, nacisku, zarysowania lub podważania;
  • mikrotopografia powierzchni widoczna dopiero w wysokiej rozdzielczości.

W analizie kryminalistycznej istotne są nie tylko cechy widoczne wizualnie, ale również sposób ich powstania: kąt przyłożenia narzędzia, nacisk, materiał podłoża, stan zużycia narzędzia, uszkodzenia powierzchni roboczej oraz zmienność między kolejnymi śladami wykonanymi tym samym narzędziem.

Dlatego system oparty o deep learning powinien być projektowany nie tylko jako klasyfikator obrazów, ale jako narzędzie do porównywania śladów powstałych w określonych warunkach fizycznych i pomiarowych.


3. Przygotowanie danych

3.1. Obrazowanie

Pierwszym etapem jest pozyskanie danych o odpowiedniej jakości. W zależności od dostępnego sprzętu i typu śladu można wykorzystać:

  • klasyczne zdjęcia 2D w wysokiej rozdzielczości;
  • mikroskopię optyczną;
  • mikroskopię konfokalną;
  • focus variation microscopy;
  • structured light scanning;
  • mapy wysokości 3D;
  • profile 1D/2D wyodrębnione z powierzchni 3D.

Ważne jest, aby jasno określić, czym jest wejście modelu. Inaczej projektuje się model dla zwykłego obrazu grayscale, inaczej dla mapy wysokości 3D, a jeszcze inaczej dla zestawu profili striacyjnych.

Przykładowe formaty wejściowe:


2D grayscale image: 128 × 128 × 1

2D RGB image: 224 × 224 × 3

Height map / depth map: 256 × 256 × 1

Multi-channel surface: 256 × 256 × C

1D profile: N punktów wysokości

W praktycznych systemach forensycznych szczególnie wartościowe są dane 3D, ponieważ pozwalają analizować topografię powierzchni, a nie tylko oświetlenie, kontrast i teksturę zdjęcia 2D.

3.2. Wyodrębnienie ROI

odel powinien analizować przede wszystkim obszar śladu, a nie tło. Dlatego należy wyodrębnić ROI, czyli region zainteresowania.

Przykładowe kroki:

  • detekcja obszaru śladu;

  • usunięcie fragmentów tła;

  • maskowanie uszkodzeń i artefaktów;

  • wyrównanie orientacji śladu;

  • standaryzacja skali i rozdzielczości.

Dla śladów striacyjnych często warto wyrównać główny kierunek striacji, aby model nie musiał uczyć się dużych, nieistotnych różnic orientacji. Trzeba jednak uważać, aby preprocessing nie usuwał informacji istotnej dla eksperta.

3.3. Normalizacja i preprocessing

W zależności od typu danych można stosować:

  • normalizację jasności lub wysokości;
  • wyrównanie histogramu;
  • filtrację medianową;
  • wygładzanie;
  • usuwanie trendu powierzchni;
  • leveling mapy wysokości;
  • normalizację rozdzielczości;
  • standaryzację wartości pikseli lub wysokości.

Dla danych 3D ważne jest, aby preprocessing był powtarzalny i udokumentowany. Zmiana parametrów filtrowania może zmienić wynik porównania, więc każda wersja pipeline'u powinna być zapisana razem z modelem.

3.4. Metadane

Każdy obraz lub pomiar powinien mieć metadane. Bez nich walidacja systemu jest bardzo trudna.

Minimalny zestaw metadanych:


tool_id

tool_type

tool_model_or_class

working_surface_id

substrate_material

mark_generation_angle

mark_generation_pressure

operator_id

lab_id

scanner_or_microscope_id

resolution

calibration_status

date_of_acquisition

preprocessing_version

case_or_experiment_id

Metadane są kluczowe przy wykrywaniu data leakage, budowaniu zbiorów walidacyjnych i ocenie, czy model nauczył się cech narzędzia, czy przypadkowo cech konkretnego laboratorium, skanera lub sesji pomiarowej.


4. Wymagania dotyczące zbioru danych

4.1. Liczba obrazów to nie wszystko

W deep learning często mówi się, że modele potrzebują dużych zbiorów danych. W analizie śladów narzędziowych ważniejsza od samej liczby obrazów jest liczba niezależnych źródeł zmienności.

Dużo cropów z jednego śladu nie zastępuje wielu niezależnych śladów. Sto fragmentów wyciętych z tej samej próbki może dawać złudzenie dużego zbioru, ale statystycznie jest to nadal bardzo ograniczona liczba niezależnych obserwacji.

Zbiór powinien obejmować:

  • wiele egzemplarzy narzędzi;

  • różne narzędzia tego samego typu;

  • narzędzia tego samego producenta i modelu;

  • narzędzia produkowane seryjnie blisko siebie;

  • różne powierzchnie robocze tego samego narzędzia;

  • różne kąty przyłożenia;

  • różny nacisk;

  • różne materiały podłoża;

  • różny stopień zużycia;

  • różne sesje pomiarowe;

  • różne urządzenia pomiarowe;

  • różne laboratoria, jeżeli system ma działać międzyinstytucjonalnie.

4.2. Unikanie data leakage

Największym zagrożeniem jest data leakage. Może wystąpić, gdy fragmenty tego samego fizycznego śladu trafią jednocześnie do treningu i testu.

Niebezpieczne przypadki:

  • cropy z jednego śladu w train i test;
  • obrazy z tej samej sesji skanowania w train i test;
  • testowe ślady wykonane tym samym operatorem i w tych samych warunkach co treningowe;
  • zbyt łatwe pary negatywne;
  • podział losowy po obrazach zamiast po narzędziach, próbkach lub sesjach.

W zależności od celu systemu należy stosować różne typy podziału:


Split po obrazach:

zwykle zbyt optymistyczny, ryzyko data leakage.

  

Split po śladach:

lepszy, ale nadal może przeceniać skuteczność, jeśli ślady pochodzą z tej samej sesji.

  

Split po sesjach:

testuje odporność na zmienność akwizycji.

  

Split po narzędziach:

testuje generalizację na nowe narzędzia.

  

Split po laboratoriach:

testuje odtwarzalność między środowiskami pomiarowymi.

Przykładowy podział z użyciem grup:


from sklearn.model_selection import GroupShuffleSplit

  

# images: tablica obrazów

# labels: etykiety narzędzi lub klas

# groups: identyfikator fizycznego narzędzia, próbki, sesji albo sprawy

# Dobór groups zależy od tego, jaki scenariusz walidujemy.

  

splitter = GroupShuffleSplit(

n_splits=1,

test_size=0.2,

random_state=42

)

train_idx, test_idx = next(splitter.split(images, labels, groups=groups))
  

X_train, X_test = images[train_idx], images[test_idx]

y_train, y_test = labels[train_idx], labels[test_idx]

4.3. Hard negatives

Pary negatywne nie powinny być losowane wyłącznie z całkowicie różnych narzędzi. To zbyt proste zadanie. Model może wtedy nauczyć się odróżniać typ narzędzia, a nie indywidualne cechy konkretnego egzemplarza.

Przykłady trudnych negatywów:

  • dwa narzędzia tego samego typu;
  • ten sam producent i model;
  • narzędzia produkowane seryjnie blisko siebie;
  • podobny stopień zużycia;
  • podobny materiał podłoża;
  • podobny kąt i nacisk;
  • podobna sesja pomiarowa;
  • różne powierzchnie robocze tego samego narzędzia, jeżeli w danym standardzie są traktowane jako różne źródła.

To jest szczególnie ważne, ponieważ cechy klasowe i podklasowe mogą być wspólne dla większej grupy narzędzi. Model, który opiera się głównie na takich cechach, może dawać fałszywe poczucie trafności.

4.4. Augmentacja danych

Augmentacja może pomóc, ale musi być fizycznie uzasadniona.

Rozsądne augmentacje:

  • niewielkie rotacje;
  • przesunięcia;
  • lekkie skalowanie;
  • zmiany jasności i kontrastu dla obrazów 2D;
  • dodanie realistycznego szumu pomiarowego;
  • losowe cropy w obrębie ROI;
  • maskowanie drobnych artefaktów.

Ryzykowne augmentacje:

  • silne deformacje elastyczne;
  • nienaturalne rozciąganie striacji;
  • agresywne filtry zmieniające mikrostrukturę;
  • generowanie śladów syntetycznych bez walidacji fizycznej;
  • mieszanie danych z różnych typów skanerów bez kontroli domeny.

Dane syntetyczne, np. generowane przez GAN-y lub symulacje fizyczne, mogą być przydatne do pretrainingu lub eksperymentów, ale nie powinny zastępować rzeczywistej walidacji na danych empirycznych.


5. Wybór modelu

5.1. CNN

Sieci konwolucyjne są naturalnym wyborem dla obrazów 2D, map wysokości i lokalnych wzorców tekstury. Mogą uczyć się krawędzi, rowków, mikrostruktury i lokalnych układów striacji.

Możliwe podejścia:

  • mała dedykowana CNN trenowana od zera;
  • ResNet lub EfficientNet z transfer learning;
  • CNN z wejściem wielokanałowym;
  • CNN 1D dla profili wysokości;
  • CNN 2D dla map topografii.

Transfer learning może zmniejszyć zależność od dużej liczby danych domenowych, ale trzeba uważać, ponieważ modele trenowane na ImageNet uczą się naturalnych obrazów, a nie topografii powierzchni.

5.2. Siamese Network

Siamese Network składa się z dwóch identycznych gałęzi, które współdzielą wagi. Każda gałąź generuje embedding dla jednego obrazu. Następnie oblicza się odległość lub podobieństwo między embeddingami.

To podejście jest naturalne dla problemu:


Czy ślad A i ślad B mogły pochodzić z tego samego źródła?

W modelu Siamese sieć uczy się zmniejszać odległość między podobnymi obrazami i zwiększać odległość między obrazami różnymi.

5.3. Triplet Network

Triplet Network używa trzech obrazów:


anchor — obraz referencyjny

positive — obraz z tego samego źródła

negative — obraz z innego źródła

Celem jest nauczenie przestrzeni embeddingów, w której anchor jest bliżej positive niż negative.

Formalnie:

L(A,P,N)=max(d(A,P)d(A,N)+margin,0) L(A, P, N) = \max(d(A, P) - d(A, N) + margin, 0)

Podejście triplet loss zostało szeroko spopularyzowane m.in. przez FaceNet, gdzie model bezpośrednio uczył mapowania obrazów do zwartej przestrzeni euklidesowej, w której odległości odpowiadają miarze podobieństwa.

5.4. Vision Transformers

Vision Transformers dzielą obraz na patche i przetwarzają je jako sekwencję tokenów. Mogą uchwycić bardziej globalny kontekst niż klasyczne CNN, ale zwykle wymagają większej ilości danych lub dobrego pretrainingu.

W analizie śladów narzędziowych ViT może być przydatny, jeśli:

  • mamy dużo danych;
  • używamy self-supervised pretraining;
  • potrzebujemy uchwycić globalny układ śladu;
  • analizujemy większe powierzchnie, nie tylko lokalne cropy.

Przy małych zbiorach danych klasyczne CNN lub CNN z metric learning będą zwykle prostszym i bezpieczniejszym punktem startowym.


6. Ważne rozróżnienie: klasyfikator par vs embedding model

W prostych przykładach model Siamese często ma postać:


embedding A

embedding B

abs(A - B)

Dense

sigmoid

To może działać jako klasyfikator par, ale nie gwarantuje, że same embeddingi będą dobrze ułożone geometrycznie do wyszukiwania najbliższych sąsiadów.

Dlatego trzeba rozróżnić dwa podejścia.

Podejście 1: klasyfikator par

Model dostaje dwa obrazy i zwraca score:


image_a, image_b -> score

Zalety:

  • może być dokładny dla porównywania par;
  • uczy się własnej funkcji decyzyjnej;
  • nadaje się do verification.

Wady:

  • wolniejszy przy dużej bazie, bo trzeba porównać query z wieloma kandydatami;
  • wynik sigmoid nie jest automatycznie prawdopodobieństwem;
  • embeddingi pośrednie nie muszą być dobre dla FAISS/kNN.

Podejście 2: embedding model

Model generuje embedding:


image -> vector

Następnie porównujemy wektory przez cosine similarity lub L2 distance.

Zalety

  • nadaje się do szybkiego wyszukiwania;
  • można budować indeksy wektorowe;
  • łatwo zwrócić top-K kandydatów;
  • dobrze współpracuje z FAISS.

Wady:

  • wymaga dobrze zaprojektowanej funkcji straty;
  • wymaga walidacji geometrii embeddingów;
  • wymaga progu odrzucenia dla przypadków open-set.

Dla systemu wyszukiwania w bazie lepiej trenować model embeddingowy bezpośrednio z contrastive loss, triplet loss, supervised contrastive loss lub podobną funkcją straty.


7. Przykładowa implementacja w Keras

Poniższy kod jest przykładem koncepcyjnym. Nie jest gotowym systemem forensycznym. Pokazuje jednak bezpieczniejszy schemat niż prosty sigmoid na końcu modelu parowego.

Założenia:


label = 1 -> ta sama powierzchnia robocza / to samo źródło

label = 0 -> różne źródła

distance mała -> większe podobieństwo

distance duża -> mniejsze podobieństwo

7.1. Model embeddingowy


import tensorflow as tf

from tensorflow import keras

from tensorflow.keras import layers

  
  

def build_embedding_model(input_shape=(128, 128, 1), embedding_dim=128):

"""

Minimalny model embeddingowy dla obrazów śladów narzędziowych.

  

Uwaga:

- dla danych 3D / map wysokości preprocessing powinien być dopasowany

do sposobu pomiaru;

- dla obrazów już znormalizowanych warstwa Rescaling może być zbędna;

- w praktyce warto rozważyć ResNet/EfficientNet lub model 1D/2D

zależnie od typu danych.

"""

inputs = keras.Input(shape=input_shape, name="toolmark_image")

  

x = layers.Rescaling(1.0 / 255.0)(inputs)

  

x = layers.Conv2D(32, 3, padding="same", activation="relu")(x)

x = layers.BatchNormalization()(x)

x = layers.MaxPooling2D()(x)

  

x = layers.Conv2D(64, 3, padding="same", activation="relu")(x)

x = layers.BatchNormalization()(x)

x = layers.MaxPooling2D()(x)

  

x = layers.Conv2D(128, 3, padding="same", activation="relu")(x)

x = layers.BatchNormalization()(x)

  

x = layers.GlobalAveragePooling2D()(x)

x = layers.Dense(256, activation="relu")(x)

x = layers.Dropout(0.2)(x)

  

x = layers.Dense(embedding_dim, name="raw_embedding")(x)

  

# L2-normalizacja ułatwia używanie cosine similarity.

outputs = layers.Lambda(

lambda t: tf.math.l2_normalize(t, axis=1),

name="l2_normalized_embedding"

)(x)

  

return keras.Model(inputs, outputs, name="toolmark_embedding_model")

  
  

embedding_model = build_embedding_model()

embedding_model.summary()

7.2. Model Siamese z contrastive loss


def euclidean_distance(vectors):

emb_a, emb_b = vectors

squared = tf.reduce_sum(tf.square(emb_a - emb_b), axis=1, keepdims=True)

return tf.sqrt(tf.maximum(squared, tf.keras.backend.epsilon()))

  
  

def contrastive_loss(y_true, y_pred, margin=1.0):

"""

y_true = 1: para pasująca

y_true = 0: para niepasująca

  

Dla par pasujących minimalizujemy dystans.

Dla par niepasujących wypychamy dystans powyżej margin.

"""

y_true = tf.cast(y_true, y_pred.dtype)

  

positive_loss = y_true * tf.square(y_pred)

negative_loss = (1.0 - y_true) * tf.square(tf.maximum(margin - y_pred, 0.0))

  

return tf.reduce_mean(positive_loss + negative_loss)

  
  

input_a = keras.Input(shape=(128, 128, 1), name="image_a")

input_b = keras.Input(shape=(128, 128, 1), name="image_b")

  

emb_a = embedding_model(input_a)

emb_b = embedding_model(input_b)

  

distance = layers.Lambda(euclidean_distance, name="euclidean_distance")([emb_a, emb_b])

  

siamese_model = keras.Model(

inputs=[input_a, input_b],

outputs=distance,

name="siamese_toolmark_model"

)

  

siamese_model.compile(

optimizer=keras.optimizers.Adam(learning_rate=1e-4),

loss=contrastive_loss

)

  

siamese_model.summary()

7.3. Generowanie par treningowych

W praktyce generator powinien uwzględniać hard negatives. Nie wystarczy losować narzędzi z zupełnie różnych klas.


import numpy as np

  
  

def generate_pair(toolmark_dataset, hard_negative_map=None):

"""

toolmark_dataset:

dict:

tool_id -> lista obrazów lub rekordów obrazów

  

hard_negative_map:

dict opcjonalny:

tool_id -> lista tool_id podobnych narzędzi,

np. ten sam typ, model, producent, podobne zużycie

  

Zwraca:

img1, img2, label

"""

tool_ids = list(toolmark_dataset.keys())

  

same_source = np.random.rand() < 0.5

  

if same_source:

tool = np.random.choice(tool_ids)

samples = toolmark_dataset[tool]

  

if len(samples) < 2:

return generate_pair(toolmark_dataset, hard_negative_map)

  

idx = np.random.choice(len(samples), size=2, replace=False)

img1 = samples[idx[0]]

img2 = samples[idx[1]]

label = 1.0

  

else:

tool1 = np.random.choice(tool_ids)

  

if hard_negative_map and tool1 in hard_negative_map and len(hard_negative_map[tool1]) > 0:

candidate_negatives = hard_negative_map[tool1]

tool2 = np.random.choice(candidate_negatives)

else:

other_tools = [t for t in tool_ids if t != tool1]

tool2 = np.random.choice(other_tools)

  

img1 = toolmark_dataset[tool1][np.random.randint(len(toolmark_dataset[tool1]))]

img2 = toolmark_dataset[tool2][np.random.randint(len(toolmark_dataset[tool2]))]

label = 0.0

  

return img1, img2, label

7.4. Trenowanie


def batch_generator(toolmark_dataset, batch_size=32, hard_negative_map=None):

while True:

X1 = np.zeros((batch_size, 128, 128, 1), dtype="float32")

X2 = np.zeros((batch_size, 128, 128, 1), dtype="float32")

y = np.zeros((batch_size, 1), dtype="float32")

  

for i in range(batch_size):

img1, img2, label = generate_pair(

toolmark_dataset,

hard_negative_map=hard_negative_map

)

X1[i] = img1

X2[i] = img2

y[i] = label

  

yield (X1, X2), y

  
  

callbacks = [

keras.callbacks.EarlyStopping(

monitor="val_loss",

patience=10,

restore_best_weights=True

)

]

  

history = siamese_model.fit(

batch_generator(train_data, batch_size=32, hard_negative_map=hard_negative_map),

validation_data=batch_generator(val_data, batch_size=32, hard_negative_map=val_hard_negative_map),

steps_per_epoch=500,

validation_steps=100,

epochs=100,

callbacks=callbacks

)

7.5. Ekstrakcja embeddingów po treningu

Po treningu używamy embedding_model, a nie całego modelu Siamese, do budowy bazy embeddingów.


db_embeddings = embedding_model.predict(database_images, batch_size=64)

query_embedding = embedding_model.predict(query_image[None, ...])


8. Mechanizm wyszukiwania w bazie danych

Po wytrenowaniu modelu embeddingowego można zbudować bazę embeddingów dla znanych śladów.

Proces:


1. Pobierz obraz lub mapę topografii śladu.

2. Wykonaj ten sam preprocessing co podczas treningu.

3. Oblicz embedding.

4. Porównaj embedding z embeddingami w bazie.

5. Zwróć top-K kandydatów.

6. Zastosuj próg odrzucenia.

7. Przekaż wynik do oceny eksperta.

8.1. Cosine similarity i FAISS

Jeżeli embeddingi są znormalizowane L2, iloczyn skalarny odpowiada cosine similarity.


import faiss

import numpy as np

  

# db_embeddings: shape = (N, embedding_dim)

db_embeddings = db_embeddings.astype("float32")

  

# Dla bezpieczeństwa normalizujemy jeszcze raz.

faiss.normalize_L2(db_embeddings)

  

index = faiss.IndexFlatIP(db_embeddings.shape[1])

index.add(db_embeddings)

  

query_embedding = query_embedding.astype("float32")

faiss.normalize_L2(query_embedding)

  

top_k = 10

scores, indices = index.search(query_embedding, top_k)

  

for rank, (idx, score) in enumerate(zip(indices[0], scores[0]), start=1):

print(rank, idx, score)

Dla bardzo dużych baz można użyć indeksów approximate nearest neighbors. KD-tree nie jest zwykle najlepszym wyborem dla embeddingów o wysokim wymiarze, np. 128D lub 512D, ponieważ w wysokich wymiarach jego przewaga nad brute-force często maleje. Lepszym punktem startowym są indeksy ANN, FAISS lub brute-force na GPU dla mniejszych baz.

8.2. Closed-set vs open-set

To bardzo ważne rozróżnienie.

W scenariuszu closed-set zakładamy, że prawdziwe narzędzie znajduje się w bazie. Wtedy system ma znaleźć najlepsze dopasowanie.

W scenariuszu open-set prawdziwego narzędzia może nie być w bazie. Wtedy system musi umieć powiedzieć:


Brak wystarczającego wsparcia dla dopasowania w bazie.

Bez progu odrzucenia system zawsze zwróci jakiegoś najbliższego sąsiada, nawet jeżeli wszystkie kandydaty są błędne.

Dlatego w praktycznym systemie potrzebne są:

  • ranking top-K;

  • score podobieństwa;

  • próg odrzucenia;

  • kalibracja score'u;

  • walidacja na przypadkach, w których źródła nie ma w bazie;

  • raportowanie niepewności.


9. Walidacja, metryki i progi decyzyjne

W forensyce sama skuteczność na zbiorze testowym nie wystarcza. Trzeba pokazać, że metoda jest odpowiednia do zamierzonego zastosowania, ma znane ograniczenia, znane poziomy błędu i daje powtarzalne wyniki.

9.1. Macierz pomyłek

Dla porównywania par:


TP — para tego samego źródła poprawnie uznana za match

TN — para różnych źródeł poprawnie odrzucona

FP — para różnych źródeł błędnie uznana za match

FN — para tego samego źródła błędnie odrzucona

Kod:


import numpy as np

from sklearn.metrics import confusion_matrix, precision_score, recall_score, f1_score

  
  

def evaluate_at_threshold(y_true, distances, threshold):

"""

y_true:

1 = ta sama powierzchnia robocza / to samo źródło

0 = różne źródła

  

distances:

mniejszy dystans = większe podobieństwo

  

threshold:

jeśli distance <= threshold, klasyfikujemy jako match

"""

y_pred = (distances <= threshold).astype(int)

  

cm = confusion_matrix(y_true, y_pred, labels=[0, 1])

tn, fp, fn, tp = cm.ravel()

  

precision = precision_score(y_true, y_pred, zero_division=0)

recall = recall_score(y_true, y_pred, zero_division=0)

f1 = f1_score(y_true, y_pred, zero_division=0)

  

return {

"threshold": threshold,

"TN": tn,

"FP": fp,

"FN": fn,

"TP": tp,

"precision": precision,

"recall": recall,

"f1": f1

}

9.2. ROC, AUC i EER

Dla modelu embeddingowego często mamy dystans. Im mniejszy dystans, tym większe podobieństwo. Do ROC wygodnie zamienić dystans na score:


score = -distance

Kod:


from sklearn.metrics import roc_curve, auc

  
  

def compute_roc_eer(y_true, distances):

scores = -distances

  

fpr, tpr, score_thresholds = roc_curve(y_true, scores)

roc_auc = auc(fpr, tpr)

  

fnr = 1.0 - tpr

eer_idx = np.nanargmin(np.abs(fpr - fnr))

  

eer = (fpr[eer_idx] + fnr[eer_idx]) / 2.0

eer_score_threshold = score_thresholds[eer_idx]

eer_distance_threshold = -eer_score_threshold

  

return {

"fpr": fpr,

"tpr": tpr,

"fnr": fnr,

"auc": roc_auc,

"eer": eer,

"eer_distance_threshold": eer_distance_threshold

}

EER, czyli Equal Error Rate, to punkt, w którym false acceptance rate i false rejection rate są zbliżone. Jest to użyteczna metryka porównawcza, ale niekoniecznie optymalny próg decyzyjny w zastosowaniach forensycznych. W praktyce próg powinien być dobierany w zależności od celu systemu oraz konsekwencji FP i FN.

9.3. Top-K, CMC, MRR i mAP

Dla systemu wyszukiwania ważniejsze niż zwykła accuracy może być pytanie:


Czy prawidłowe źródło znajduje się w top-5 lub top-10 wyników?

Warto raportować:

  • Top-1 accuracy;
  • Top-5 accuracy;
  • Top-10 accuracy;
  • CMC curve;
  • Mean Reciprocal Rank;
  • mean Average Precision;
  • odsetek poprawnych odrzuceń w trybie open-set.

9.4. Niepewność i zależność par

Przy danych parowych istnieje ważny problem: pary nie są niezależne.

Jeden obraz może wystąpić w wielu parach, a jedno narzędzie może wygenerować setki porównań. Jeżeli policzymy accuracy po parach, możemy sztucznie zawyżyć wiarygodność wyników.

Dlatego warto stosować:

  • confidence intervals;
  • bootstrap grupowany po narzędziu;
  • bootstrap grupowany po próbce lub sprawie;
  • raportowanie wyników per tool type;
  • raportowanie wyników per laboratory/scanner;
  • oddzielną walidację dla łatwych i trudnych negatywów;
  • oddzielną walidację dla open-set.

9.5. Kalibracja score'u

Wynik modelu nie powinien być automatycznie nazywany prawdopodobieństwem.

Jeżeli model zwraca sigmoid = 0.92, to nie znaczy, że istnieje „92% prawdopodobieństwa dopasowania”. To tylko score modelu, chyba że został skalibrowany na reprezentatywnych danych.

Możliwe techniki kalibracji:

  • Platt scaling;
  • isotonic regression;
  • temperature scaling;
  • kalibracja oparta na rozkładach Known Same Source i Known Different Source;
  • likelihood ratio.

W forensic science coraz ważniejsze jest podejście, w którym surowe score'y porównawcze są interpretowane przez rozkłady known matching i known non-matching oraz przekształcane w likelihood ratio wraz z miarą niepewności.


10. Interpretacja wyniku w kontekście forensycznym

Wynik systemu powinien być komunikowany ostrożnie.

Zamiast:


Model zidentyfikował narzędzie.

lepiej pisać:


Model wskazał ślady referencyjne o najwyższym podobieństwie do śladu zapytania.

Zamiast:


Prawdopodobieństwo dopasowania wynosi 92%.

lepiej pisać:


Score podobieństwa wynosi 0.92 według modelu X, przy progu Y wyznaczonym na zbiorze walidacyjnym Z.

Jeszcze lepiej, jeżeli system jest poprawnie skalibrowany:


Wynik porównania odpowiada likelihood ratio LR = X w ramach zwalidowanego zakresu zastosowania: typ narzędzia A, materiał B, metoda obrazowania C.

W raporcie powinny znaleźć się:


- wersja modelu;

- wersja preprocessingu;

- typ danych wejściowych;

- opis bazy referencyjnej;

- top-K wyników;

- score lub dystans;

- próg decyzyjny;

- zakres walidacji;

- znane ograniczenia;

- poziomy błędów;

- informacja o niepewności;

- informacja, że wynik wymaga oceny eksperta.


11. Dokumentacja, akredytacja i powtarzalność

System forensyczny powinien być projektowany z myślą o audycie i odtwarzalności.

W praktyce trzeba dokumentować:

  • dane treningowe;

  • dane walidacyjne;

  • procedurę pozyskiwania danych;

  • parametry skanowania;

  • preprocessing;

  • architekturę modelu;

  • funkcję straty;

  • hiperparametry;

  • seedy losowości;

  • wersje bibliotek;

  • procedurę trenowania;

  • procedurę wyboru progu;

  • wyniki walidacji;

  • ograniczenia modelu.

W kontekście laboratoriów kryminalistycznych istotne są standardy i wytyczne jakościowe, m.in. ISO/IEC 17025, ISO/IEC 17020 oraz wytyczne ILAC dotyczące laboratoriów forensic science, niepewności pomiaru i reguł decyzyjnych.

Walidacja powinna obejmować co najmniej:


1. Zakres zastosowania:

Dla jakich narzędzi, materiałów i metod obrazowania system jest przeznaczony?


2. Dane:

Czy dane są reprezentatywne dla rzeczywistych przypadków?

  

3. Metryki:

Jakie są FP, FN, TPR, FPR, AUC, EER, Top-K, open-set rejection?

  

4. Niepewność:

Jakie są przedziały ufności i zmienność między narzędziami?

  

5. Powtarzalność:

Czy ta sama procedura daje podobne wyniki w tych samych warunkach?

  

6. Odtwarzalność:

Czy wyniki są podobne między operatorami, urządzeniami i laboratoriami?

  

7. Dokumentacja:

Czy wynik można odtworzyć po czasie?

  

8. Ekspercka weryfikacja:

Czy system wspiera, a nie zastępuje ocenę biegłego?


12. Zalecana architektura systemu

Praktyczny system można podzielić na moduły:


[Acquisition]

zdjęcie 2D / skan 3D / mapa wysokości

  

[Preprocessing]

ROI, leveling, normalizacja, maskowanie, kontrola jakości

  

[Embedding Model]

CNN / ResNet / model 1D / model 3D / ViT

  

[Vector Database]

embeddingi znanych śladów

  

[Search Engine]

FAISS / ANN / brute-force GPU

  

[Verification]

score pary, dystans, calibrated score

  

[Decision Support]

top-K, progi, open-set rejection, wizualizacje

  

[Expert Review]

końcowa ocena eksperta

  

[Reporting]

wersje, metryki, zakres walidacji, niepewność

Taki podział pozwala jasno rozdzielić część badawczą, część obliczeniową i część ekspercką.


13. Najważniejsze ryzyka

Ryzyka przy projektowaniu takiego systemu:


1. Zbyt mocna teza:

„Model identyfikuje narzędzie” zamiast „model wspiera ranking kandydatów”.

  

2. Data leakage:

Fragmenty tego samego śladu w treningu i teście.

  

3. Zbyt łatwe negatywy:

Model uczy się typu narzędzia, a nie indywidualnego źródła.

  

4. Brak open-set:

System zawsze wskazuje najbliższego sąsiada, nawet gdy prawdziwego narzędzia nie ma w bazie.

  

5. Sigmoid jako „prawdopodobieństwo”:

Wynik 0–1 nie oznacza automatycznie skalibrowanego prawdopodobieństwa.

  

6. Brak kalibracji:

Brak progu i brak oszacowania niepewności.

  

7. Brak walidacji między sesjami i laboratoriami:

Model działa dobrze tylko na danych z jednego skanera.

  

8. Nadmierna augmentacja:

Transformacje tworzą ślady niefizyczne.

  

9. Brak metadanych:

Nie wiadomo, czego model się nauczył.

  

10. Brak dokumentacji:

Wyniku nie da się odtworzyć ani obronić.


14. Podsumowanie

Deep learning może być użyteczny w analizie śladów narzędziowych, ale tylko jako element dobrze zaprojektowanego, zwalidowanego i udokumentowanego systemu wspomagającego.

Najbezpieczniejszy kierunek to:


1. Pozyskiwać wysokiej jakości dane 2D lub 3D.

2. Dokumentować metadane i warunki pomiaru.

3. Unikać data leakage.

4. Trenować embedding model przez metric learning.

5. Używać hard negatives.

6. Budować bazę embeddingów i wyszukiwać top-K kandydatów.

7. Obsługiwać open-set, czyli przypadek braku źródła w bazie.

8. Kalibrować score'y i progi.

9. Raportować FP, FN, AUC, EER, Top-K oraz niepewność.

10. Traktować wynik jako wsparcie dla eksperta, nie automatyczny dowód.

Poprawnie zaprojektowany system może znacząco przyspieszyć analizę porównawczą, pomóc w przeszukiwaniu dużych baz śladów i wskazać kandydatów do dalszej oceny. Nie powinien jednak zastępować biegłego ani wykraczać poza zakres, w którym został zwalidowany.


Bibliografia

  1. Koch, G., Zemel, R., Salakhutdinov, R. — Siamese Neural Networks for One-shot Image Recognition, 2015.

https://www.cs.cmu.edu/~rsalakhu/papers/oneshot1.pdf

  1. Schroff, F., Kalenichenko, D., Philbin, J. — FaceNet: A Unified Embedding for Face Recognition and Clustering, 2015.

https://arxiv.org/abs/1503.03832

  1. Dosovitskiy, A. et al. — An Image is Worth 16x16 Words: Transformers for Image Recognition at Scale, 2020.

https://arxiv.org/abs/2010.11929

  1. Zhuang, F. et al. — A Comprehensive Survey on Transfer Learning, 2019.

https://arxiv.org/abs/1911.02685

  1. Keras — Image similarity estimation using a Siamese Network with a contrastive loss
    https://keras.io/examples/vision/siamese_contrastive/

  2. Keras — Image similarity estimation using a Siamese Network with a triplet loss.

https://keras.io/examples/vision/siamese_network/

  1. FAISS Documentation — Efficient similarity search and clustering of dense vectors.

https://faiss.ai/index.html

  1. NIST — Surface Texture and Forensic Topography.

https://www.nist.gov/programs-projects/surface-texture-and-forensic-topography

  1. NIST — Firearms and Toolmarks.

https://www.nist.gov/spo/forensic-science-program/firearms-and-toolmarks

  1. Swofford, H. et al. — Validation in Forensic Science: Guiding Principles for the Collection and Use of Validation Data, NIST IR 8589, 2025.

https://www.nist.gov/publications/validation-forensic-science-guiding-principles-collection-and-use-validation-data

  1. ASB Standard 100 — Standard Scale and Criteria for Source Conclusions in Toolmark Examinations.

https://www.aafs.org/asb-standard-100-standard-scale-and-criteria-source-conclusions-toolmark-examinations

  1. Patteet, J.-A., Champod, C. — Striated toolmarks comparison and reporting methods: Review and perspectives, Forensic Science International, 2024.

https://www.sciencedirect.com/science/article/pii/S0379073824000781

  1. Baiker-Sørensen, M. et al. — Automated interpretation of firearm mark comparison results, Forensic Science International, 2023.

https://www.nist.gov/publications/automated-interpretation-firearm-mark-comparison-results

  1. Cuellar, M., Gao, S., Hofmann, H. — An algorithm for forensic toolmark comparisons, 2024.

https://arxiv.org/html/2312.00032v3

  1. ILAC — Guidance Documents: ILAC G17, ILAC G19 and related forensic accreditation guidance.

https://ilac.org/publications-and-resources/ilac-guidance-series/

  1. scikit-learn — Metrics and scoring: quantifying the quality of predictions.

https://scikit-learn.org/stable/modules/model_evaluation.html