mc = as_tibble(mcycle)
mc
Per suddividere il dataset si è dapprima impostato il seme per la generazione (pseudo)casuale dei numeri in modo tale da avere lo stesso risultato ogni volta che il codice girerà.
sequenza serve a fare un riordinamento casuale del
dataset, così poi da dividerlo in due parti, il 75% sarà destinato al
dataset utilizzato per allenare il modello, mnetre il restante verrà
utilizzato per testare la qualità del modello.
set.seed(1)
sequenza = sample(c(1:dim(mc)[1]),
size = dim(mc)[1],
replace = F)
mcTraining = mc[sequenza[c(1:(0.75*dim(mc)[1]))],]
mcTest = mc[sequenza[c((0.75*dim(mc)[1]):dim(mc)[1])],]
modLin = lm(accel ~ times, data = mcTraining)
modQuad = lm(accel ~ I(times**2), data = mcTraining)
modCub = lm(accel ~ I(times**3), data = mcTraining)
{
plot(x = mcTraining$times,
y = mcTraining$accel)
asseX = seq(from = min(mcTraining$times),
to = max(mcTraining$times),
by = .1)
lines(x=asseX,
predict(modLin,data.frame(times=asseX)),
col = "green")
lines(x=asseX,
predict(modQuad,data.frame(times=asseX)),
col = "red")
lines(x=asseX,
predict(modCub,data.frame(times=asseX)),
col = "blue")
legend("bottomright",
c("Modello lineare","Modello quadratico","Modello cubico"),
col = c("green","red","blue"),
lwd = 1)
}
poly# modificando questo parametro si genereranno x modelli polinomiali fino al modello con polinomio grado x
gradoMax = 6
# ogni volta che il codice girerà i colori rimarranno sempre gli stessi per ogni modello
set.seed(1)
modelli = lapply(X = c(1:gradoMax),
function(grado) lm(accel ~ poly(times,grado),
data = mcTraining))
# creo una palette di colori evitando le scale di grigi
colori = sample(grDevices::colors()[grep('gr(a|e)y', grDevices::colors(), invert = T)],
size = gradoMax,
replace = F)
{
plot(x = mcTraining$times,
y = mcTraining$accel)
asseX = seq(from = min(mcTraining$times),
to = max(mcTraining$times),
by = .1)
apply(X = c(1:gradoMax) %>% matrix,
1,
function(grado) lines(x=asseX,
predict(modelli[[grado]],
data.frame(times=asseX)),
col = colori[grado]))
legend("bottomright",
stringr::str_c("grado ",c(1:gradoMax)),
col = colori,
lwd = 1,
cex = .6)
}
Nel primo grafico si nota come il modello quadratico e cubico
posseggano una derivata seconda quasi nulla e che quindi si comportino
quasi come una retta. Nel secondo grafico, dove è stata introdotta la
funzione poly si può osservare come i modelli si addatti
molto di più ai dati.
Sfruttando la generazione precedente di modelli viene molto facile e veloce controllare la misura dell’addattamento sul training set, cossiché da vedere il modello che si adatta di più ai dati.
gradoMax = 20
modelli = lapply(X = c(1:gradoMax),
function(grado) lm(accel ~ poly(times,grado),
data = mcTraining))
SSEtraining = sapply(c(1:gradoMax),function(grado) deviance(modelli[[grado]]))
data.frame(Polinomio = stringr::str_c("grado ",c(1:gradoMax)),SSEtraining)
accelPredict = lapply(c(1:gradoMax),
function(grado) predict(modelli[[grado]], newdata = mcTest))
SSEtest = sapply(c(1:gradoMax), function(grado) sum((mcTest$accel-accelPredict[[grado]])**2))
SST = sum((mcTest$accel-mean(mcTraining$accel))**2)
R2 = 1 - SSEtest/SST
{
plot(SSEtraining/dim(mcTraining)[1],
type = "l",
ylim = c(0,max(SSEtest/dim(mcTest)[1])),
xlab = "Grado del polinomio",
ylab = "Devianza media")
lines(SSEtest/dim(mcTest)[1],type = "l",col = "green")
legend("topright",
col = c("green","black"),
lwd = 1,
c("Test set","Training set"),)
}