Applicazioni pratiche di machine learning/Diagnosi di malattie mentali

Indice del libro

Caricamento librerieModifica

 library(ggplot2)
 library(dplyr)
 library(statsr)
 library(hashmap)

Parte 1 : DatiModifica

Il dataset scaricabile da qui : https://osmihelp.org/research è ricavato da un sondaggio del 2014, che misura le attitudini verso la salute mentale e la frequenza di disturbi mentali in ambienti di lavoro tecnologici. E' costituito da 1259 records contenenti ognuna 27 risposte, confluite nelle seguenti 27 variabili:

  • Timestamp: Data della registrazione
  • Age: Età del rispondente
  • Gender: Sesso
  • Country: Paese del rispondente
  • state: Se vivi negli Stati Uniti, in quale stato o territorio risiedi?
  • self_employed: Sei un lavoratore autonomo ?
  • family_history: Hai una storia familiare di malattia mentale?
  • treatment: Hai cercato un trattamento farmacologico o psicoterapeutico per problemi di salute mentale?
  • work_interfere: Se hai un problema di salute mentale, questo interferisce con il tuo lavoro?
  • no_employees: Quanti impiegati ha la tua azienda o organizzazione?
  • remote_work: Lavori in remoto al di fuori dell'ufficio per almeno il 50% del tempo?
  • tech_company: Il tuo datore di lavoro è principalmente un'azienda oppure un' organizzazione tecnologica?
  • benefits: Il tuo datore di lavoro offre benefits per la salute mentale?
  • care_options: Conosci le possibilità di assistenza per la salute mentale offerte dal tuo datore di lavoro??
  • wellness_program: Il tuo datore di lavoro ha mai discusso di salute mentale nell'ambito di un programma di benessere per i dipendenti?
  • seek_help: il tuo datore di lavoro fornisce risorse per saperne di più sui problemi di salute mentale e su come chiedere aiuto?
  • anonymity: il tuo anonimato è protetto se scegli di utilizzare le risorse per la salute mentale o contro l'abuso di sostanze?
  • leave: quanto è facile per te prendere un congedo medico per un problema di salute mentale??
  • mentalhealthconsequence: Pensi che discutere di un problema di salute mentale con il tuo datore di lavoro avrebbe conseguenze negative?
  • physhealthconsequence: Pensi che discutere di un problema di salute fisica con il tuo datore di lavoro avrebbe conseguenze negative?
  • coworkers: Saresti disposto a discutere di un problema di salute mentale con i tuoi colleghi?
  • supervisor: Saresti disposto a discutere un problema di salute mentale con i tuoi diretti supervisori?
  • mentalhealthinterview: Faresti emergere un problema di salute mentale con un potenziale datore di lavoro in un'intervista?
  • physhealthinterview: faresti emergere un problema di salute fisica con un potenziale datore di lavoro in un'intervista?
  • mentalvsphysical: ritieni che il tuo datore di lavoro prenda in considerazione la salute mentale tanto seriamente quanto la salute fisica?
  • obs_consequence: hai sentito parlare o hai osservato conseguenze negative per i colleghi con problemi di salute mentale sul posto di lavoro?
  • comments: eventuali note o commenti aggiuntivi

Si crea una nuova variabile sex, a partire dalla variabile gender, che può assumere soltanto 3 valori : Maschio, Femmina e Trans .

 male_str <- c("male", "m", "male-ish", "maile", "mal", "male (cis)", "make", "male ", "man","msle", "mail", "malr","cis man") 
 trans_str <- c("trans-female", "something kinda male?", "queer/she/they", "non-binary","nah", "all", "enby", "fluid", "genderqueer", "androgyne", "agender", "male leaning androgynous", "guy (-ish) ^_^", "trans woman", "neuter", "female (trans)", "queer", "ostensibly male, unsure what that really means" ) 
 female_str <- c("cis female", "f", "female", "woman", "femake", "female ","cis-female/femme", "female (cis)", "femail") 

 df <- data.frame(str=male_str,gender="Maschio")
 df <- rbind(df,data.frame(str=trans_str,gender="Trans"))
 df <- rbind(df,data.frame(str=female_str,gender="Femmina"))

 map <-hashmap(as.character(df$str),as.character(df$gender))

 n<-nrow(survey)
 v<- rep(NA,n)

 for (i in 1:n) {
  v[i]<-map[[tolower(survey[i,3])]]
 }

 survey <- cbind(survey,sex=v)


Gestione dei valori mancanti:

 colSums(is.na(survey))
 survey <- survey[-which(is.na(survey$sex)),]
 survey$work_interfere <- as.character(survey$work_interfere)
 survey$work_interfere[is.na(survey$work_interfere)] <- "No"
 survey$work_interfere <- as.factor(survey$work_interfere)


Parte 2 : Domanda di ricercaModifica

Predicendo la variabile treatment a partire dalle variabili family_history, work_interfere e sex si vuole effettuare una diagnosi del disturbo mentale utilizzando come predictors il sesso, se si ha una storia familiare di malattia mentale e se il disagio mentale interferisce con il lavoro, utilizzando l'algoritmo di machine learning Random Forest.

Parte 3 : Esplorazione dei datiModifica

Come si vede dal seguente grafico nel campione il numero di persone in trattamento farmacologico o psicoterapico che hanno una storia familiare di malattia mentale è maggiore di chi è sano mentalmente:

 survey %>%
  ggplot(aes(treatment, fill=family_history))+
  geom_bar()

Come si vede dal seguente grafico nel campione chi ha un problema di salute mentale ha maggiori problemi in ambito lavorativo:


 survey %>%
  filter(!is.na(work_interfere)) %>%
  ggplot(aes(treatment, fill=work_interfere))+
  geom_bar()

Parte 4 : Modellizzazione e diagnosiModifica

Si divide il dataset in un training set con 879 osservazioni ed un testing set con 375 osservazioni . Sul training set si costruisce un modello previsionale per diagnosticare un disturbo mentale a partire dalle variabili sex, work_interfere e family_history, utilizzando l'algoritmo Random Forest e lo si prova sul testing set, ottenendo un'Accuracy nella diagnosi dell'82,67%

 train <- createDataPartition(survey$treatment, p=0.7, list = FALSE)
 training <- survey[train,]
 testing <- survey[-train,]

 model <-  train( treatment ~ sex + family_history + work_interfere, data=training,  method="rf")
 p1 <- predict(model,newdata = testing)
 print(confusionMatrix(p1,testing$treatment))
Confusion Matrix and Statistics
          Reference
Prediction  No Yes
       No  131  10
       Yes  55 179
                                         
              Accuracy : 0.8267          
                95% CI : (0.7845, 0.8636)
   No Information Rate : 0.504           
   P-Value [Acc > NIR] : < 2.2e-16       
                                         
                 Kappa : 0.6526          
                                         
Mcnemar's Test P-Value : 4.828e-08       
                                         
           Sensitivity : 0.7043          
           Specificity : 0.9471          
        Pos Pred Value : 0.9291          
        Neg Pred Value : 0.7650          
            Prevalence : 0.4960          
        Detection Rate : 0.3493          
  Detection Prevalence : 0.3760          
     Balanced Accuracy : 0.8257          
                                         
      'Positive' Class : No   

Esempio di diagnosiModifica

Si prenda ad esempio un uomo con una storia familiare di disagio psichico che interferisce spesso con la vita lavorativa, allora per il modello c'è un problema mentale :

 predict(model,newdata = data.frame(sex="Maschio",family_history="Yes", work_interfere="Often"))
[1] Yes
Levels: No Yes