Descripción basic
El kerasformula El paquete ofrece una interfaz de alto nivel para la interfaz R a Keras. Su interfaz principal es la kms
función, una interfaz estilo regresión para keras_model_sequential
que usa fórmulas y matrices escasas.
El paquete KerasFormula está disponible en CRAN y se puede instalar con:
# set up the kerasformula package deal
set up.packages("kerasformula")
# or devtools::install_github("rdrr1990/kerasformula")
library(kerasformula)
# set up the core keras library (if you have not already completed so)
# see ?install_keras() for choices e.g. install_keras(tensorflow = "gpu")
install_keras()
La función kms ()
Muchos tutoriales clásicos de aprendizaje automático suponen que los datos vienen en una forma relativamente homogénea (por ejemplo, píxeles para reconocimiento de dígitos o recuentos o rangos de palabras) que pueden hacer que la codificación sea algo engorrosa cuando los datos están contenidos en un marco de datos heterogéneo. kms()
Aprovecha la flexibilidad de las fórmulas R para suavizar este proceso.
kms
construye redes neuronales densas y, después de ajustarlas, devuelve un solo objeto con predicciones, medidas de ajuste y detalles sobre la llamada de función. kms
acepta una serie de parámetros, incluidas las funciones de pérdida y activación que se encuentran en keras
. kms
también acepta compilado keras_model_sequential
Objetos que permiten una personalización aún más adicional. Esta pequeña demostración muestra cómo kms
Can Help es la construcción de modelos e selección de hiperparameter (por ejemplo, tamaño por lotes) que comienza con datos sin procesar recopilados utilizando library(rtweet)
.
Veamos los tweets #Rstats (excluyendo Retweets) para un período de seis días que finaliza el 24 de enero de 2018 a las 10:40. Esto nos da un buen número razonable de observaciones para trabajar en términos de tiempo de ejecución (y el propósito de este documento es mostrar sintaxis, no construir modelos particularmente predictivos).
rstats <- search_tweets("#rstats", n = 10000, include_rts = FALSE)
dim(rstats)
[1] 2840 42
Supongamos que nuestro objetivo es predecir cómo se basarán los tweets populares en la frecuencia con la que el tweet fue retuiteado y favorecido (lo que se correlaciona fuertemente).
cor(rstats$favorite_count, rstats$retweet_count, technique="spearman")
[1] 0.7051952
Como pocas tweeets se vuelven virales, los datos están bastante sesgados hacia cero.
Aprovechando al máximo las fórmulas
Supongamos que estamos interesados en poner tweets en categorías en función de la popularidad, pero no estamos seguros de cuán finamente gritado queremos hacer distinciones. Algunos de los datos, como rstats$mentions_screen_name
Viene en una lista de diferentes longitudes, así que escribamos una función de ayuda para contar las entradas que no son de la NA.
Comencemos con una densa purple neuronal, el valor predeterminado de kms
. Podemos usar las funciones de Base R para ayudar a limpiar los datos, en este caso, reduce
para discretizar el resultado, grepl
buscar palabras clave y weekdays
y format
Para capturar diferentes aspectos del tiempo se publicó el tweet.
breaks <- c(-1, 0, 1, 10, 100, 1000, 10000)
reputation <- kms(reduce(retweet_count + favorite_count, breaks) ~ screen_name +
supply + n(hashtags) + n(mentions_screen_name) +
n(urls_url) + nchar(textual content) +
grepl('picture', media_type) +
weekdays(created_at) +
format(created_at, '%H'), rstats)
plot(reputation$historical past)
+ ggtitle(paste("#rstat reputation:",
paste0(spherical(100*reputation$evaluations$acc, 1), "%"),
"out-of-sample accuracy"))
+ theme_minimal()
reputation$confusion
reputation$confusion
(-1,0] (0,1] (1,10] (10,100] (100,1e+03] (1e+03,1e+04]
(-1,0] 37 12 28 2 0 0
(0,1] 14 19 72 1 0 0
(1,10] 6 11 187 30 0 0
(10,100] 1 3 54 68 0 0
(100,1e+03] 0 0 4 10 0 0
(1e+03,1e+04] 0 0 0 1 0 0
El modelo solo clasifica aproximadamente el 55% de los datos fuera de la muestra correctamente y esa precisión predictiva no mejora después de las primeras diez épocas. La matriz de confusión sugiere que el modelo lo hace mejor con los tweets que se retuitean un puñado de veces pero exageran el nivel de 1-10. El historical past
La trama también sugiere que la precisión fuera de la muestra no es muy estable. Podemos cambiar fácilmente los puntos de interrupción y el número de épocas.
breaks <- c(-1, 0, 1, 25, 50, 75, 100, 500, 1000, 10000)
reputation <- kms(reduce(retweet_count + favorite_count, breaks) ~
n(hashtags) + n(mentions_screen_name) + n(urls_url) +
nchar(textual content) +
screen_name + supply +
grepl('picture', media_type) +
weekdays(created_at) +
format(created_at, '%H'), rstats, Nepochs = 10)
plot(reputation$historical past)
+ ggtitle(paste("#rstat reputation (new breakpoints):",
paste0(spherical(100*reputation$evaluations$acc, 1), "%"),
"out-of-sample accuracy"))
+ theme_minimal()
Eso ayudó a algunos (aproximadamente un 5% de precisión predictiva adicional). Supongamos que queremos agregar un poco más de datos. Primero almacenemos la fórmula de entrada.
pop_input <- "reduce(retweet_count + favorite_count, breaks) ~
n(hashtags) + n(mentions_screen_name) + n(urls_url) +
nchar(textual content) +
screen_name + supply +
grepl('picture', media_type) +
weekdays(created_at) +
format(created_at, '%H')"
Aquí usamos paste0
Para agregar a la fórmula en bucle a través de ID de usuario agregando algo como:
grepl("12233344455556", mentions_user_id)
mentions <- unlist(rstats$mentions_user_id)
mentions <- distinctive(mentions[which(table(mentions) > 5)]) # take away rare
mentions <- mentions[!is.na(mentions)] # drop NA
for(i in mentions)
pop_input <- paste0(pop_input, " + ", "grepl(", i, ", mentions_user_id)")
reputation <- kms(pop_input, rstats)
Eso ayudó a un tacto, pero la precisión predictiva sigue siendo bastante inestable en todas las épocas …
Personalización de capas con kms ()
Podríamos agregar más datos, tal vez agregar palabras individuales del texto o alguna otra estadística de resumen (imply(textual content %in% LETTERS)
para ver si todos los límites explican popularidad). Pero alteremos la purple neuronal.
El enter.system
se usa para crear una matriz modelo escasa. Por ejemplo, rstats$supply
(Twitter o Twitter-Consumer Utility) y rstats$screen_name
son vectores de personajes que serán muñidos. ¿Cuántas columnas tiene?
[1] 1277
Digamos que queríamos remodelar las capas para hacer la transición más gradualmente de la forma de entrada a la salida.
kms
construye un keras_sequential_model()
que es una pila de capas lineales. La forma de entrada está determinada por la dimensionalidad de la matriz modelo (reputation$P
) Pero después de eso, los usuarios son libres de determinar el número de capas, and so forth. El kms
argumento layers
espera una lista, cuya primera entrada es un vector items
con que llamar keras::layer_dense()
. El primer elemento el número de items
En la primera capa, el segundo elemento para la segunda capa, y así sucesivamente (NA
como el elemento remaining connota para detectar automáticamente el número remaining de unidades en función del número observado de resultados). activation
también se pasa a layer_dense()
y puede tomar valores como softmax
, relu
, elu
y linear
. (kms
también tiene un parámetro separado para controlar el optimizador; por defecto kms(... optimizer="rms_prop")
.) El dropout
Eso sigue a cada tasa de capa densa evita el sobreajuste (pero, por supuesto, no es aplicable a la capa remaining).
Elegir un tamaño por lotes
Por defecto, kms
Utiliza lotes de 32. Supongamos que estábamos contentos con nuestro modelo pero no teníamos ninguna intuición explicit sobre cuál debería ser el tamaño.
Nbatch <- c(16, 32, 64)
Nruns <- 4
accuracy <- matrix(nrow = Nruns, ncol = size(Nbatch))
colnames(accuracy) <- paste0("Nbatch_", Nbatch)
est <- record()
for(i in 1:Nruns){
for(j in 1:size(Nbatch)){
est[[i]] <- kms(pop_input, rstats, Nepochs = 2, batch_size = Nbatch[j])
accuracy[i,j] <- est[[i]][["evaluations"]][["acc"]]
}
}
colMeans(accuracy)
Nbatch_16 Nbatch_32 Nbatch_64
0.5088407 0.3820850 0.5556952
En aras del tiempo de ejecución de reducción, el número de épocas se estableció arbitrariamente corta pero, a partir de esos resultados, 64 es el mejor tamaño de lotes.
Hacer predicciones para nuevos datos
Hasta ahora, hemos estado utilizando la configuración predeterminada para kms
que primero divide los datos en 80% de entrenamiento y un 20% de pruebas. Del entrenamiento del 80%, una cierta porción se reserva para la validación y eso es lo que produce los gráficos de pérdida y precisión de la época por epoch. El 20% solo se usa al remaining para evaluar la precisión predictiva. Pero suponga que quería hacer predicciones en un nuevo conjunto de datos …
reputation <- kms(pop_input, rstats[1:1000,])
predictions <- predict(reputation, rstats[1001:2000,])
predictions$accuracy
[1] 0.579
Debido a que la fórmula crea una variable ficticia para cada nombre de pantalla y mención, cualquier conjunto de tweets dado está garantizado que tenga diferentes columnas. predict.kms_fit
es un S3 technique
Eso toma los nuevos datos y construye una matriz modelo (escasa) que preserva la estructura unique de la matriz de entrenamiento. predict
Luego devuelve las predicciones junto con una matriz de confusión y puntaje de precisión.
Si su NewData tiene los mismos niveles observados de y y columnas de x_train (la matriz modelo), también puede usar keras::predict_classes
en object$mannequin
.
Usando un modelo Keras compilado
Esta sección muestra cómo ingresar un modelo compilado en la moda típico de library(keras)
que es útil para modelos más avanzados. Aquí hay un ejemplo para lstm
análogo al IMBD con Keras Ejemplo.
ok <- keras_model_sequential()
ok %>%
layer_embedding(input_dim = reputation$P, output_dim = reputation$P) %>%
layer_lstm(items = 512, dropout = 0.4, recurrent_dropout = 0.2) %>%
layer_dense(items = 256, activation = "relu") %>%
layer_dropout(0.3) %>%
layer_dense(items = 8, # variety of ranges noticed on y (final result)
activation = 'sigmoid')
ok %>% compile(
loss = 'categorical_crossentropy',
optimizer = 'rmsprop',
metrics = c('accuracy')
)
popularity_lstm <- kms(pop_input, rstats, ok)
Déjame una línea a través del proyecto Repositorio de Github. Agradecimiento especial a @dfalbel y @jjallaire ¡Para sugerencias útiles!