#Biblioteki
library(pROC)
## Type 'citation("pROC")' for a citation.
## 
## Dołączanie pakietu: 'pROC'
## Następujące obiekty zostały zakryte z 'package:stats':
## 
##     cov, smooth, var
#Dodanie danych
dane <- read.csv("C:/Users/grzeg/OneDrive/Pulpit/Projekt_27/german.data-numeric.csv", header = FALSE, sep = " ")
#Dodanie nazw zmiennych
colnames(dane) <- c(
  "Stan_konta", "Czas_kredytu", "Historia_kredytowa", "Cel_kredytu", "Kwota_kredytu",
  "Oszczednosci", "Zatrudnienie", "Rata_procent", "Status_osobisty", "Inni_gwaranci",
  "Czas_mieszkania", "Wlasnosc", "Wiek", "Inne_plany_ratalne", "Mieszkanie",
  "Liczba_kredytow", "Praca", "Liczba_osob", "Telefon", "Pracownik_zagraniczny",
  "ID1", "ID2", "ID3","ID4", "Class")
#Usuwam zmienne, które nie były opisane
dane <- dane[, !(names(dane) %in% c("ID1", "ID2", "ID3","ID4"))]
summary(dane)
##    Stan_konta     Czas_kredytu  Historia_kredytowa  Cel_kredytu    
##  Min.   :1.000   Min.   : 4.0   Min.   :0.000      Min.   :  2.00  
##  1st Qu.:1.000   1st Qu.:12.0   1st Qu.:2.000      1st Qu.: 14.00  
##  Median :2.000   Median :18.0   Median :2.000      Median : 23.00  
##  Mean   :2.577   Mean   :20.9   Mean   :2.545      Mean   : 32.71  
##  3rd Qu.:4.000   3rd Qu.:24.0   3rd Qu.:4.000      3rd Qu.: 40.00  
##  Max.   :4.000   Max.   :72.0   Max.   :4.000      Max.   :184.00  
##  Kwota_kredytu    Oszczednosci    Zatrudnienie    Rata_procent  
##  Min.   :1.000   Min.   :1.000   Min.   :1.000   Min.   :1.000  
##  1st Qu.:1.000   1st Qu.:3.000   1st Qu.:2.000   1st Qu.:2.000  
##  Median :1.000   Median :3.000   Median :3.000   Median :3.000  
##  Mean   :2.105   Mean   :3.384   Mean   :2.682   Mean   :2.845  
##  3rd Qu.:3.000   3rd Qu.:5.000   3rd Qu.:3.000   3rd Qu.:4.000  
##  Max.   :5.000   Max.   :5.000   Max.   :4.000   Max.   :4.000  
##  Status_osobisty Inni_gwaranci   Czas_mieszkania    Wlasnosc    
##  Min.   :1.000   Min.   :19.00   Min.   :1.000   Min.   :1.000  
##  1st Qu.:1.000   1st Qu.:27.00   1st Qu.:3.000   1st Qu.:1.000  
##  Median :2.000   Median :33.00   Median :3.000   Median :1.000  
##  Mean   :2.358   Mean   :35.55   Mean   :2.675   Mean   :1.407  
##  3rd Qu.:3.000   3rd Qu.:42.00   3rd Qu.:3.000   3rd Qu.:2.000  
##  Max.   :4.000   Max.   :75.00   Max.   :3.000   Max.   :4.000  
##       Wiek       Inne_plany_ratalne   Mieszkanie    Liczba_kredytow
##  Min.   :1.000   Min.   :1.000      Min.   :1.000   Min.   :0.000  
##  1st Qu.:1.000   1st Qu.:1.000      1st Qu.:1.000   1st Qu.:0.000  
##  Median :1.000   Median :1.000      Median :1.000   Median :0.000  
##  Mean   :1.155   Mean   :1.404      Mean   :1.037   Mean   :0.234  
##  3rd Qu.:1.000   3rd Qu.:2.000      3rd Qu.:1.000   3rd Qu.:0.000  
##  Max.   :2.000   Max.   :2.000      Max.   :2.000   Max.   :1.000  
##      Praca        Liczba_osob       Telefon      Pracownik_zagraniczny
##  Min.   :0.000   Min.   :0.000   Min.   :0.000   Min.   :0.000        
##  1st Qu.:0.000   1st Qu.:1.000   1st Qu.:0.000   1st Qu.:0.000        
##  Median :0.000   Median :1.000   Median :0.000   Median :0.000        
##  Mean   :0.103   Mean   :0.907   Mean   :0.041   Mean   :0.179        
##  3rd Qu.:0.000   3rd Qu.:1.000   3rd Qu.:0.000   3rd Qu.:0.000        
##  Max.   :1.000   Max.   :1.000   Max.   :1.000   Max.   :1.000        
##      Class    
##  Min.   :1.0  
##  1st Qu.:1.0  
##  Median :1.0  
##  Mean   :1.3  
##  3rd Qu.:2.0  
##  Max.   :2.0
#Sprawdzam czy są braki:
sum(is.na(dane))
## [1] 0
#Nie ma
#Przekształcenia wartości ostatniej zmiennej
dane$Class <- ifelse(dane$Class == 1, 0, 1)
#Ustawiam ziarno z nr indeksu
set.seed(145290)
#Losowy podział zbioru na zbiory: uczący, walidacyjny i testowy w proporcjach odpowiednio 40%, 30% i 30%

n <- nrow(dane)

indeksy <- sample(1:n)

#Określenie liczby wierszy w poszczególnych zbiorach
n_uczacy  <- floor(0.4 * n)
n_walidacyjny <- floor(0.3 * n)
n_testowy  <- n - n_uczacy - n_walidacyjny

#Wyznaczenie indeksów dla każdego zbioru
uczacy_idx       <- indeksy[1:n_uczacy]
walidacyjny_idx  <- indeksy[(n_uczacy + 1):(n_uczacy + n_walidacyjny)]
testowy_idx      <- indeksy[(n_uczacy + n_walidacyjny + 1):n]

#Tworzenie zbiorów
uczacy      <- dane[uczacy_idx, ]
walidacyjny <- dane[walidacyjny_idx, ]
testowy     <- dane[testowy_idx, ]

dim(uczacy)
## [1] 400  21
dim(walidacyjny)
## [1] 300  21
dim(testowy)
## [1] 300  21
#Budowa modeli:

# Model 1
model1 <- glm(Class ~ Czas_kredytu + Kwota_kredytu + Rata_procent + Wiek + Liczba_kredytow, data = uczacy, family = binomial)

summary(model1)
## 
## Call:
## glm(formula = Class ~ Czas_kredytu + Kwota_kredytu + Rata_procent + 
##     Wiek + Liczba_kredytow, family = binomial, data = uczacy)
## 
## Coefficients:
##                  Estimate Std. Error z value Pr(>|z|)    
## (Intercept)     -1.103279   0.526525  -2.095 0.036136 *  
## Czas_kredytu     0.033451   0.009748   3.432 0.000600 ***
## Kwota_kredytu   -0.287775   0.080708  -3.566 0.000363 ***
## Rata_procent    -0.093258   0.102224  -0.912 0.361613    
## Wiek             0.197074   0.314150   0.627 0.530446    
## Liczba_kredytow  0.651339   0.251936   2.585 0.009729 ** 
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 493.67  on 399  degrees of freedom
## Residual deviance: 461.40  on 394  degrees of freedom
## AIC: 473.4
## 
## Number of Fisher Scoring iterations: 4
# Model 2
model2 <- glm(Class ~ Stan_konta + Historia_kredytowa + Cel_kredytu + Zatrudnienie + Kwota_kredytu, data = uczacy, family = binomial)

summary(model2)
## 
## Call:
## glm(formula = Class ~ Stan_konta + Historia_kredytowa + Cel_kredytu + 
##     Zatrudnienie + Kwota_kredytu, family = binomial, data = uczacy)
## 
## Coefficients:
##                     Estimate Std. Error z value Pr(>|z|)    
## (Intercept)         1.658058   0.587015   2.825  0.00473 ** 
## Stan_konta         -0.575667   0.102573  -5.612    2e-08 ***
## Historia_kredytowa -0.380274   0.121177  -3.138  0.00170 ** 
## Cel_kredytu         0.010937   0.004307   2.540  0.01110 *  
## Zatrudnienie       -0.038831   0.173459  -0.224  0.82286    
## Kwota_kredytu      -0.218692   0.083110  -2.631  0.00850 ** 
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 493.67  on 399  degrees of freedom
## Residual deviance: 416.72  on 394  degrees of freedom
## AIC: 428.72
## 
## Number of Fisher Scoring iterations: 4
#W modulu 1 Rata_procent i Wiek są niesitotne statystycznie, a w modelu 2 Zatrudnienie
#Budowa modeli - usunięcie z nich zmiennych nieistotnych statystycznie:

# Model 1
model1 <- glm(Class ~ Czas_kredytu + Kwota_kredytu  + Liczba_kredytow, data = uczacy, family = binomial)

summary(model1)
## 
## Call:
## glm(formula = Class ~ Czas_kredytu + Kwota_kredytu + Liczba_kredytow, 
##     family = binomial, data = uczacy)
## 
## Coefficients:
##                 Estimate Std. Error z value Pr(>|z|)    
## (Intercept)     -1.12106    0.29338  -3.821 0.000133 ***
## Czas_kredytu     0.03267    0.00972   3.361 0.000776 ***
## Kwota_kredytu   -0.29130    0.08056  -3.616 0.000299 ***
## Liczba_kredytow  0.65131    0.25069   2.598 0.009374 ** 
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 493.67  on 399  degrees of freedom
## Residual deviance: 462.55  on 396  degrees of freedom
## AIC: 470.55
## 
## Number of Fisher Scoring iterations: 4
# Model 2
model2 <- glm(Class ~ Stan_konta + Historia_kredytowa + Cel_kredytu  + Kwota_kredytu, data = uczacy, family = binomial)

summary(model2)
## 
## Call:
## glm(formula = Class ~ Stan_konta + Historia_kredytowa + Cel_kredytu + 
##     Kwota_kredytu, family = binomial, data = uczacy)
## 
## Coefficients:
##                     Estimate Std. Error z value Pr(>|z|)    
## (Intercept)         1.563069   0.404839   3.861 0.000113 ***
## Stan_konta         -0.575430   0.102515  -5.613 1.99e-08 ***
## Historia_kredytowa -0.383632   0.120295  -3.189 0.001427 ** 
## Cel_kredytu         0.010966   0.004306   2.547 0.010874 *  
## Kwota_kredytu      -0.219355   0.083074  -2.640 0.008279 ** 
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 493.67  on 399  degrees of freedom
## Residual deviance: 416.77  on 395  degrees of freedom
## AIC: 426.77
## 
## Number of Fisher Scoring iterations: 4
#Prezentacja zdolności predykcyjnej modeli na zbiorze uczącym i walidacyjnym

#Model 1
prob_uczacy_m1    <- predict(model1, newdata = uczacy, type = "response")
prob_walidacyjny_m1 <- predict(model1, newdata = walidacyjny, type = "response")

#Model 2
prob_uczacy_m2    <- predict(model2, newdata = uczacy, type = "response")
prob_walidacyjny_m2 <- predict(model2, newdata = walidacyjny, type = "response")

#ROC dla modelu 1
roc_uczacy_m1 <- roc(uczacy$Class, prob_uczacy_m1)
## Setting levels: control = 0, case = 1
## Setting direction: controls < cases
roc_walidacyjny_m1 <- roc(walidacyjny$Class, prob_walidacyjny_m1)
## Setting levels: control = 0, case = 1
## Setting direction: controls < cases
#ROC dla modelu 2
roc_uczacy_m2 <- roc(uczacy$Class, prob_uczacy_m2)
## Setting levels: control = 0, case = 1
## Setting direction: controls < cases
roc_walidacyjny_m2 <- roc(walidacyjny$Class, prob_walidacyjny_m2)
## Setting levels: control = 0, case = 1
## Setting direction: controls < cases
#AUC
auc(roc_uczacy_m1)
## Area under the curve: 0.6689
auc(roc_walidacyjny_m1)
## Area under the curve: 0.6701
auc(roc_uczacy_m2)
## Area under the curve: 0.7634
auc(roc_walidacyjny_m2)
## Area under the curve: 0.7565
#ROC-wykres porównawczy dla zbioru uczącego model1
plot(roc_uczacy_m1, col = "blue", lwd = 2, main = "ROC – Zbiór uczący")
lines(roc_uczacy_m2, col = "red", lwd = 2)
legend("bottomright", legend = c("Model 1", "Model 2"), col = c("blue", "red"), lwd = 2)

#ROC-wykres porównawczy dla zbioru walidacyjnego model2
plot(roc_walidacyjny_m1, col = "blue", lwd = 2, main = "ROC – Zbiór walidacyjny")
lines(roc_walidacyjny_m2, col = "red", lwd = 2)
legend("bottomright", legend = c("Model 1", "Model 2"), col = c("blue", "red"), lwd = 2)

#KOM: Model 2 ma wyraźnie lepszą zdolność predykcyjną!

#Porównanie zbioru uczącego i walidacyjnego dla obu modeli:

#ROC dla Modelu 1 uczący/walidacyjny
plot(roc_uczacy_m1, col = "blue", lwd = 2, main = "ROC Model 1 – Uczący vs Walidacyjny")
lines(roc_walidacyjny_m1, col = "green", lwd = 2)
legend("bottomright",
       legend = c("Zbiór uczący", "Zbiór walidacyjny"),
       col = c("blue", "green"),
       lwd = 2)

#ROC dla Modelu 2 uczący/walidacyjny
plot(roc_uczacy_m2, col = "red", lwd = 2, main = "ROC Model 2 – Uczący vs Walidacyjny")
lines(roc_walidacyjny_m2, col = "orange", lwd = 2)
legend("bottomright",
       legend = c("Zbiór uczący", "Zbiór walidacyjny"),
       col = c("red", "orange"),
       lwd = 2)

#Prezentacja zdolności predykcyjnej najlepszego moidelu (modelu2) na zbiorze walidacyjnym i testowym

prob_testowy_m2     <- predict(model2, newdata = testowy, type = "response")

#ROC dla testowego
roc_testowy_m2     <- roc(testowy$Class, prob_testowy_m2)
## Setting levels: control = 0, case = 1
## Setting direction: controls < cases
#AUC dla testowego i walidacyjnego
auc_testowy_m2     <- auc(roc_testowy_m2)
auc_walidacyjny_m2 <- auc(roc_walidacyjny_m2)

auc(roc_testowy_m2)
## Area under the curve: 0.7768
auc(roc_walidacyjny_m2)
## Area under the curve: 0.7565
#Wykres ROC dla Modelu 2 testowy/walidacyjny
plot(roc_walidacyjny_m2, col = "blue", lwd = 2, main = "ROC – Model 2 (Walidacyjny vs Testowy)")
lines(roc_testowy_m2, col = "red", lwd = 2)
legend("bottomright",
       legend = c(paste("Walidacyjny (AUC =", round(auc_walidacyjny_m2,4), ")"),paste("Testowy (AUC =", round(auc_testowy_m2,4), ")")),
       col = c("blue","red"),
       lwd = 2)

#Krzywa kosztów złych decyzji

#Parametry
koszt_FP <- 150
koszt_FN <- 1000

#Progi odcięcia
progi <- seq(0.5, 0.9, by = 0.01)

#Predykcje prawdopodobieństwa na zbiorze walidacyjnym
prawd_walidacyjny <- predict(model2, newdata = walidacyjny, type = "response")
prawdziwa_klasa   <- walidacyjny$Class

#Funkcja do obliczania kosztu
koszt_calkowity <- sapply(progi, function(prog){
  pred_klasa <- ifelse(prawd_walidacyjny >= prog, 1, 0)
  FP <- sum(pred_klasa == 1 & prawdziwa_klasa == 0)
  FN <- sum(pred_klasa == 0 & prawdziwa_klasa == 1)
  koszt <- FP * koszt_FP + FN * koszt_FN
  return(koszt)
})

#Wykresu
plot(progi, koszt_calkowity, type = "l", col = "darkred", lwd = 2,
     xlab = "Próg odcięcia", ylab = "Koszt złych decyzji [PLN]",
     main = "Krzywa kosztów złych decyzji – Model 2 (Walidacyjny)")
grid()

#Optymalny próg odcięcia, dla którego koszty złych decyzji będą najniższe.

#Znalezienie
min_koszt <- min(koszt_calkowity)
optymalny_prog <- progi[which.min(koszt_calkowity)]

#Wyniku
cat("Minimalny koszt złych decyzji:", min_koszt, "PLN\n")
## Minimalny koszt złych decyzji: 54600 PLN
cat("Optymalny próg odcięcia:", optymalny_prog, "\n")
## Optymalny próg odcięcia: 0.52
#Wykres
plot(progi, koszt_calkowity, type = "l", col = "darkred", lwd = 2,
     xlab = "Próg odcięcia", ylab = "Koszt złych decyzji [PLN]",
     main = "Krzywa kosztów złych decyzji – Model 2 (Walidacyjny)")
grid()
abline(v = optymalny_prog, col = "blue", lwd = 2, lty = 2)
text(optymalny_prog, min_koszt + 1000, paste("Optymalny próg =", round(optymalny_prog,2)), col="blue")

#Predykcje prawdopodobieństwa na zbiorze testowym dla najlepszego modelu (model2)
prawd_testowy <- predict(model2, newdata = testowy, type = "response")
prawdziwa_klasa_test <- testowy$Class

#Przypisanie klas według progu
pred_klasa_test <- ifelse(prawd_testowy >= optymalny_prog, 1, 0)

#Obliczenie liczby FP i FN
FP <- sum(pred_klasa_test == 1 & prawdziwa_klasa_test == 0)
FN <- sum(pred_klasa_test == 0 & prawdziwa_klasa_test == 1)

#Całkowity koszt
koszt_calkowity_test <- FP * koszt_FP + FN * koszt_FN

#Wyniki
cat("Koszt złych decyzji na zbiorze testowym przy progu", optymalny_prog, ":", koszt_calkowity_test, "PLN\n")
## Koszt złych decyzji na zbiorze testowym przy progu 0.52 : 57150 PLN
cat("Liczba fałszywych pozytywów (FP):", FP, "\n")
## Liczba fałszywych pozytywów (FP): 21
cat("Liczba fałszywych negatywów (FN):", FN, "\n")
## Liczba fałszywych negatywów (FN): 54