All checks were successful
ENGIN CI / Build, test and smoke (push) Successful in 1m1s
176 lines
7.8 KiB
Markdown
176 lines
7.8 KiB
Markdown
# ENGIN Diagnostic Console
|
||
|
||
Gotowy do demonstracji system diagnostyki cylindrów przemysłowych silników Diesla. Z pomiaru widma 0–20 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 --target runtime -t engin-console .
|
||
docker run --rm -p 127.0.0.1:8501:8501 engin-console
|
||
```
|
||
|
||
Zalecane uruchomienie produkcyjne korzysta z `compose.prod.yaml`: kontener działa
|
||
jako UID/GID `10001`, z systemem plików tylko do odczytu, bez Linux capabilities
|
||
oraz z limitami CPU, pamięci i procesów. Pełna procedura startu, aktualizacji i
|
||
rollbacku znajduje się w `docs/PRODUCTION_RUNBOOK.md`.
|
||
|
||
## Co zawiera produkt
|
||
|
||
- przegląd silników 8-, 12- i 16-cylindrowych 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 nasilenie i kolejka cylindrów do kontroli,
|
||
- mapa odchyleń całego silnika ze stałą, porównywalną skalą,
|
||
- porównanie widma cylindra z medianą pozostałych cylindrów tej samej jednostki,
|
||
- priorytet kontroli, trzy najbardziej anomalne pasma oraz krótkie uzasadnienie diagnozy,
|
||
- 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 3–5 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.
|
||
- Proces aplikacji działa jako użytkownik bez uprawnień roota; produkcyjny Compose
|
||
dodatkowo wymusza read-only root filesystem, usuwa capabilities i ustawia limity zasobów.
|
||
- 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.
|