Marcin Bukowski
07.06.2026
Model logitowy (regresja logistyczna) to parametryczny model statystyczny służący do modelowania prawdopodobieństwa wystąpienia zdarzenia binarnego (np. niespłacenia kredytu).
W naszym przypadku:
Model logitowy modeluje:
\[ P(Y = 1 \mid X_1, \ldots, X_p) \in (0, 1) \]
Następnie na podstawie wybranego progu odcięcia (zwykle \(0{,}5\)) przypisujemy klasę.
Gdyby zastosować regresję liniową \(Y = \beta_0 + \beta_1 X_1 + \ldots + \varepsilon\):
Rozwiązanie: zastosować nieliniową funkcję łączącą (link function) - logit - która sprowadza prawdopodobieństwo z \((0,1)\) na całą oś \(\mathbb{R}\):
\[ \text{logit}(p) = \ln\left(\frac{p}{1-p}\right) \]
Szansa (odds):
\[ \text{odds}(Y=1) = \frac{P(Y=1)}{1 - P(Y=1)} \]
Logit (logarytm szansy) jest modelowany liniowo:
\[ \ln\left(\frac{p}{1-p}\right) = \beta_0 + \beta_1 X_1 + \beta_2 X_2 + \ldots + \beta_p X_p \]
Odwrotność: rozwiązując względem \(p\), otrzymujemy funkcję logistyczną:
\[ p = P(Y=1 \mid X) = \frac{e^{\beta_0 + \beta_1 X_1 + \ldots + \beta_p X_p}}{1 + e^{\beta_0 + \beta_1 X_1 + \ldots}} = \frac{1}{1 + e^{-(\beta_0 + \beta_1 X_1 + \ldots)}} \]
Funkcja jest monotonicznie rosnąca, ograniczona w przedziale \((0, 1)\), z punktem przegięcia w \(z = 0\) (gdzie \(p = 0{,}5\)).
Parametry \(\boldsymbol{\beta}\) estymujemy maksymalizując funkcję wiarygodności. Dla próby \((x_i, y_i)\), \(i=1,\ldots,n\):
\[ L(\boldsymbol{\beta}) = \prod_{i=1}^{n} p_i^{y_i} (1 - p_i)^{1 - y_i} \]
W praktyce maksymalizujemy logarytm wiarygodności (log-likelihood):
\[ \ell(\boldsymbol{\beta}) = \sum_{i=1}^{n} \left[ y_i \ln p_i + (1 - y_i) \ln(1 - p_i) \right] \]
gdzie \(p_i = 1 / (1 + e^{-\mathbf{x}_i^T \boldsymbol{\beta}})\).
Maksimum znajdujemy iteracyjnie - algorytmem IRLS
(Iteratively Reweighted Least Squares) lub metodą Newtona-Raphsona. W R
robi to za nas funkcja glm().
Po dopasowaniu modelu oceniamy je m.in. przez:
glm(family = binomial)).Fikcyjny zbiór 500 klientów banku, klasy:
Zmienne objaśniające:
Wiek - wiek klienta (lata),Dochod - miesięczny dochód netto (zł),Staz_pracy - staż pracy (lata),Zadluzenie - łączne zadłużenie (zł),Liczba_kredytow - liczba aktywnych kredytów,Status_mieszk - status mieszkaniowy (Własne / Wynajem /
Rodzice).| Wiek | Dochod | Staz_pracy | Zadluzenie | Liczba_kredytow | Status_mieszk | Klasa |
|---|---|---|---|---|---|---|
| 47 | 8173 | 17 | 1718 | 1 | Wlasne | Dobry |
| 32 | 8098 | 11 | 1122 | 1 | Wynajem | Dobry |
| 43 | 6612 | 12 | 999 | 1 | Wlasne | Dobry |
| 41 | 10608 | 15 | 2371 | 0 | Wlasne | Dobry |
| 36 | 6654 | 10 | 2325 | 1 | Wlasne | Dobry |
| 20 | 6829 | 11 | 2132 | 1 | Wynajem | Dobry |
| 35 | 6594 | 9 | 1476 | 0 | Rodzice | Dobry |
| 33 | 12150 | 10 | 2254 | 0 | Wlasne | Dobry |
model <- glm(
Y ~ Wiek + Dochod + Staz_pracy + Zadluzenie +
Liczba_kredytow + Status_mieszk,
data = train,
family = binomial(link = "logit")
)Kluczowe argumenty:
family = binomial(link = "logit") - mówi R, że budujemy
regresję logistyczną.Y musi być liczbą 0/1 (lub czynnikiem
- wtedy “sukcesem” jest drugi poziom).Alternatywne funkcje łączące w binomial:
probit - dystrybuanta rozkładu normalnego,cloglog - complementary log-log (asymetryczna, dobra
dla rzadkich zdarzeń).| Zmienna | Estymata β | Bł. std. | Stat. z | p-value | exp(β) = OR |
|---|---|---|---|---|---|
| (Intercept) | 11.5862 | 5.1075 | 2.2685 | 0.0233 | 107600.8524 |
| Wiek | -0.1467 | 0.0927 | -1.5828 | 0.1135 | 0.8635 |
| Dochod | -0.0021 | 0.0008 | -2.6487 | 0.0081 | 0.9979 |
| Staz_pracy | -0.4983 | 0.2310 | -2.1567 | 0.0310 | 0.6076 |
| Zadluzenie | 0.0027 | 0.0009 | 2.8954 | 0.0038 | 1.0027 |
| Liczba_kredytow | 1.8710 | 0.7350 | 2.5455 | 0.0109 | 6.4948 |
| Status_mieszkWynajem | -2.3490 | 1.7614 | -1.3336 | 0.1823 | 0.0955 |
| Status_mieszkRodzice | 2.7251 | 2.4681 | 1.1041 | 0.2695 | 15.2582 |
Statystyka Walda \(z = \hat{\beta}/SE(\hat{\beta})\) testuje hipotezę \(H_0: \beta = 0\).
Jeżeli różnica między null deviance a residual deviance jest duża - dodanie predyktorów wyraźnie poprawia model.
Współczynniki w skali logitowej trudno interpretować bezpośrednio. Stosujemy iloraz szans (OR) - \(e^{\beta_j}\):
\[ OR_j = \frac{\text{odds}(Y=1 \mid X_j = x + 1)}{\text{odds}(Y=1 \mid X_j = x)} = e^{\beta_j} \]
Interpretacja:
Dla zmiennych ilościowych w dużych jednostkach (np. dochód w zł) wygodnie liczyć OR dla zmiany o 1000 zł: \(OR_{1000} = e^{1000 \cdot \beta_j}\).
OR powyżej linii 1 → zwiększa ryzyko, poniżej → zmniejsza.
# Prawdopodobieństwo P(Y = 1) - klient "Zły"
prob_test <- predict(model, newdata = test, type = "response")
# Klasyfikacja przy progu 0.5
pred_test <- factor(ifelse(prob_test > 0.5, "Zly", "Dobry"),
levels = c("Dobry","Zly"))|
Predykcja Rzeczywistość
|
Dobry
|
Zly
|
|---|---|---|
| Dobry | Zly | |
| Dobry | 93 | 2 |
| Zly | 0 | 55 |
Oznaczenia: TP - poprawnie “Zły”, TN - poprawnie “Dobry”, FP - błędnie “Zły” (fałszywy alarm), FN - błędnie “Dobry” (przeoczone ryzyko).
\[ \text{Accuracy} = \frac{TP + TN}{TP + TN + FP + FN} \qquad \text{Error Rate} = \frac{FP + FN}{TP + TN + FP + FN} \]
\[ \text{Sensitivity} = \frac{TP}{TP + FN} \qquad \text{Specificity} = \frac{TN}{TN + FP} \]
\[ \text{Precision} = \frac{TP}{TP + FP} \qquad F_1 = \frac{2 \cdot \text{Precision} \cdot \text{Recall}}{\text{Precision} + \text{Recall}} \]
\[ \text{AUC} = \int_0^1 TPR(FPR^{-1}(t)) \, dt \qquad \text{Gini} = 2 \cdot AUC - 1 \]
Z naszej macierzy pomyłek (N = 150): TP = 55, TN = 93, FP = 0, FN = 2.
\[\text{Accuracy} = \frac{55 + 93}{150} = \frac{148}{150} \approx 0.987\]\[\text{Error Rate} = \frac{0 + 2}{150} \approx 0.013\]\[\text{Sensitivity} = \frac{55}{55 + 2} = \frac{55}{57} \approx 0.965\]\[\text{Specificity} = \frac{93}{93 + 0} = \frac{93}{93} \approx 1.000\]
\[\text{Precision} = \frac{55}{55 + 0} = \frac{55}{55} \approx 1.000\]\[F_1 = \frac{2 \cdot 1.000 \cdot 0.965}{1.000 + 0.965} \approx 0.982\]\[\text{AUC} \approx 0.990 \qquad \text{Gini} = 2 \cdot 0.990 - 1 \approx 0.980\]
Interpretacja: Accuracy = 0.987, czyli model poprawnie klasyfikuje 98.7% klientów testowych. AUC = 0.99 oznacza dobrą zdolność dyskryminacyjną - dla losowej pary (zły, dobry) model w 99% przypadków przypisze wyższe prawdopodobieństwo złemu.
| Miara | Wartosc | Opis |
|---|---|---|
| Accuracy | 0.987 | Udział poprawnych klasyfikacji ogółem |
| Error Rate | 0.013 | Udział błędnych klasyfikacji |
| Sensitivity | 0.965 | Skuteczność wykrywania klientów ‘złych’ |
| Specificity | 1.000 | Skuteczność wykrywania klientów ‘dobrych’ |
| Precision | 1.000 | Wiarygodność predykcji ‘zły’ |
| F1-score | 0.982 | Średnia harmoniczna precyzji i czułości |
| AUC | 0.990 | Pole pod krzywą ROC |
| Gini | 0.980 | Współczynnik Giniego = 2·AUC - 1 |
ROC pokazuje kompromis czułość vs. swoistość dla wszystkich progów odcięcia. AUC ≈ 0,5 - klasyfikator losowy, AUC = 1 - idealny.
W scoringu kredytowym KS > 0,3 uznaje się za akceptowalny, KS > 0,5 za bardzo dobry.
W modelu logitowym przeuczenie objawia się:
Sygnał ostrzegawczy: różnica AUC między uczącym a testowym > 0,05.
Nasz model: AUC uczący = 0.999, AUC testowy = 0.990, różnica = 0.009
Iteracyjne dodawanie/usuwanie zmiennych minimalizujące AIC:
\[ AIC = -2 \ell(\hat{\boldsymbol{\beta}}) + 2k \]
Wybrany model:
Y ~ Wiek + Dochod + Staz_pracy + Zadluzenie + Liczba_kredytow +
Wybrany model:
Status_mieszk
AIC: model pełny = 38.58
| model po selekcji = 38.58
AIC karze za dodatkowe parametry - mniejszy AIC oznacza lepszy kompromis między dopasowaniem a złożonością.
Gdy zmiennych jest bardzo dużo, stosujemy
regularyzację (pakiet glmnet):
\[ \hat{\boldsymbol{\beta}} = \arg\min_{\boldsymbol{\beta}} \left[ -\ell(\boldsymbol{\beta}) + \lambda \sum_{j=1}^p |\beta_j|^q \right] \]
Parametr \(\lambda\) wybieramy przez
kros-walidację (cv.glmnet).
Tak jak w drzewach, błędy mają różne koszty finansowe:
W modelu logitowym mamy bezpośrednią kontrolę przez próg odcięcia \(p^*\):
\[ \hat{y} = \begin{cases} 1 & \text{gdy } \hat{p} > p^* \\ 0 & \text{w przeciwnym razie} \end{cases} \]
Domyślnie \(p^* = 0{,}5\), ale to rzadko jest optymalne ekonomicznie.
Oczekiwany koszt dla progu \(p^*\):
\[ E[\text{Koszt}](p^*) = C_{FP} \cdot FP(p^*) + C_{FN} \cdot FN(p^*) \]
Teoretyczny optymalny próg dla założeń kosztowych (przy zbalansowanej próbie):
\[ p^*_{opt} = \frac{C_{FP}}{C_{FP} + C_{FN}} = \frac{1000}{1000 + 10000} \approx 0{,}091 \]
| Prog | FP | FN | Sensitivity | Specificity | Koszt (zł) |
|---|---|---|---|---|---|
| 0,50 (domyślny) | 0 | 2 | 0.965 | 1 | 20 000 |
| 0,48 (optymalny) | 0 | 2 | 0.965 | 1 | 20 000 |
Przesunięcie progu w dół zwiększa FP, ale drastycznie redukuje FN - i to obniża koszt łączny, bo FN jest 10× droższy.
glm(weights = ...) - większe wagi dla rzadszej /
kosztowniejszej klasy.glmnet, xgboost.Kontakt: mbukowski1977@gmail.com
Pełny kod źródłowy w pliku model_logitowy.Rmd.
Aby wygenerować prezentację: