Applicazioni pratiche di machine learning/Diagnosi di malattie
Diagnosi di malattie tramite descrizione testuale
[modifica | modifica sorgente]Tramite 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
[modifica | modifica sorgente]Utilizzando 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
[modifica | modifica sorgente]Caricamento librerie
[modifica | modifica sorgente] library(dplyr)
library(ggplot2)
library(caret)
Parte 1: Dati
[modifica | modifica sorgente]Il 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
[modifica | modifica sorgente]Si 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 | modifica sorgente] 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
[modifica | modifica sorgente]Divido 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
[modifica | modifica sorgente]Per 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