6.1 KiB
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 (3.11 również powinien działać).
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,iglicalubunknown, - nasilenie:
male,srednie,duze; dlaokiunknownzawszenie_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.csvi 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ć.
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/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:
okzmienia się naunknowntylko 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.
Kontrakt danych wejściowych
Każdy wiersz reprezentuje cylinder. Wymagane kolumny:
engine_id,cylinder,n_cylindersró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:
python -m unittest discover -v
Pakiet zawiera 32 testy:
- 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.
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 raz i przechowywany w cache procesu.
- 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.