Go to file
Jakub Famulski 2 8e6dcb750d
All checks were successful
ENGIN CI / Build, test and smoke (push) Successful in 2m58s
prod: load versioned model artifact at runtime
2026-08-25 13:06:14 +02:00
.gitea/workflows prod: load versioned model artifact at runtime 2026-08-25 13:06:14 +02:00
.streamlit feat: initial ENGIN diagnostic product 2026-08-25 11:26:55 +02:00
archive/legacy_experiments feat: initial ENGIN diagnostic product 2026-08-25 11:26:55 +02:00
artifacts/engin-2026.08.25-1 prod: load versioned model artifact at runtime 2026-08-25 13:06:14 +02:00
assets feat: initial ENGIN diagnostic product 2026-08-25 11:26:55 +02:00
docs feat: initial ENGIN diagnostic product 2026-08-25 11:26:55 +02:00
engin prod: load versioned model artifact at runtime 2026-08-25 13:06:14 +02:00
presentation feat: initial ENGIN diagnostic product 2026-08-25 11:26:55 +02:00
scripts prod: load versioned model artifact at runtime 2026-08-25 13:06:14 +02:00
tests prod: load versioned model artifact at runtime 2026-08-25 13:06:14 +02:00
.dockerignore prod: load versioned model artifact at runtime 2026-08-25 13:06:14 +02:00
.gitignore feat: initial ENGIN diagnostic product 2026-08-25 11:26:55 +02:00
1_przebiegi_usterek.png feat: initial ENGIN diagnostic product 2026-08-25 11:26:55 +02:00
2_przebiegi_silnika.png feat: initial ENGIN diagnostic product 2026-08-25 11:26:55 +02:00
app.py prod: load versioned model artifact at runtime 2026-08-25 13:06:14 +02:00
baseline_predictions.csv feat: initial ENGIN diagnostic product 2026-08-25 11:26:55 +02:00
benchmark_grouped.py prod: load versioned model artifact at runtime 2026-08-25 13:06:14 +02:00
Dockerfile prod: load versioned model artifact at runtime 2026-08-25 13:06:14 +02:00
final_pipeline.py prod: load versioned model artifact at runtime 2026-08-25 13:06:14 +02:00
ml_polish_benchmark.py ci: enforce Ruff lint checks 2026-08-25 12:37:41 +02:00
ml_polish_negative_control.csv feat: initial ENGIN diagnostic product 2026-08-25 11:26:55 +02:00
ml_polish_runs.csv feat: initial ENGIN diagnostic product 2026-08-25 11:26:55 +02:00
ml_polish_summary.csv feat: initial ENGIN diagnostic product 2026-08-25 11:26:55 +02:00
prediction_diagnostics.csv feat: initial ENGIN diagnostic product 2026-08-25 11:26:55 +02:00
predictions.csv feat: initial ENGIN diagnostic product 2026-08-25 11:26:55 +02:00
README.md prod: load versioned model artifact at runtime 2026-08-25 13:06:14 +02:00
requirements-lock.txt prod: load versioned model artifact at runtime 2026-08-25 13:06:14 +02:00
requirements.txt feat: initial ENGIN diagnostic product 2026-08-25 11:26:55 +02:00
robustness_grouped.py feat: initial ENGIN diagnostic product 2026-08-25 11:26:55 +02:00
ruff.toml ci: enforce Ruff lint checks 2026-08-25 12:37:41 +02:00
sample_submit.csv feat: initial ENGIN diagnostic product 2026-08-25 11:26:55 +02:00
severity_benchmark.py prod: load versioned model artifact at runtime 2026-08-25 13:06:14 +02:00
severity_negative_control.py feat: initial ENGIN diagnostic product 2026-08-25 11:26:55 +02:00
starter.py feat: initial ENGIN diagnostic product 2026-08-25 11:26:55 +02:00
test_benchmark_grouped.py feat: initial ENGIN diagnostic product 2026-08-25 11:26:55 +02:00
test_final_pipeline.py feat: initial ENGIN diagnostic product 2026-08-25 11:26:55 +02:00
test.csv feat: initial ENGIN diagnostic product 2026-08-25 11:26:55 +02:00
train.csv feat: initial ENGIN diagnostic product 2026-08-25 11:26:55 +02:00
val.csv feat: initial ENGIN diagnostic product 2026-08-25 11:26:55 +02:00

ENGIN Diagnostic Console

Gotowy do demonstracji system diagnostyki cylindrów przemysłowych silników Diesla. Z pomiaru widma 020 kHz rozpoznaje stan każdego cylindra, przewiduje nasilenie usterki i pokazuje mechanikowi, które pasma oraz cylindry wymagają uwagi.

Uruchomienie

Wymagany jest Python 3.12. Artefakt modelu sprawdza zgodność wersji Pythona i bibliotek przed deserializacją.

python -m venv .venv
source .venv/bin/activate
pip install -r requirements-lock.txt
streamlit run app.py

Windows PowerShell:

py -m venv .venv
.venv\Scripts\Activate.ps1
pip install -r requirements-lock.txt
streamlit run app.py

Aplikacja otworzy się pod http://localhost:8501. Od razu uruchamia bezpieczne demo na test.csv; w panelu bocznym można przełączyć się na własny CSV.

Alternatywnie przez Docker:

docker build -t engin-console .
docker run --rm -p 8501:8501 engin-console

Co zawiera produkt

  • mapa 8-, 12- i 16-cylindrowych silników z diagnozą każdego cylindra,
  • typ usterki: ok, zakoksowany, lejacy, pompa, iglica lub unknown,
  • nasilenie: male, srednie, duze; dla ok i unknown zawsze nie_dotyczy,
  • status silnika, najwyższe rzeczywiste severity i kolejka cylindrów do kontroli,
  • heatmapa odchyleń całego silnika,
  • porównanie widma cylindra z medianą pozostałych cylindrów tej samej jednostki,
  • trzy najbardziej anomalne pasma, niekalibrowany score modelu oraz rekomendowany następny krok,
  • pobieranie predictions.csv i rozszerzonej diagnostyki,
  • ścisła walidacja CSV i bezpieczne komunikaty błędów,
  • lokalne działanie na CPU, bez wysyłania danych do zewnętrznych usług.

Architektura

Interfejs jest cienką warstwą prezentacji. Zależności są wstrzykiwane do DiagnosticService, dlatego odczyt pliku, walidator i model można niezależnie wymieniać oraz testować.

Proces produkcyjny nie trenuje modelu przy starcie. Aplikacja weryfikuje checksumę, schemat wejścia i wersje bibliotek, a następnie ładuje artefakt engin-2026.08.25-1. Uszkodzony lub niezgodny artefakt uruchamia ograniczony fallback demonstracyjny.

flowchart TD
    UI["Streamlit UI"] --> S["DiagnosticService"]
    S --> R["FrameReader"]
    S --> V["FrameValidator"]
    S --> M["PredictionModel"]
    S --> E["Explainability + wykresy"]

Najważniejsze katalogi i pliki:

app.py                       cienka warstwa Streamlit
engin/io.py                  adapter odczytu CSV
engin/validation.py          kontrakt i walidacja danych
engin/model.py               adapter modelu i fallback demo
engin/artifact.py            manifest, checksumy i ładowanie artefaktu
engin/features.py            stabilne transformacje używane w train/inference
engin/inference.py           runtime predykcji bez zależności od benchmarków
engin/service.py             przypadek użycia / dependency injection
engin/explainability.py      status, porządkowy triage i uzasadnienia
engin/charts.py              czyste, testowalne fabryki Plotly
final_pipeline.py            finalny pipeline konkursowy
tests/                       testy aplikacji, błędów i komponentów
docs/DEMO_SCENARIO.md         gotowy scenariusz prezentacji 35 min
docs/JURY_QA.md               odpowiedzi na typowe pytania jury

Model i wynik

Finalna architektura została wybrana w walidacji StratifiedGroupKFold po engine_id, bez mieszania cylindrów tego samego silnika:

  • label: odchylenie od mediany pozostałych cylindrów + Logistic Regression (C=10),
  • OOD: ok zmienia się na unknown tylko po przekroczeniu progu 7.25 mV oraz 2.5× mediany anomalii własnego silnika,
  • severity: cechy odchylenia + Extra Trees (max_features=0.3),
  • braki widma: interpolacja wzdłuż częstotliwości z deterministycznym fallbackiem,
  • inference na CPU, bez CNN i bez GPU.
Scenariusz walidacji Macro F1 Severity accuracy Raw Score Punkty ML
clean 0.9811 0.9298 0.9683 33.65/40
dokładnie 5% braków 0.9829 0.9333 0.9705 34.10/40

To średnie z pięciu seedów walidacji grupowej, nie wynik ukrytego testu. Negative control dla severity pozostaje w okolicy losowego poziomu, co zmniejsza ryzyko pozornego wyniku przez leakage.

Jedynym źródłem finalnych metryk jest ml_polish_benchmark.py oraz pliki ml_polish_summary.csv/ml_polish_runs.csv. Starsze eksperymenty zostały przeniesione do archive/legacy_experiments/ i jawnie oznaczone jako niewłaściwe do raportowania finalnego wyniku.

Score zwracany przez predict_proba służy tylko do względnego porównania predykcji i nie jest przedstawiany jako skalibrowane prawdopodobieństwo awarii. Dla decyzji OOD score label jest celowo pusty, ponieważ OOD jest regułą bezpieczeństwa, a nie klasą modelu probabilistycznego.

Finalne pliki można odtworzyć poleceniem:

python final_pipeline.py

Powstają predictions.csv (600/600 rekordów, bez duplikatów i braków) oraz prediction_diagnostics.csv używany przez aplikację do explainability.

Wersjonowany artefakt modelu buduje osobny krok release:

python -m scripts.build_model_artifact \
  --source-revision "$(git rev-parse HEAD)"

python -m scripts.build_model_artifact --verify-only

Druga komenda nie trenuje modelu. Ładuje artefakt, sprawdza manifest i checksumę oraz wymaga dokładnej zgodności wszystkich 600 predykcji z zamrożonym predictions.csv.

Kontrakt danych wejściowych

Każdy wiersz reprezentuje cylinder. Wymagane kolumny:

  • engine_id,
  • cylinder,
  • n_cylinders równe 8, 12 albo 16,
  • mV_0mV_20.

Każdy silnik musi zawierać dokładnie cylindry 1..n_cylinders. Aplikacja odrzuca między innymi puste i zbyt duże pliki, brakujące kolumny, duplikaty cylindrów, tekst w widmie, wartości ujemne/nieskończone, niespójny rozmiar jednostki i ponad 50% braków w jednym cylindrze. Mniejsza liczba braków jest uzupełniana tak samo jak podczas walidacji modelu.

Testy i weryfikacja

Pełna kontrola projektu:

python -m unittest discover -v

Pakiet zawiera 38 testów:

  • testy braku leakage, cech, OOD i kontraktu submission,
  • testy jednostkowe walidatora i błędnych CSV,
  • testy serwisu z fake reader/validator/model — weryfikują dependency injection,
  • testy explainability, rankingu i wykresów,
  • testy smoke Streamlit dla demo, pustego uploadu i synchronizacji mapy cylindrów ze szczegółami.
  • testy artefaktu: checksumy, zgodność bibliotek, brak odczytu danych treningowych przy starcie i regresja predykcji 600/600.

Szybka kontrola serwera:

streamlit run app.py --server.headless true
# drugi terminal
curl --fail http://localhost:8501/_stcore/health

Oczekiwana odpowiedź: ok.

Odporność operacyjna

  • Model jest trenowany poza aplikacją i ładowany raz z wersjonowanego artefaktu do cache procesu.
  • Finalny obraz runtime nie zawiera val.csv, train.csv ani skryptów treningowych.
  • Nieoczekiwany błąd inicjalizacji modelu uruchamia read-only fallback dla danych demo.
  • Nieprawidłowe dane nie docierają do modelu.
  • Błędy użytkownika mają stabilne kody i nie pokazują tracebacków w interfejsie.
  • Zależności produkcyjne są przypięte w requirements-lock.txt.
  • Aplikacja nie zmienia przesłanego pliku i nie wykonuje połączeń zewnętrznych.