Applicazioni pratiche di machine learning/Previsione di reati
Caricamento librerie
[modifica | modifica sorgente]library(dplyr)
library(ggplot2)
library(caret)
library(h2o)
Parte 1: Dati
[modifica | modifica sorgente]Il dataset crimes.csv scaricabile da qui : https://www.kaggle.com/AnalyzeBoston/crimes-in-boston contiene 317.751 records relativi a reati forniti dal Dipartimento di Polizia di Boston (BPD) con informazioni su dove e quando essi si sono verificati. Le variabili contenute nel dataset sono le seguenti :
- INCIDENT_NUMBER:Numero interno dell'incidente stabilito da BPD
- OFFENSE_CODE: Codice numerico della descrizione dell'incidente
- OFFENSE_CODE_GROUP: Categoria interna per la descrizione dell'incidente
- OFFENSE_DESCRIPTION:Descrizione primaria dell'incidente
- DISTRICT:Quartiere in cui si è verificato l'incidente
- REPORTING_AREA: Numero RA associato con il luogo in cui si è verificato l'incidente
- SHOOTING:Indica se la registrazione è avvenuta nel luogo del fatto
- OCCURRED_ON_DATE:Giorno e ora in cui l'incidente si è verificato
- YEAR: Anno dell'incidente
- MONTH: Mese dell'incidente
- DAY_OF_WEEK:Giorno della settimana
- HOUR:Ora
- UCR_PART:Uniform Crime Report che può assumere 3 valori (Part 1,Part 2, Part 3).
- Part 1 include crimini violenti e crimini contro il patrimonio. Ad esempio Aggressione aggravata , stupro forzato , omicidio e rapina mentre incendio doloso , furto con scasso , furto e furto di veicoli a motore sono classificati come reati contro il patrimonio.
- Parte 2, vengono incluse le seguenti categorie: aggressione semplice, reati di coprifuoco e vagabondaggio, appropriazione indebita, falsificazione e contraffazione, condotta disordinata, guida sotto l'influenza di droghe, reati di droga, frode, gioco d'azzardo, reati di alcol, reati contro la famiglia, prostituzione, ubriachezza in pubblico, fughe, reati sessuali, beni rubati, atti vandalici, vagabondaggio e reati legati alle armi.
- Parte 3 : Altro
- STREET:Nome della strada in cui l'incidente si è verificato
- Lat: Latitudine del luogo in cui si è verificato l'incidente
- Long: Longitudine
- Location:(Latitudine, Longitudine)
Caricamento dati:
crime <- read.csv("crime.csv")
Parte 2: Esplorazione dati
[modifica | modifica sorgente]crime %>%
filter(!is.na(OFFENSE_CODE_GROUP)) %>%
group_by(OFFENSE_CODE_GROUP) %>%
summarise(n=n()) %>%
filter(n>200) %>%
mutate(OFFENSE_CODE_GROUP=reorder(OFFENSE_CODE_GROUP,n)) %>%
ggplot(aes(OFFENSE_CODE_GROUP,n))+
geom_bar(stat="identity", fill="red")+
coord_flip()+
geom_text(aes(label=n), hjust=0, size=2)+
guides(fill=FALSE)+
ylab("Numero totale") +
xlab("Crimine") +
ggtitle("Tipo di incidenti o reati a Boston")
crime %>%
group_by(STREET) %>%
summarise(n=n()) %>%
filter(n>800) %>%
mutate(STREET=reorder(STREET,n)) %>%
ggplot(aes(STREET,n, fill=STREET))+
geom_bar(stat="identity", fill="blue")+
coord_flip()+
geom_text(aes(label=n), hjust=0, size=2)+
guides(fill=FALSE)+
ylab("Numero totale") +
xlab("Strade") +
ggtitle("Strade di Boston con più crimini")
crime %>%
group_by(DISTRICT,UCR_PART) %>%
summarise(n=n()) %>%
filter(n>800) %>%
mutate(STREET=reorder(DISTRICT,n)) %>%
ggplot(aes(STREET,n, fill=UCR_PART))+
geom_bar(stat="identity")+
coord_flip()+
ylab("Numero totale") +
xlab("Quartieri") +
ggtitle("Quartieri di Boston per UCR_PART")
Parte 3: Domanda di ricerca
[modifica | modifica sorgente]Si vuole predire che tipo di reato verrà compiuto, cioè se di UCR_PART 1,2 o 3 in base al luogo e al tempo indicato. Quindi UCR_PART è la variabile da predire tramite le variabili : Lat, Long, YEAR, MONTH, HOUR, DAYS_OF_WEEK
Parte 4: Modellizzazione
[modifica | modifica sorgente]crime$UCR_PART <- as.character(crime$UCR_PART)
crime<- crime[-which(crime$UCR_PART==""),]
crime<- crime[-which(crime$UCR_PART=="Other"),]
crime$UCR_PART <- as.factor(crime$UCR_PART)
Si dividono i dati in un training set costituito dal 70% dei records su cui si costruisce il modello e in un testing set costituito dal rimanente 30% su cui si testa il modello:
trainIndex <- createDataPartition(crime$UCR_PART,p=0.7, list = FALSE)
training <- crime[trainIndex,]
testing <- crime[-trainIndex,]
h2o.init()
H2O is not running yet, starting it now... openjdk version "11.0.8" 2020-07-14 OpenJDK Runtime Environment (build 11.0.8+10-post-Ubuntu-0ubuntu120.04) OpenJDK 64-Bit Server VM (build 11.0.8+10-post-Ubuntu-0ubuntu120.04, mixed mode, sharing) Starting H2O JVM and connecting: ..... Connection successful!
R is connected to the H2O cluster: H2O cluster uptime: 6 seconds 187 milliseconds H2O cluster timezone: Europe/Rome H2O data parsing timezone: UTC H2O cluster version: 3.30.1.3 H2O cluster version age: 8 days H2O cluster name: H2O_started_from_R_gian_vxl021 H2O cluster total nodes: 1 H2O cluster total memory: 1.92 GB H2O cluster total cores: 2 H2O cluster allowed cores: 2 H2O cluster healthy: TRUE H2O Connection ip: localhost H2O Connection port: 54321 H2O Connection proxy: NA H2O Internal Security: FALSE H2O API Extensions: Amazon S3, XGBoost, Algos, AutoML, Core V3, TargetEncoder, Core V4 R Version: R version 3.6.3 (2020-02-29)
training_hf <- as.h2o(training)
y <- "UCR_PART"
x <- c("Lat","Long", "YEAR" ,"MONTH" , "HOUR" , "DAY_OF_WEEK")
aml <- h2o.automl(x = x, y = y,
training_frame = training_hf ,max_runtime_secs = 600)
I primi 6 modelli trovati sono i seguenti :
lb <- aml@leaderboard
lb
model_id mean_per_class_error 1 XGBoost_2_AutoML_20201007_033612 0.6050108 2 DRF_1_AutoML_20201007_033612 0.6127668 3 XGBoost_grid__1_AutoML_20201007_033612_model_1 0.6195701 4 XRT_1_AutoML_20201007_033612 0.6196397 5 GBM_5_AutoML_20201007_033612 0.6269082 6 StackedEnsemble_BestOfFamily_AutoML_20201007_033612 0.6303185
Si calcola l'Accuracy dei primi 5 modelli :
test <- as.h2o(testing)
for (i in 1:5) {
m<-h2o.getModel(lb[i,1])
p1 = h2o.predict(m, newdata=test)
df2 <- as.data.frame(p1$predict)
print(mean(df2$predict==testing$UCR_PART))
}
|======================================================================| 100% |======================================================================| 100% [1] 0.5007081 |======================================================================| 100% [1] 0.4525141 |======================================================================| 100% [1] 0.519948 |======================================================================| 100% [1] 0.4719323 |======================================================================| 100% [1] 0.5122583 |======================================================================| 100%
Il modello XGBoost_grid__1_AutoML_20201007_033612_model_1 ha l'Accuracy maggiore pari al 52% quindi lo si sceglie :
test <- as.h2o(testing)
model <- h2o.getModel(lb[3,1])
p1 = h2o.predict(model, newdata=test)
df2 <- as.data.frame(p1$predict)
confusionMatrix(df2$predict,testing$UCR_PART)
Confusion Matrix and Statistics
Reference Prediction Part One Part Three Part Two Part One 1621 844 640 Part Three 15359 43627 24315 Part Two 1508 3094 4315
Overall Statistics
Accuracy : 0.5199 95% CI : (0.5168, 0.5231) No Information Rate : 0.499 P-Value [Acc > NIR] : < 2.2e-16
Kappa : 0.0924
Mcnemar's Test P-Value : < 2.2e-16
Statistics by Class:
Class: Part One Class: Part Three Class: Part Two Sensitivity 0.08768 0.9172 0.14742 Specificity 0.98069 0.1693 0.93033 Pos Pred Value 0.52206 0.5237 0.48391 Neg Pred Value 0.81710 0.6724 0.71119 Prevalence 0.19395 0.4990 0.30706 Detection Rate 0.01701 0.4577 0.04527 Detection Prevalence 0.03257 0.8739 0.09355 Balanced Accuracy 0.53418 0.5432 0.53887
Controversie sull'uso del modello
[modifica | modifica sorgente]Se il modello viene usato per predire i reati "Parte 1" ossia i crimini violenti non c'è nulla da ridire, ma se si la polizia si concentra su quelli "Parte 2" che comprendono vagabondaggio, accattonaggio, consumo in modica quantità di stupefacenti o alcol c'è il rischio di concentrarsi sui quartieri degradati della città e arrestare persone povere che diventerebbero vittime civili del modello.[1]
- ↑ Cathy O'Neil, Armi di distruzione matematica, Saggi Bompiani.