Verrà effettuato un confronto di modelli utilizzando il dataset IMDB, una raccolta di recensioni di film.
Per maggiori dettagli riguardo i dati, consultare questo link.
In questo report verrà riportato solamente il codice riguardante le reti neurali, e non quello di tutti gli altri modelli statistici, in quanto non sono argomento di interesse. Nelle conclusioni potrete trovare, tuttavia, il confronto dei risultati.
Eseguite il codice qui in seguito, se desiderate impostare in seed ed ottenere risultati riproducibili.
In seguito, definiamo due variabili necessarie per la sentiment analysis, o in generale l’analisi testuale:
max_features
: generalmente quando si effettua un’analisi testuale, si fa riferimento ad un vocabolario, ovvero una raccolta di parole ordinata secondo la frequenza in cui si presentano nel corpus di documenti; di queste parole vengono considerate solamente le n parole più frequenti, dove n è il valore associato alla variabile max_features
; tutte le restanti parole vengono sostituite con un generico valore 2L
.maxlen
: è la lunghezza massima di una frase; se una frase è più lunga del valore di questa variabile, verrà tagliata.Generalmente il primo step di preparazione è la tokenizzazione, ossia l’associazione di un numero intero a ciascuna parola. Questo step non è necessario, perchè in questo caso le sequenze sono già tokenizzate.
In seguito, defininiamo anche una funzione che servirà in seguito: vectorize_sequences
. Questa funzione ha come scopo la trasformazione dell’intero dataset, effettuando la dicotomizzazione delle parole presenti nelle frasi.
vectorize_sequences <- function(sequences, dimension = max_features) {
# Function that applies one-hot-encoding to the sequences.
# Input:
# - sequences: list of sequences; each sequence has length equal to the length of the sentence, and each int value of the sequence corresponds to a word.
# - dimension: max number of words to include; words are ranked by how often they occur (in the training set) and only the most frequent words are kept.
# Output:
# - results: matrix of dim = (n, dimension); each row represents a different sentence, and each column represents a different word; the matrix is filled by 0 and 1 values, depending if the word is present in that sentence or else.
results <- matrix(0, nrow = length(sequences), ncol = dimension)
for (i in 1:length(sequences)) results[i, sequences[[i]]] <- 1
return(results)
}
y_train <- as.numeric(train_labels)
y_test <- as.numeric(test_labels)
Specificare l’architettura della rete neurale:
model <- keras_model_sequential() %>%
layer_dense(units = 32, activation = "relu", input_shape = c(max_features)) %>%
layer_dense(units = 16, activation = "relu") %>%
layer_dense(units = 1, activation = "sigmoid")
model
## Model
## Model: "sequential"
## ________________________________________________________________________________
## Layer (type) Output Shape Param #
## ================================================================================
## dense (Dense) (None, 32) 160032
## ________________________________________________________________________________
## dense_1 (Dense) (None, 16) 528
## ________________________________________________________________________________
## dense_2 (Dense) (None, 1) 17
## ================================================================================
## Total params: 160,577
## Trainable params: 160,577
## Non-trainable params: 0
## ________________________________________________________________________________
Compilare il modello:
rmsprop
, con un learning rate pari a \(0.001\);model %>% compile(
optimizer = optimizer_rmsprop(lr = 0.001),
loss = "binary_crossentropy",
metrics = c("accuracy")
)
Effettuare il training della rete neurale. Come input alla rete neurale, diamo le sequenze dicotomizzate, applicando la funzione vectorize_sequences
al dataset x_train
.
history <- model %>% fit(
x = vectorize_sequences(x_train),
y = y_train,
epochs = 10,
batch_size = 32,
validation_split = 0.2,
verbose = 1
)
In seguito viene rappresentato il grafico della funzione di perdita e dell’accuratezza in funzione del numero di epoche.
Valutazione del modello sui dati di test.
results <- model %>% evaluate(
x = vectorize_sequences(x_test),
y = y_test,
verbose = 0
)
print(paste("Loss on test data:", results["loss"]))
## [1] "Loss on test data: 0.592347383499146"
## [1] "Accuracy on test data: 0.860759973526001"
Specificare l’architettura della rete neurale:
model <- keras_model_sequential() %>%
layer_embedding(input_dim = max_features, output_dim = 128) %>%
layer_lstm(units = 32) %>%
layer_dense(units = 1, activation = "sigmoid")
model
## Model
## Model: "sequential_1"
## ________________________________________________________________________________
## Layer (type) Output Shape Param #
## ================================================================================
## embedding (Embedding) (None, None, 128) 640000
## ________________________________________________________________________________
## lstm (LSTM) (None, 32) 20608
## ________________________________________________________________________________
## dense_3 (Dense) (None, 1) 33
## ================================================================================
## Total params: 660,641
## Trainable params: 660,641
## Non-trainable params: 0
## ________________________________________________________________________________
Compilare il modello:
rmsprop
, con un learning rate pari a \(0.001\);model %>% compile(
optimizer = optimizer_rmsprop(lr = 0.001),
loss = "binary_crossentropy",
metrics = c("accuracy")
)
Effettuare il training della rete neurale. Prima di dare in input le sequenze, vi applichiamo la funzione pad_sequences
: questa funzione applica una lunghezza massima alle sequenze, in questo caso pari al valore max_len. Inoltre, alle sequenze più corte di max_len, vi applica il padding, ossia aggiunge una serie di elementi tutti pari a \(0\) (zero) al temine della sequenza, fino a farla diventare di lunghezza max_len. Questa tecnica è necessaria perchè la rete neurale richiede che le sequenze in input abbiano tutte la stessa lunghezza.
history <- model %>% fit(
x = pad_sequences(x_train, maxlen = maxlen),
y = y_train,
epochs = 10,
batch_size = 32,
validation_split = 0.2,
verbose = 1
)
In seguito viene rappresentato il grafico della funzione di perdita e dell’accuratezza in funzione del numero di epoche.
Valutazione del modello sui dati di test.
results <- model %>% evaluate(
x = pad_sequences(x_test, maxlen = maxlen),
y = y_test,
verbose = 0
)
print(paste("Loss on test data:", results["loss"]))
## [1] "Loss on test data: 0.309290438890457"
## [1] "Accuracy on test data: 0.883960008621216"
Modello | Accuratezza |
---|---|
Recurrent neural network | 88.4% |
Lasso | 87.0% |
Regressione logistica | 86.2% |
Deep neural network | 86.1% |
Random forest | 84.7% |
Bagging | 77.0% |
Adaboost | 72.5% |
Gradient boosting | 70.1% |