{"metadata":{"kernelspec":{"name":"ir","display_name":"R","language":"R"},"language_info":{"name":"R","codemirror_mode":"r","pygments_lexer":"r","mimetype":"text/x-r-source","file_extension":".r","version":"4.0.5"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"### In the following R notebook we provide a detailed EDA of the data and fit a generalized linear model (elastic net to be more precise) as a baseline model.\n\n### Table of Contents\n* [Import](#1)\n* [EDA](#2)\n* [Impact of Features on Target](#2b)\n* [Model Fit](#3)\n* [Model Evaluation](#4)\n* [Predict and Submit](#5)","metadata":{}},{"cell_type":"code","source":"# packages\nlibrary(tidyverse)\nlibrary(readr)\nlibrary(corrplot)\nlibrary(naniar) # missing value evaluation\nlibrary(h2o) # machine learning tools","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","_kg_hide-output":true,"execution":{"iopub.status.busy":"2022-08-08T16:50:56.033478Z","iopub.execute_input":"2022-08-08T16:50:56.035662Z","iopub.status.idle":"2022-08-08T16:50:56.056803Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# plot config\noptions(repr.plot.width = 12, repr.plot.height = 6)","metadata":{"execution":{"iopub.status.busy":"2022-08-08T16:50:56.060312Z","iopub.execute_input":"2022-08-08T16:50:56.061988Z","iopub.status.idle":"2022-08-08T16:50:56.075614Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id='1'></a>\n# Import","metadata":{}},{"cell_type":"code","source":"# import training data\nt1 <- Sys.time()\ndf_train <- read.csv('../input/tabular-playground-series-aug-2022/train.csv')\nt2 <- Sys.time()\nprint(t2-t1)\n\ndf_train$id <- as.factor(df_train$id)\ndf_train$product_code <- as.factor(df_train$product_code)\n\n# import test set\nt1 <- Sys.time()\ndf_test  <- read.csv('../input/tabular-playground-series-aug-2022/test.csv')\nt2 <- Sys.time()\nprint(t2-t1)\n\ndf_test$id <- as.factor(df_test$id)\ndf_test$product_code <- as.factor(df_test$product_code)\n\n# import submission template\ndf_sub <- read.csv('../input/tabular-playground-series-aug-2022/sample_submission.csv')","metadata":{"execution":{"iopub.status.busy":"2022-08-08T16:50:56.079367Z","iopub.execute_input":"2022-08-08T16:50:56.081132Z","iopub.status.idle":"2022-08-08T16:50:56.740388Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id='2'></a>\n# EDA","metadata":{}},{"cell_type":"code","source":"# overview of data frame\nstr(df_train)","metadata":{"execution":{"iopub.status.busy":"2022-08-08T16:50:56.742735Z","iopub.execute_input":"2022-08-08T16:50:56.744135Z","iopub.status.idle":"2022-08-08T16:50:56.778178Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"n_train = nrow(df_train)\nn_test = nrow(df_test)\n\ncat('Size training data :', n_train, '\\n')\ncat('Size test data     :', n_test, '\\n')","metadata":{"execution":{"iopub.status.busy":"2022-08-08T16:50:56.780554Z","iopub.execute_input":"2022-08-08T16:50:56.781900Z","iopub.status.idle":"2022-08-08T16:50:56.804735Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# look at product code\nsummary(df_train$product_code)\nsummary(df_test$product_code)","metadata":{"execution":{"iopub.status.busy":"2022-08-08T16:50:56.808946Z","iopub.execute_input":"2022-08-08T16:50:56.811023Z","iopub.status.idle":"2022-08-08T16:50:56.837004Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### => Product code cannot be used as there are no common levels in test and train.","metadata":{}},{"cell_type":"markdown","source":"### Categorical Features:","metadata":{}},{"cell_type":"code","source":"# categorical features\nfeatures_cat <- paste0('attribute_',0:3)\nfeatures_cat","metadata":{"execution":{"iopub.status.busy":"2022-08-08T16:50:56.840369Z","iopub.execute_input":"2022-08-08T16:50:56.841978Z","iopub.status.idle":"2022-08-08T16:50:56.864485Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# plots for categorical features\nfor (f in features_cat) {\n    df_train[,f] <- as.factor(df_train[,f])\n    df_test[,f] <- as.factor(df_test[,f])\n    par(mfrow=c(1,2)) \n    plot(df_train[,f], col='blue', main=paste0(f, ' - train')); grid()\n    plot(df_test[,f], col='darkgreen', main=paste0(f, ' - test')); grid()\n    par(mfrow=c(1,1)) \n}","metadata":{"execution":{"iopub.status.busy":"2022-08-08T16:50:56.866960Z","iopub.execute_input":"2022-08-08T16:50:56.868389Z","iopub.status.idle":"2022-08-08T16:50:57.379590Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### => We see big differences between train and test set here!","metadata":{}},{"cell_type":"code","source":"# basic stats - train\nsummary(df_train[features_cat])","metadata":{"execution":{"iopub.status.busy":"2022-08-08T16:50:57.381973Z","iopub.execute_input":"2022-08-08T16:50:57.383431Z","iopub.status.idle":"2022-08-08T16:50:57.402366Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# basic stats - test\nsummary(df_test[features_cat])","metadata":{"execution":{"iopub.status.busy":"2022-08-08T16:50:57.404748Z","iopub.execute_input":"2022-08-08T16:50:57.406169Z","iopub.status.idle":"2022-08-08T16:50:57.426369Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Numerical Features:","metadata":{}},{"cell_type":"code","source":"features_num <- 'loading'\nfeatures_num <- c(features_num, paste0('measurement_',0:17))\n\nsummary(df_train[features_num])","metadata":{"execution":{"iopub.status.busy":"2022-08-08T16:50:57.430025Z","iopub.execute_input":"2022-08-08T16:50:57.431854Z","iopub.status.idle":"2022-08-08T16:50:57.491085Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"summary(df_test[features_num])","metadata":{"execution":{"iopub.status.busy":"2022-08-08T16:50:57.493581Z","iopub.execute_input":"2022-08-08T16:50:57.495014Z","iopub.status.idle":"2022-08-08T16:50:57.538686Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### => We observe a lot of missing values in the numerical columns!","metadata":{}},{"cell_type":"code","source":"# plots for numerical features\nfor (f in features_num) {\n    par(mfrow=c(1,2))\n    hist(df_train[,f], col='blue', main=paste0(f, ' - train')); grid()\n    hist(df_test[,f], col='darkgreen', main=paste0(f, ' - test')); grid()\n    par(mfrow=c(1,1))\n}","metadata":{"execution":{"iopub.status.busy":"2022-08-08T16:50:57.541173Z","iopub.execute_input":"2022-08-08T16:50:57.542599Z","iopub.status.idle":"2022-08-08T16:50:59.768978Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Numerical Features - Missing Values:","metadata":{}},{"cell_type":"code","source":"# visualize missing values occurrence (training data)\noptions(repr.plot.width = 14, repr.plot.height = 10)\nsuppressWarnings(vis_miss(df_train[features_num]))\noptions(repr.plot.width = 12, repr.plot.height = 6)","metadata":{"execution":{"iopub.status.busy":"2022-08-08T16:50:59.771677Z","iopub.execute_input":"2022-08-08T16:50:59.773299Z","iopub.status.idle":"2022-08-08T16:51:02.504990Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# missing value percentage by column (training data)\nmiss_perc <- round(100 * colSums(is.na(df_train[,features_num])) / n_train, 4)\ncat('Missing Values (Train) in %:\\n\\n')\nprint(miss_perc)\n\n# plot missing value percentage\npar(mar = c(8, 4, 4, 4))\nbarplot(miss_perc, las=2, col='darkred', main='Missing Value Percentage (Train)')\ngrid()","metadata":{"execution":{"iopub.status.busy":"2022-08-08T16:51:02.507636Z","iopub.execute_input":"2022-08-08T16:51:02.509178Z","iopub.status.idle":"2022-08-08T16:51:02.641558Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### Hmm, this looks pretty artificial...","metadata":{}},{"cell_type":"markdown","source":"### Numerical Features - Correlations:","metadata":{}},{"cell_type":"code","source":"# train\ncorrplot::corrplot(cor(df_train[,features_num], use = 'pairwise.complete.obs'))","metadata":{"execution":{"iopub.status.busy":"2022-08-08T16:51:02.644836Z","iopub.execute_input":"2022-08-08T16:51:02.646468Z","iopub.status.idle":"2022-08-08T16:51:02.855920Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# test\ncorrplot::corrplot(cor(df_test[,features_num], use = 'pairwise.complete.obs'))","metadata":{"execution":{"iopub.status.busy":"2022-08-08T16:51:02.859838Z","iopub.execute_input":"2022-08-08T16:51:02.862360Z","iopub.status.idle":"2022-08-08T16:51:03.064908Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Target:","metadata":{}},{"cell_type":"code","source":"df_train$target <- as.factor(df_train$failure)\nplot(df_train$target, main='Target', col='darkorange'); grid()","metadata":{"execution":{"iopub.status.busy":"2022-08-08T16:51:03.067485Z","iopub.execute_input":"2022-08-08T16:51:03.069028Z","iopub.status.idle":"2022-08-08T16:51:03.192929Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id='2b'></a>\n# Impact of Features on Target","metadata":{}},{"cell_type":"markdown","source":"### Categorical Features","metadata":{}},{"cell_type":"code","source":"options(repr.plot.width = 12, repr.plot.height = 5)\nfor (f in features_cat) {\n    # mosaic plot shows percentage of 0/1 target values\n    plot(df_train[,f], df_train$target,\n         ylim=c(0,0.5),\n         main=paste0('Target vs ', f),\n         col=c('blue','lightblue'))\n}\noptions(repr.plot.width = 12, repr.plot.height = 6)","metadata":{"execution":{"iopub.status.busy":"2022-08-08T16:51:03.195304Z","iopub.execute_input":"2022-08-08T16:51:03.196732Z","iopub.status.idle":"2022-08-08T16:51:03.552435Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### Numerical Features","metadata":{}},{"cell_type":"code","source":"options(repr.plot.width = 12, repr.plot.height = 5)\nfor (f in features_num) {\n    # binning using quantiles of each feature\n    qq <- quantile(na.omit(df_train[,f]), seq(0,1,0.1))\n    # mosaic plot shows percentage of 0/1 target values\n    plot(cut(df_train[,f], qq), df_train$target,\n         ylim=c(0,0.5),\n         main=paste0('Target vs ', f),\n         col=c('blue','lightblue'))\n}\noptions(repr.plot.width = 12, repr.plot.height = 6)","metadata":{"execution":{"iopub.status.busy":"2022-08-08T16:51:03.554797Z","iopub.execute_input":"2022-08-08T16:51:03.556139Z","iopub.status.idle":"2022-08-08T16:51:05.331590Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### We can see that \"loading\" has a strong impact on the target (percentage of 1s increases with higher loading). Also \"measurement_17\" shows a trend but much more moderate. ","metadata":{}},{"cell_type":"markdown","source":"<a id='3'></a>\n# Model Fit","metadata":{}},{"cell_type":"code","source":"# define predictors and target variable\npredictors <- c(features_num, features_cat)\ntarget <- 'target'","metadata":{"execution":{"iopub.status.busy":"2022-08-08T16:51:05.335523Z","iopub.execute_input":"2022-08-08T16:51:05.337388Z","iopub.status.idle":"2022-08-08T16:51:05.353410Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# initialize H2O\nh2o.init(ip='localhost', port=54321, max_mem_size = '6G')","metadata":{"_kg_hide-output":true,"execution":{"iopub.status.busy":"2022-08-08T16:51:05.357011Z","iopub.execute_input":"2022-08-08T16:51:05.359200Z","iopub.status.idle":"2022-08-08T16:51:05.462889Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# upload data in H2O environment\ntrain_hex <- as.h2o(df_train[,c(predictors,target)]) # use only necessary columns\ntest_hex <- as.h2o(df_test[,c(predictors)])","metadata":{"execution":{"iopub.status.busy":"2022-08-08T16:51:05.465374Z","iopub.execute_input":"2022-08-08T16:51:05.466839Z","iopub.status.idle":"2022-08-08T16:51:06.693989Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# fit linear model\nfit <- h2o.glm(x=predictors, y=target,\n               training_frame = train_hex,\n               nfolds = 5,\n               seed = 987)","metadata":{"execution":{"iopub.status.busy":"2022-08-08T16:51:06.697927Z","iopub.execute_input":"2022-08-08T16:51:06.700174Z","iopub.status.idle":"2022-08-08T16:51:09.113579Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# show model details\nfit","metadata":{"execution":{"iopub.status.busy":"2022-08-08T16:51:09.115943Z","iopub.execute_input":"2022-08-08T16:51:09.117359Z","iopub.status.idle":"2022-08-08T16:51:09.160897Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id='4'></a>\n# Model Evaluation","metadata":{}},{"cell_type":"code","source":"# AUC on training\ncat('AUC Train:', h2o.auc(fit, train = TRUE), '\\n')\ncat('AUC CV   :', h2o.auc(fit, xval = TRUE), '\\n')","metadata":{"execution":{"iopub.status.busy":"2022-08-08T16:58:53.580774Z","iopub.execute_input":"2022-08-08T16:58:53.582424Z","iopub.status.idle":"2022-08-08T16:58:53.605291Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# ROC curve\noptions(repr.plot.width = 7, repr.plot.height = 7)\nperf <- h2o.performance(fit, newdata = train_hex)\nplot(perf, type='roc', main='ROC Curve - Train')\noptions(repr.plot.width = 12, repr.plot.height = 6)","metadata":{"execution":{"iopub.status.busy":"2022-08-08T17:00:47.607721Z","iopub.execute_input":"2022-08-08T17:00:47.610373Z","iopub.status.idle":"2022-08-08T17:00:47.837381Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# precision/recall curve\noptions(repr.plot.width = 7, repr.plot.height = 7)\nplot(perf, type = 'pr', main='Precision Recall Curve - Train')\noptions(repr.plot.width = 12, repr.plot.height = 6)","metadata":{"execution":{"iopub.status.busy":"2022-08-08T16:59:49.311408Z","iopub.execute_input":"2022-08-08T16:59:49.313875Z","iopub.status.idle":"2022-08-08T16:59:49.427069Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# variable importance\noptions(repr.plot.width = 12, repr.plot.height = 8)\nh2o.varimp_plot(fit,100)\noptions(repr.plot.width = 12, repr.plot.height = 5)","metadata":{"execution":{"iopub.status.busy":"2022-08-08T16:51:09.187253Z","iopub.execute_input":"2022-08-08T16:51:09.188561Z","iopub.status.idle":"2022-08-08T16:51:09.320251Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"<a id='5'></a>\n# Predict and Submit","metadata":{}},{"cell_type":"code","source":"# apply model on train set\npred_train <- as.data.frame(predict(fit, train_hex))\npred_train <- pred_train$p1\nsummary(pred_train)","metadata":{"execution":{"iopub.status.busy":"2022-08-08T16:51:09.322601Z","iopub.execute_input":"2022-08-08T16:51:09.323984Z","iopub.status.idle":"2022-08-08T16:51:09.586441Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"hist(pred_train, n=100, main='Train Set Predictions', col='blue'); grid()","metadata":{"execution":{"iopub.status.busy":"2022-08-08T17:00:04.577019Z","iopub.execute_input":"2022-08-08T17:00:04.578669Z","iopub.status.idle":"2022-08-08T17:00:04.702159Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# apply model on test set\npred_test <- as.data.frame(predict(fit, test_hex))\npred_test <- pred_test$p1\nsummary(pred_test)","metadata":{"execution":{"iopub.status.busy":"2022-08-08T16:51:09.704009Z","iopub.execute_input":"2022-08-08T16:51:09.705475Z","iopub.status.idle":"2022-08-08T16:51:09.930173Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"#### Note that we have levels not trained on.","metadata":{}},{"cell_type":"code","source":"hist(pred_test, n=100, main='Test Set Predictions', col='darkgreen'); grid()","metadata":{"execution":{"iopub.status.busy":"2022-08-08T16:51:09.932497Z","iopub.execute_input":"2022-08-08T16:51:09.933922Z","iopub.status.idle":"2022-08-08T16:51:10.041990Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# submission\ndf_sub$failure <- pred_test\nwrite_delim(df_sub, file='submission.csv', delim=',')","metadata":{"execution":{"iopub.status.busy":"2022-08-08T16:51:10.044283Z","iopub.execute_input":"2022-08-08T16:51:10.045663Z","iopub.status.idle":"2022-08-08T16:51:10.105917Z"},"trusted":true},"execution_count":null,"outputs":[]}]}