Es ist durchaus möglich, mit einem CNN Zeitreihenvorhersagen zu treffen, sei es eine Regression oder eine Klassifikation. CNNs sind gut darin, lokale Muster zu finden, und tatsächlich arbeiten CNNs mit der Annahme, dass lokale Muster überall relevant sind. Auch Faltung ist eine bekannte Operation in der Zeitreihen- und Signalverarbeitung. Ein weiterer Vorteil gegenüber RNNs besteht darin, dass sie sehr schnell zu berechnen sind, da sie im Gegensatz zur sequentiellen RNN-Natur parallelisiert werden können.
Im folgenden Code werde ich eine Fallstudie zeigen, in der es möglich ist, den Strombedarf in R mithilfe von Keras vorherzusagen. Beachten Sie, dass dies kein Klassifizierungsproblem ist (ich hatte kein praktisches Beispiel), es jedoch nicht schwierig ist, den Code zu ändern, um ein Klassifizierungsproblem zu behandeln (verwenden Sie eine Softmax-Ausgabe anstelle einer linearen Ausgabe und einen Kreuzentropieverlust).
Der Datensatz ist in der fpp2-Bibliothek verfügbar:
library(fpp2)
library(keras)
data("elecdemand")
elec <- as.data.frame(elecdemand)
dm <- as.matrix(elec[, c("WorkDay", "Temperature", "Demand")])
Als nächstes erstellen wir einen Datengenerator. Dies wird verwendet, um Stapel von Trainings- und Validierungsdaten zu erstellen, die während des Trainingsprozesses verwendet werden. Beachten Sie, dass dieser Code eine einfachere Version eines Datengenerators ist, der in dem Buch "Deep Learning with R" (und der Videoversion davon "Deep Learning with R in Motion") aus bemannten Veröffentlichungen zu finden ist.
data_gen <- function(dm, batch_size, ycol, lookback, lookahead) {
num_rows <- nrow(dm) - lookback - lookahead
num_batches <- ceiling(num_rows/batch_size)
last_batch_size <- if (num_rows %% batch_size == 0) batch_size else num_rows %% batch_size
i <- 1
start_idx <- 1
return(function(){
running_batch_size <<- if (i == num_batches) last_batch_size else batch_size
end_idx <- start_idx + running_batch_size - 1
start_indices <- start_idx:end_idx
X_batch <- array(0, dim = c(running_batch_size,
lookback,
ncol(dm)))
y_batch <- array(0, dim = c(running_batch_size,
length(ycol)))
for (j in 1:running_batch_size){
row_indices <- start_indices[j]:(start_indices[j]+lookback-1)
X_batch[j,,] <- dm[row_indices,]
y_batch[j,] <- dm[start_indices[j]+lookback-1+lookahead, ycol]
}
i <<- i+1
start_idx <<- end_idx+1
if (i > num_batches){
i <<- 1
start_idx <<- 1
}
list(X_batch, y_batch)
})
}
Als Nächstes geben wir einige Parameter an, die an unsere Datengeneratoren übergeben werden sollen (wir erstellen zwei Generatoren, einen für das Training und einen für die Validierung).
lookback <- 72
lookahead <- 1
batch_size <- 168
ycol <- 3
Der Lookback-Parameter gibt an, wie weit in der Vergangenheit gesucht werden soll, und der Lookahead, wie weit in der Zukunft vorausgesagt werden soll.
Als Nächstes teilen wir unseren Datensatz auf und erstellen zwei Generatoren:
train_dm <- dm [1: 15000,]
val_dm <- dm[15001:16000,]
test_dm <- dm[16001:nrow(dm),]
train_gen <- data_gen(
train_dm,
batch_size = batch_size,
ycol = ycol,
lookback = lookback,
lookahead = lookahead
)
val_gen <- data_gen(
val_dm,
batch_size = batch_size,
ycol = ycol,
lookback = lookback,
lookahead = lookahead
)
Als nächstes erstellen wir ein neuronales Netzwerk mit einer Faltungsschicht und trainieren das Modell:
model <- keras_model_sequential() %>%
layer_conv_1d(filters=64, kernel_size=4, activation="relu", input_shape=c(lookback, dim(dm)[[-1]])) %>%
layer_max_pooling_1d(pool_size=4) %>%
layer_flatten() %>%
layer_dense(units=lookback * dim(dm)[[-1]], activation="relu") %>%
layer_dropout(rate=0.2) %>%
layer_dense(units=1, activation="linear")
model %>% compile(
optimizer = optimizer_rmsprop(lr=0.001),
loss = "mse",
metric = "mae"
)
val_steps <- 48
history <- model %>% fit_generator(
train_gen,
steps_per_epoch = 50,
epochs = 50,
validation_data = val_gen,
validation_steps = val_steps
)
Schließlich können wir mit einem einfachen Verfahren, das in den R-Kommentaren erläutert wird, Code erstellen, um eine Sequenz von 24 Datenpunkten vorherzusagen.
####### How to create predictions ####################
#We will create a predict_forecast function that will do the following:
#The function will be given a dataset that will contain weather forecast values and Demand values for the lookback duration. The rest of the MW values will be non-available and
#will be "filled-in" by the deep network (predicted). We will do this with the test_dm dataset.
horizon <- 24
#Store all target values in a vector
goal_predictions <- test_dm[1:(lookback+horizon),ycol]
#get a copy of the dm_test
test_set <- test_dm[1:(lookback+horizon),]
#Set all the Demand values, except the lookback values, in the test set to be equal to NA.
test_set[(lookback+1):nrow(test_set), ycol] <- NA
predict_forecast <- function(model, test_data, ycol, lookback, horizon) {
i <-1
for (i in 1:horizon){
start_idx <- i
end_idx <- start_idx + lookback - 1
predict_idx <- end_idx + 1
input_batch <- test_data[start_idx:end_idx,]
input_batch <- input_batch %>% array_reshape(dim = c(1, dim(input_batch)))
prediction <- model %>% predict_on_batch(input_batch)
test_data[predict_idx, ycol] <- prediction
}
test_data[(lookback+1):(lookback+horizon), ycol]
}
preds <- predict_forecast(model, test_set, ycol, lookback, horizon)
targets <- goal_predictions[(lookback+1):(lookback+horizon)]
pred_df <- data.frame(x = 1:horizon, y = targets, y_hat = preds)
und voila:
Nicht so schlecht.