hackathon-ENGIN/README.md
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

169 lines
7.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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ą.
```bash
python -m venv .venv
source .venv/bin/activate
pip install -r requirements-lock.txt
streamlit run app.py
```
Windows PowerShell:
```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:
```bash
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.
```mermaid
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:
```text
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:
```bash
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:
```bash
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_0``mV_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:
```bash
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:
```bash
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.