Përdorimi i Tidymodels
për të analizuar të dhënat dhe për të parashikuar se kush i mbijetoi tragjedisë së Titanikut
Të dhënat e Titanikut janë një zgjedhje popullore midis shkencëtarëve të të dhënave dhe praktikuesve të mësimit të makinerive, që përmban informacione rreth pasagjerëve në udhëtimin fatkeq, si demografia e tyre, klasa e biletave dhe statusi i mbijetesës. Duke përdorur algoritme të ndryshme klasifikimi dhe kornizën e modeleve të rregullta, përpiqem të parashikoj mbijetesën e pasagjerëve në Titanikun.
Prezantimi
Rreth të dhënave
Të dhënat e testit përmban informacionin e mëposhtëm
klasa: Një përfaqësues për statusin socio-ekonomik (SES)
- 1 = e sipërme
- 2 = e mesme
- 3 = e poshtme
mosha: Mosha është e pjesshme nëse është më pak se 1. Nëse mosha vlerësohet, a është në formën e xx.5
sibsp: grupi i të dhënave përcakton marrëdhëniet familjare në këtë mënyrë…
Vëllai/vëllai = vëllai, motra, njerku, njerka
Bashkëshorti = burri, gruaja (të dashurat dhe të fejuarit u injoruan)
parch: grupi i të dhënave përcakton marrëdhëniet familjare në këtë mënyrë…
- Prindi = nëna, babai
- Fëmija = vajza, djali, njerka, njerku
Disa fëmijë udhëtuan vetëm me dado, pra parch=0 per to.
Ngarkimi i paketave
Ngarkimi i paketave të nevojshme për analizën. Paketa tidymodels
përdoret për të ndërtuar modelet e klasifikimit, dhe paketa discrim
përdoret për analizën e diskriminimit linear. Paketa skimr
përdoret për të ofruar një përmbledhje të grupit të të dhënave. Paketa knitr
përdoret për të gjeneruar raportin, dhe për funksionin kable
për të shfaqur grupin e të dhënave. Paketa tidyverse
përdoret për grindje dhe vizualizim të të dhënave, dhe paketa hrbrthemes
përdoret për temën e komploteve për t'i bërë ato më të këndshme estetikisht.
suppressPackageStartupMessages({ library(tidyverse) library(skimr) library(knitr) library(tidymodels) library(discrim) })
Analiza e të dhënave eksploruese
Kaggle ofron një grup të dhënash trajnimi dhe një grup të dhënash testimi. Të dhënat e trajnimit përdoren për të ndërtuar modelet e klasifikimit dhe grupi i të dhënave testuese përdoret për të vlerësuar performancën e modeleve. Të dhënat e trajnimit përmban 891 vëzhgime dhe 12 atribute, ndërsa grupi i të dhënave testuese përmban 418 vëzhgime dhe 11 atribute. Të dhënat e testimit i mungon atributi i mbijetesës, i cili është variabli i synuar për analizën.
Ngarkimi i të dhënave
training_data <- read_csv("data/train.csv") Rows: 891 Columns: 12 ── Column specification ──────────────────────────────────────────────────────── Delimiter: "," chr (5): Name, Sex, Ticket, Cabin, Embarked dbl (7): PassengerId, Survived, Pclass, Age, SibSp, Parch, Fare ℹ Use `spec()` to retrieve the full column specification for this data. ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message. testing_data <- read_csv("data/test.csv") Rows: 418 Columns: 11 ── Column specification ──────────────────────────────────────────────────────── Delimiter: "," chr (5): Name, Sex, Ticket, Cabin, Embarked dbl (6): PassengerId, Pclass, Age, SibSp, Parch, Fare ℹ Use `spec()` to retrieve the full column specification for this data. ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
Le të hedhim një vështrim në rreshtat e parë të grupit të të dhënave të trajnimit.
kable(training_data |> head(5))
Duke përdorur paketën skimr
, mund të marrim një përmbledhje të grupit të të dhënave dhe atributeve.
skim(training_data)
Të dhënat përmbajnë atribute të ndryshme që kanë të bëjnë me pasagjerët në bordin e anijes në momentin e fundosjes. Objektivi i kësaj analize është të identifikojë se cilat atribute janë më të rëndësishme në përcaktimin e mbijetesës së pasagjerëve.
Pas inspektimit fillestar, disa atribute duket se janë më pak informuese në parashikimin e mbijetesës së pasagjerëve. Për shembull, atributi i ID-së së pasagjerit është arbitrar dhe nuk ofron ndonjë pasqyrë mbi rezultatin, dhe kështu mund të hiqet nga analiza. Në mënyrë të ngjashme, atributi i numrit të biletës nuk duket se ka ndonjë rëndësi në lidhje me mbijetesën e pasagjerëve, kështu që ai gjithashtu mund të hiqet. Megjithatë, atributi i emrit mund të sigurojë potencialisht informacion mbi demografinë si seksi, fisnikëria ose titulli, dhe kështu mund të jetë e nevojshme analiza e mëtejshme përpara se të vendoset për të hequr këtë atribut.
Për më tepër, grupi i të dhënave përmban disa atribute me vlera që mungojnë, si numri i kabinës dhe atributet e moshës. Këto atribute duhet të pastrohen dhe të përpunohen paraprakisht përpara përdorimit në ndërtimin e modelit. Meqenëse modelet e klasifikimit priren të performojnë më mirë me atributet e faktorit, atribute të caktuara si Pclass, SibSp, Fare, Embarked dhe Parch duhet të konvertohen në faktorë sipas nevojës.
Lufta dhe Konvertimi i të Dhënave
Kolona që përfaqëson moshën e pasagjerit në grupin e të dhënave përmban një sasi të konsiderueshme vlerash që mungojnë. Ndërsa përdorimi i metodave më të avancuara për imputimin e këtyre vlerave, si regresioni ose interpolimi, ka të ngjarë të japë rezultate më të sakta, për qëllimet e kësaj analize dhe paraqitjeje, vlera mesatare për moshën do të përdoret si zëvendësim për të dhënat që mungojnë.
Kombinimi i grupeve të të dhënave të trajnimit dhe testimit do të lejojë një analizë më të fortë të të dhënave, si dhe një imputim më të saktë të vlerave që mungojnë. Kjo do të lejojë gjithashtu heqjen e atributit "Emri", i cili do të bëhet në hapin tjetër. Atributet “PassengerId” dhe “Ticket” do të hiqen gjithashtu, pasi ato nuk japin ndonjë informacion të dobishëm për analizën. Atributi "Cabin" gjithashtu do të hiqet tani për tani, pasi përmban një sasi të konsiderueshme vlerash që mungojnë dhe do të kërkohet analizë e mëtejshme për të përcaktuar nëse ky atribut mund të përdoret në analizë.
training_data <- training_data |> mutate(group = 'training') testing_data <- testing_data |> mutate(group = 'testing') combined_data <- bind_rows(training_data, testing_data) combined_data <- combined_data |> select(-c(Name, PassengerId, Ticket,Cabin)) glimpse(combined_data) Rows: 1,309 Columns: 9 $ Survived <dbl> 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0… $ Pclass <dbl> 3, 1, 3, 1, 3, 3, 1, 3, 3, 2, 3, 1, 3, 3, 3, 2, 3, 2, 3, 3, 2… $ Sex <chr> "male", "female", "female", "female", "male", "male", "male",… $ Age <dbl> 22, 38, 26, 35, 35, NA, 54, 2, 27, 14, 4, 58, 20, 39, 14, 55,… $ SibSp <dbl> 1, 1, 0, 1, 0, 0, 0, 3, 0, 1, 1, 0, 0, 1, 0, 0, 4, 0, 1, 0, 0… $ Parch <dbl> 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 1, 0, 0, 5, 0, 0, 1, 0, 0, 0, 0… $ Fare <dbl> 7.2500, 71.2833, 7.9250, 53.1000, 8.0500, 8.4583, 51.8625, 21… $ Embarked <chr> "S", "C", "S", "S", "S", "Q", "S", "S", "S", "C", "S", "S", "… $ group <chr> "training", "training", "training", "training", "training", "…
Më pas do të imponojmë vlerat që mungojnë në atributin "Mosha". Kodi i mëposhtëm do të zëvendësojë vlerat që mungojnë në atributin "Mosha" me vlerën mesatare për atributin.
combined_data$Age[is.na(combined_data$Age)] <- mean(combined_data$Age,na.rm=T) sum(is.na(combined_data$Age)) [1] 0
Hapi tjetër në analizë është konvertimi i variablave "mbijetuar", "seks", "SibSp" dhe "Embarked" nga llojet e tyre origjinale të të dhënave në faktorë. Kjo do të lehtësojë manipulimin dhe analizën e këtyre variablave kategorike.
combined_data <- combined_data |> mutate(Survived = as.factor(Survived), Sex = as.factor(Sex), Embarked = as.factor(Embarked)) glimpse(combined_data) glimpse(combined_data) Rows: 1,309 Columns: 9 $ Survived <fct> 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0… $ Pclass <dbl> 3, 1, 3, 1, 3, 3, 1, 3, 3, 2, 3, 1, 3, 3, 3, 2, 3, 2, 3, 3, 2… $ Sex <fct> male, female, female, female, male, male, male, male, female,… $ Age <dbl> 22.00000, 38.00000, 26.00000, 35.00000, 35.00000, 29.88114, 5… $ SibSp <dbl> 1, 1, 0, 1, 0, 0, 0, 3, 0, 1, 1, 0, 0, 1, 0, 0, 4, 0, 1, 0, 0… $ Parch <dbl> 0, 0, 0, 0, 0, 0, 0, 1, 2, 0, 1, 0, 0, 5, 0, 0, 1, 0, 0, 0, 0… $ Fare <dbl> 7.2500, 71.2833, 7.9250, 53.1000, 8.0500, 8.4583, 51.8625, 21… $ Embarked <fct> S, C, S, S, S, Q, S, S, S, C, S, S, S, S, S, S, Q, S, S, C, S… $ group <chr> "training", "training", "training", "training", "training", "…
E rëndësishme
Kolona e emrit mund të përmbajë potencialisht disa informacione të dobishme që mund të ndihmojnë në përcaktimin e shkallës së mbijetesës, por për këtë raund, unë preferoj të mos e përdor atë.
Deri më tani, kam mbaruar me hapat e para-përpunimit të të dhënave dhe 'inxhinierisë së veçorive' dhe jam gati të ndërtoj modelet që do të doja të provoja për këto të dhëna.
Ndërtesa Model
Duke përdorur paketën TidyModels për të ndërtuar modelet që do të doja të provoja për këto të dhëna. Meqenëse ne po shikojmë kryesisht nëse pasagjerët në Titanic mbijetuan, të dhënat janë kategorike, prandaj, modelet e klasifikimit janë të dobishme. Algoritmet kryesore që do të doja të provoja janë:
- Regresioni logjistik,
- Modelet e klasifikimit të rastësishëm të pyjeve,
- K-Klasifikimi i fqinjëve më të afërt,
- XGBoost,
- Pemët e Vendimit, dhe
- Analiza Diskriminuese Lineare.
Ka disa algoritme të tjera që mund të jenë të dobishëm, por për hir të thjeshtësisë, modelet e lartpërmendura do të kontrollohen kundrejt të dhënave.
Ndarja e të dhënave në Test dhe Train
Qëllimi i kësaj është të vlerësojë performancën e modelit që është trajnuar në grupin e trajnimit, duke e testuar atë në të dhënat e padukshme që është grupi i testimit. Kjo lejon një vlerësim më të saktë të aftësisë së modelit për të përgjithësuar në të dhëna të reja, të padukshme. Për më tepër, duke përdorur një grup të veçantë testimi, ne mund të parandalojmë mbipërshtatjen, e cila ndodh kur një model është trajnuar shumë mirë në grupin e trajnimit dhe performon dobët në të dhënat e reja. Meqenëse tashmë e kemi grupin e trajnimit, për hir të thjeshtësisë, ne mund ta përdorim atë si ndarje të trajnimit.
train <- combined_data |> filter(group == "training") |> mutate( Survived = as.factor(Survived) ) |> select(-group) set.seed(123) split_data <- initial_split(train) titanic_train <- training(split_data) titanic_test <- testing(split_data) set.seed(234) titanic_folds <- vfold_cv(titanic_train, strata = Survived) titanic_folds # 10-fold cross-validation using stratification # A tibble: 10 × 2 splits id <list> <chr> 1 <split [600/68]> Fold01 2 <split [600/68]> Fold02 3 <split [601/67]> Fold03 4 <split [601/67]> Fold04 5 <split [601/67]> Fold05 6 <split [601/67]> Fold06 7 <split [602/66]> Fold07 8 <split [602/66]> Fold08 9 <split [602/66]> Fold09 10 <split [602/66]> Fold10 titanic_formula <- Survived ~ .
Regresioni logjistik
glm_spec <- logistic_reg() |> set_engine("glm") glm_wf <- workflow(titanic_formula, glm_spec) contrl_preds <- control_resamples(save_pred = TRUE) glm_rs <- fit_resamples( glm_wf, resamples = titanic_folds, control = contrl_preds ) collect_metrics(glm_rs) # A tibble: 2 × 6 .metric .estimator mean n std_err .config <chr> <chr> <dbl> <int> <dbl> <chr> 1 accuracy binary 0.815 10 0.0141 Preprocessor1_Model1 2 roc_auc binary 0.855 10 0.0180 Preprocessor1_Model1
K Fqinjët më të afërt
knn_spec <- nearest_neighbor(mode = "classification", weight_func = "rectangular", neighbors = 5) |> set_engine("kknn") knn_wf <- workflow(titanic_formula, knn_spec) knn_rs <- fit_resamples( knn_wf, resamples = titanic_folds, control = contrl_preds ) collect_metrics(knn_rs) # A tibble: 2 × 6 .metric .estimator mean n std_err .config <chr> <chr> <dbl> <int> <dbl> <chr> 1 accuracy binary 0.810 10 0.0121 Preprocessor1_Model1 2 roc_auc binary 0.850 10 0.0160 Preprocessor1_Model1
Pylli i rastësishëm
rf_spec <- rand_forest(mode = "classification", trees = 1000) |> set_engine("ranger") rf_wf <- workflow(titanic_formula, rf_spec) rf_rs <- fit_resamples( rf_wf, resamples = titanic_folds, control = contrl_preds) collect_metrics(rf_rs) # A tibble: 2 × 6 .metric .estimator mean n std_err .config <chr> <chr> <dbl> <int> <dbl> <chr> 1 accuracy binary 0.810 10 0.0150 Preprocessor1_Model1 2 roc_auc binary 0.871 10 0.0190 Preprocessor1_Model1
Pemët e Vendimit
dt_spec <- decision_tree(mode = "classification") |> set_engine("rpart") dt_wf <- workflow(titanic_formula, dt_spec) dt_rs <- fit_resamples( dt_wf, resamples = titanic_folds, control = contrl_preds ) collect_metrics(dt_rs) # A tibble: 2 × 6 .metric .estimator mean n std_err .config <chr> <chr> <dbl> <int> <dbl> <chr> 1 accuracy binary 0.811 10 0.0129 Preprocessor1_Model1 2 roc_auc binary 0.813 10 0.0192 Preprocessor1_Model1
XGBoost
xgb_spec <- boost_tree(mode = "classification") |> set_engine("xgboost") xgb_wf <- workflow(titanic_formula, xgb_spec) xgb_rs <- fit_resamples( xgb_wf, resamples = titanic_folds, control = contrl_preds ) collect_metrics(xgb_rs) # A tibble: 2 × 6 .metric .estimator mean n std_err .config <chr> <chr> <dbl> <int> <dbl> <chr> 1 accuracy binary 0.825 10 0.0163 Preprocessor1_Model1 2 roc_auc binary 0.842 10 0.0253 Preprocessor1_Model1
Analiza Diskriminuese Lineare
lda_spec <- discrim_linear( mode = "classification", engine = "MASS" ) lda_wf <- workflow(titanic_formula, lda_spec) lda_rs <- fit_resamples( lda_wf, resamples = titanic_folds, control = contrl_preds ) collect_metrics(lda_rs) # A tibble: 2 × 6 .metric .estimator mean n std_err .config <chr> <chr> <dbl> <int> <dbl> <chr> 1 accuracy binary 0.804 10 0.0135 Preprocessor1_Model1 2 roc_auc binary 0.853 10 0.0188 Preprocessor1_Model1
Asnjë nga modelet nuk u akordua, por rezultatet janë premtuese për shumë modele. Pemët e vendimit duket se nuk po ecin mirë, por modelet e tjera po shkojnë mirë për xhirimin e parë jo të sintonizuar. Saktësia e modeleve si dhe saktësia janë të gjitha mbi 80% që është një shenjë e mirë.
Krahasimi i modeleve
Krahasimi i modeleve duke përdorur lakoren ROC
bind_rows( collect_predictions(glm_rs) |> mutate(mod = "Logistical Regression"), collect_predictions(knn_rs) |> mutate(mod = "K-Nearest Neighbors"), collect_predictions(rf_rs) |> mutate(mod = "Random Forest"), collect_predictions(dt_rs) |> mutate(mod = "Decision Trees"), collect_predictions(xgb_rs) |> mutate(mod = "XGBoost"), collect_predictions(lda_rs) |> mutate(mod = "Linear Dis")) |> group_by(mod) |> roc_curve(Survived, .pred_0) |> autoplot() + hrbrthemes::theme_ipsum()
Duket sikur modeli i regresionit logjistik është një nga modelet më të mira i bazuar thjesht në kurbën ROC. Pra, për hapin tjetër, unë do të përdor modelin e regresionit logjistik për të parashikuar mbijetesën e pasagjerëve në grupin e të dhënave të testit.
Zgjedhja e modelit
final_fitted <- last_fit(glm_wf, split_data) collect_metrics(final_fitted) # A tibble: 2 × 4 .metric .estimator .estimate .config <chr> <chr> <dbl> <chr> 1 accuracy binary 0.760 Preprocessor1_Model1 2 roc_auc binary 0.837 Preprocessor1_Model1
Parashikimi, Vendosja dhe Dorëzimi
Marrja e modelit përfundimtar të përshtatur dhe përdorimi i tij për të parashikuar mbijetesën e pasagjerëve në grupin e të dhënave të trajnimit si shembull
# predict on the test data final_wf <- extract_workflow(final_fitted) predict(final_wf, titanic_train[59,]) # A tibble: 1 × 1 .pred_class <fct> 1 0 titanic_train[59,] # A tibble: 1 × 8 Survived Pclass Sex Age SibSp Parch Fare Embarked <fct> <dbl> <fct> <dbl> <dbl> <dbl> <dbl> <fct> 1 1 1 male 28 0 0 26.6 S
Tani do të përdor modelin përfundimtar të montuar për të parashikuar mbijetesën e pasagjerëve në grupin e të dhënave të kombinuara që përfshin të dhënat e trajnimit dhe testimit.
final_predict <- predict(final_wf, combined_data) final_predict # A tibble: 1,309 × 1 .pred_class <fct> 1 0 2 1 3 1 4 1 5 0 6 0 7 0 8 0 9 1 10 1 # … with 1,299 more rows
Ne marrim rezultatet, kështu që më pas do t'i kombinojmë rezultatet me të dhënat e testit dhe do t'i shkruajmë në një skedar csv.
konkluzioni
Modeli i regresionit logjistik performoi më së miri me një saktësi prej 0.82 dhe për këtë arsye unë do ta përdor këtë model për të parashikuar mbijetesën e pasagjerëve në grupin e të dhënave të testit.
# combine the final predictions with the test data final_submission <- combined_data %>% mutate(Survived = final_predict$.pred_class) |> filter(group == "testing") submission_file <- final_submission |> mutate(PassengerID = testing_data$PassengerId) #write a csv file write_csv(submission_file, "submission.csv") final_submission # A tibble: 418 × 9 Survived Pclass Sex Age SibSp Parch Fare Embarked group <fct> <dbl> <fct> <dbl> <dbl> <dbl> <dbl> <fct> <chr> 1 0 3 male 34.5 0 0 7.83 Q testing 2 0 3 female 47 1 0 7 S testing 3 0 2 male 62 0 0 9.69 Q testing 4 0 3 male 27 0 0 8.66 S testing 5 1 3 female 22 1 1 12.3 S testing 6 0 3 male 14 0 0 9.22 S testing 7 1 3 female 30 0 0 7.63 Q testing 8 0 2 male 26 1 1 29 S testing 9 1 3 female 18 0 0 7.23 C testing 10 0 3 male 21 2 0 24.2 S testing # … with 408 more rows submission_file # A tibble: 418 × 10 Survived Pclass Sex Age SibSp Parch Fare Embarked group PassengerID <fct> <dbl> <fct> <dbl> <dbl> <dbl> <dbl> <fct> <chr> <dbl> 1 0 3 male 34.5 0 0 7.83 Q testing 892 2 0 3 female 47 1 0 7 S testing 893 3 0 2 male 62 0 0 9.69 Q testing 894 4 0 3 male 27 0 0 8.66 S testing 895 5 1 3 female 22 1 1 12.3 S testing 896 6 0 3 male 14 0 0 9.22 S testing 897 7 1 3 female 30 0 0 7.63 Q testing 898 8 0 2 male 26 1 1 29 S testing 899 9 1 3 female 18 0 0 7.23 C testing 900 10 0 3 male 21 2 0 24.2 S testing 901 # … with 408 more rows
Prodhimi i dosjes së dorëzimit iu dorëzua Kaggle dhe rezultatet ishin:
Për modelin e regresionit logjistik:
Pozicioni i renditjes: 8700, Saktësia: 0,76794
Totali i dorëzimeve: 55,402
Pra, ne jemi në 16% më të lartë, që është një rezultat mjaft i mirë për një përpjekje të parë.
Ne mund ta përmirësojmë modelin duke bërë disa inxhinieri tipare, të cilat unë planifikoj ta bëj në të ardhmen. Mund të provojmë edhe modele të tjera si SVM, Naive Bayes, etj. dhe të shohim se si funksionojnë. dhe ne gjithashtu mund të përpiqemi të rregullojmë hiperparametrat e modeleve për të parë nëse mund të përmirësojmë saktësinë. Modelet që kam përdorur në këtë projekt nuk janë të akorduara, kështu që ka shumë vend për përmirësim. Plus, duke pasur parasysh faktin se grupi i të dhënave është i vogël, ne gjithashtu mund të përpiqemi të përdorim modele të të mësuarit të thellë si rrjetet nervore dhe të shohim se si funksionojnë ato.
Referencat
Disa nga burimet që kam përdorur për të mësuar rreth modeleve të rregullta dhe grupit të të dhënave të Titanic dhe si t'i përdor ato së bashku. Për më tepër, disa nga burimet që përdora për të mësuar rreth grupit të të dhënave të Titanikut, ku autorët përdorën modele të rregullta për të parashikuar mbijetesën e pasagjerëve.
- Tidymodels - "Link"
- Parashikimi i mbijetesës së pasagjerëve të Titanikut duke përdorur modele të rregullta | Niels van der Velden - "Lidhja"
- Tidymodels dhe Titaniku | ditari i të dhënave - "Lidhja"
- Eksperimentimi me mësimin e makinerive në R me modele të rregullta dhe grupin e të dhënave titanik Kaggle | Olivier Gimenez - "Lidhje"
- Sintonizoni XGBoost me modele të rregullta dhe volejboll plazhi #TidyTuesday — Link
- Titaniku - Mësimi i Makinerisë nga Fatkeqësia - "Lidhja"