Applicazioni pratiche di machine learning/Diagnosi di malattie
Diagnosi di malattie tramite descrizione testuale
modificaTramite il modello BERT di classificazione del testo è possibile diagnosticare malattie, descrivendo liberamente la propria sintomatologia. Su HuggingFace al seguente indirizzo : https://huggingface.co/Zabihin/Symptom_to_Diagnosis è possibile digitare in inglese in modo discorsivo i propri sintomi nell'apposita casella di testo, ottenendo varie diagnosi con una certa accuracy in percentuale.
Diagnosi di malattie tramite sintomi
modificaUtilizzando l'algoritmo di machine learning Random Forest è possibile diagnosticare le malattie tramite i loro sintomi con un'Accuracy del 99% . Su HuggingFace al seguente indirizzo : https://huggingface.co/gianlab/random-forest-model-disease-symptom-prediction è possibile scaricare il modello sul proprio PC o su Google Colab, in modo da fare diagnosi mediche attraverso sintomi. Il codice per effettuare tale analisi si trova su Github, come indicato nel suddetto link.
Diagnosi di malattie cardiache
modificaCaricamento librerie
modifica library(dplyr)
library(ggplot2)
library(caret)
Parte 1: Dati
modificaIl dataset "heart.csv" scaricabile da qui : https://archive.ics.uci.edu/ml/datasets/Heart+Disease contiene 303 osservazioni, ciascuna delle quali contiene 14 variabili relative al cuore. Tali variabili sono le seguenti :
- age: l'età della persona in anni
- sex: il sesso della persona (1 = maschio, 0 = femmina)
- cp: dolore toracico sperimentato (1: angina tipica, 2: angina atipica, 3:dolore non anginale, 4: asintomatico)
- trestbps: pressione sanguigna a riposo della persona (mm/Hg al momento del ricovero in ospedale)
- chol: misurazione del colesterolo in mg/dl
- fbs: glicemia a digiuno della persona (> 120 mg/dl, 1 = vero; 0 = falso)
- restecg: elettrocardiogramma a riposo (0 = normale, 1 = con anomalia dell'onda ST-T, 2 = ipertrofia ventricolare sinistra probabile o definita secondo i criteri di Estes)
- thalach: frequenza cardiaca massima raggiunta dalla persona
- exang: angina indotta dall'esercizio (1 = sì; 0 = no)
- oldpeak: depressione ST indotta dall'esercizio ('ST' si riferisce alle posizioni sul diagramma ECG)
- slop: pendenza del segmento ST (valore 1: salita, valore 2: piano, valore 3: discesa)
- ca: numero di vasi principali (0-3)
- tal: disturbo del sangue chiamato talassemia (3 = normale; 6 = difetto fisso; 7 = difetto reversibile)
- target: malattie cardiache (0 = no, 1 = sì)
Caricamento dei dati:
heart <- read.csv("heart.csv")
Ricerca valori mancanti:
colSums(is.na(heart))
age sex cp trestbps chol fbs restecg thalach 0 0 0 0 0 0 0 0 exang oldpeak slope ca thal target 0 0 0 0 0 0
Parte 2 : Domanda di ricerca
modificaSi vuole predire l'eventuale presenza di una malattia cardiaca nel paziente, predicendo la variabile target in base alle 13 suddette variabili.
Parte 3: Esplorazione dei dati
modifica df <- heart
#Traduco le variabili del dataset in italiano:
names(df)<-c("eta","sesso","tipo di dolore toracico","pressione sanguigna a riposo","colesterolo in mg/dl","glicemia a digiuno","elettrocardiogramma a riposo","frequenza cardiaca massima raggiunta","angina indotta dall'esercizio","depressione ST indotta","pendenza del segmento ST","numero di vessels","talassemia","malattia al cuore")
#Rendo più comprensibili i valori delle variabili:
df$sesso[df$sesso==0]="Femmina"
df$sesso[df$sesso==1]="Maschio"
df$sesso=as.factor(df$sesso)
df$`tipo di dolore toracico`[df$`tipo di dolore toracico`==0]="Angina tipica"
df$`tipo di dolore toracico`[df$`tipo di dolore toracico`==1]="Angina atipica"
df$`tipo di dolore toracico`[df$`tipo di dolore toracico`==2]="Dolore non anginale"
df$`tipo di dolore toracico`[df$`tipo di dolore toracico`==3]="Asintomatico"
df$`tipo di dolore toracico`=as.factor(df$`tipo di dolore toracico`)
df$`glicemia a digiuno`[df$`glicemia a digiuno`==0] ="minore di 120 mg/ml"
df$`glicemia a digiuno`[df$`glicemia a digiuno`==1] ="maggiore di 120 mg/ml"
df$`glicemia a digiuno`=as.factor(df$`glicemia a digiuno`)
df$`elettrocardiogramma a riposo`[df$`elettrocardiogramma a riposo`==0]="Normale"
df$`elettrocardiogramma a riposo`[df$`elettrocardiogramma a riposo`==1]="con anomalia dell'onda ST-T"
df$`elettrocardiogramma a riposo`[df$`elettrocardiogramma a riposo`==2]="Ipertrofia ventricolare sinistra"
df$`elettrocardiogramma a riposo`= as.factor(df$`elettrocardiogramma a riposo`)
df$`malattia al cuore`[df$`malattia al cuore`==0]="No"
df$`malattia al cuore`[df$`malattia al cuore`==1]="Si"
Visualizzo informazioni sulle variabili numeriche come min, max, media, mediana, 1°quartile, 3° quartile ecc e per le variabili categoriche il numero di elementi di ciascun livello:
summary(df)
Alcuni grafici relativi al campione :
df %>%
ggplot(aes(`pressione sanguigna a riposo`, fill=`malattia al cuore`))+
geom_histogram(binwidth = 10, colour="gray")
df %>%
ggplot(aes(`colesterolo in mg/dl`, fill=`malattia al cuore`))+
geom_histogram(binwidth = 10, colour="gray")
df %>%
ggplot(aes(`tipo di dolore toracico`, fill=`malattia al cuore`))+
geom_bar()
Parte 4: Modellizzazione e previsione
modificaDivido il dataset heart in un training set costituito dal 70% delle osservazioni casuali, ottenendo 213 osservazioni, ed in un testing set costituito dalle rimanenti 90 osservazioni:
train <- createDataPartition(heart$target,p=0.7,list = FALSE)
training <- heart[train,]
testing <- heart[-train,]
training$target <- as.factor(training$target)
testing$target <- as.factor(testing$target)
Utilizzando l'algoritmo Random Forest costruisco un modello previsionale sul training set che mi dà un'Accuracy quasi del 100% e sul testing set un'Accuracy dell'80% per cui il modello così ottenuto, con cui si predice se il paziente ha malattie al cuore oppure no, si può ritenere valido.
model <- train( target ~ .,data=training, method="rf", verbose=FALSE )
p3 <- predict(model,newdata = training)
print(confusionMatrix(p3,training$target))
p3 <- predict(model,newdata = testing)
print(confusionMatrix(p3,testing$target))
Confusion Matrix and Statistics
Reference Prediction 0 1 0 97 0 1 1 115 Accuracy : 0.9953 95% CI : (0.9741, 0.9999) No Information Rate : 0.5399 P-Value [Acc > NIR] : <2e-16 Kappa : 0.9905 Mcnemar's Test P-Value : 1 Sensitivity : 0.9898 Specificity : 1.0000 Pos Pred Value : 1.0000 Neg Pred Value : 0.9914 Prevalence : 0.4601 Detection Rate : 0.4554 Detection Prevalence : 0.4554 Balanced Accuracy : 0.9949 'Positive' Class : 0 Confusion Matrix and Statistics
Reference Prediction 0 1 0 33 11 1 7 39 Accuracy : 0.8 95% CI : (0.7025, 0.8769) No Information Rate : 0.5556 P-Value [Acc > NIR] : 1.034e-06 Kappa : 0.599 Mcnemar's Test P-Value : 0.4795 Sensitivity : 0.8250 Specificity : 0.7800 Pos Pred Value : 0.7500 Neg Pred Value : 0.8478 Prevalence : 0.4444 Detection Rate : 0.3667 Detection Prevalence : 0.4889 Balanced Accuracy : 0.8025 'Positive' Class : 0
Esempio di diagnosi
modificaPer un uomo di 37 anni con i dati di seguito indicati il modello fa una diagnosi di malattia al cuore:
predict(model, newdata= data.frame(age=37, sex=1, cp=2, trestbps=130, chol=250, fbs=0, restecg=1, thalach=187, exang=0, oldpeak=3.5, slope=0, ca=0, thal=2))
[1] 1 Levels: 0 1