Нет эффекта маскирующего слоя в керасе - PullRequest
0 голосов
/ 17 сентября 2018

возможно, я просто не понимаю концепцию, но я подумал, что маскирующие слои должны улучшить производительность моделей при обучении данных с отсутствующими данными.В качестве эксперимента по изучению нерегулярных временных рядов я настроил набор данных (не нужно разбираться в том, как построены данные, но вы можете взглянуть на результирующие Xtrain, Ytrain, Xtest, Ytest):

# some parameters to adjust data generation process
seqSize <- 5
Nfeature <- 2
N <- 50000
pTrain <- .8
missValueMarker <- -1000000
p.miss.samples <- 0.5
p.miss.rate    <-  0.0001
minValues <- 3
epochs <- 20


# create some random data
createSeq <- function(xInit,t0=0,tn=2*pi,seqSize=5){
  tstepSize <- (tn - t0) / seqSize
  tseq <- sort(sample(seq(from=t0, to=tn, length.out=seqSize*200),seqSize))
  ty   <- tn + tstepSize
  yseq1 <- sin(xInit*tseq)
  y1    <- sin(xInit*ty)
  yseq2 <- cos(xInit*tseq)
  y2    <- cos(xInit*ty)
  matrix(c(yseq1,y1,yseq2,y2,diff(c(tseq,ty)),NaN),byrow = TRUE,ncol=(seqSize+1),nrow=3)
}
dx <- seqSize
trainIndex <- sample(1:N,round(pTrain*N))
xInits <- rnorm(N)
xInitTrain <- xInits[trainIndex]
xInitTest <- xInits[-trainIndex]
D <- t(sapply(xInits,function(x)createSeq(x,seqSize=seqSize)))
dim(D) <- c(N,Nfeature+1,seqSize+1)

# insert some missing values
nValues <- prod(seqSize * Nfeature)
p.miss.seq     <- dexp(1:nValues,p.miss.rate)/sum(dexp(1:nValues,p.miss.rate))
p.miss.seq
missIdx <- sample(1:N,round(p.miss.samples*N))
for(i in missIdx){
  nMiss <- min(sample(1:nValues,size=1,prob=p.miss.seq),nValues-minValues)
  if(nMiss < 1){
    next()
  }
  for(j in 1:nMiss){
    # if(nMiss>1){
    #   browser()
    # }
    missId1 <- sample(1:Nfeature,1)
    missId2 <- sample(1:seqSize,1)
    D[i,missId1,missId2] <- missValueMarker
  }
}
# get some overview on the missing data
naCnt <- apply(D,1,function(x)sum(x==missValueMarker,na.rm = TRUE))
table(naCnt)
# devide into feature and labels and train and test part
X <- D[,1:3,1:seqSize]
Y <- D[,1:2,seqSize+1]
Xtrain <- X[trainIndex,,]
Ytrain <- Y[trainIndex,]
Xtest <- X[-trainIndex,,]
Ytest <- Y[-trainIndex,]

КакПри этом нет необходимости вдаваться в подробности, но, как видно из проверки набора данных, данные состоят из X (3 × 5) матриц в качестве входных данных и двух меток в качестве выходных данных.Данные содержат отсутствующие данные, идентифицируемые с помощью заданного значения (-1000000 в приведенном выше примере).Теперь, когда я настроил две одинаковые модели, одну с другим, а другую без маскирующего слоя, вот так:

# build model with and without masking layer
require(keras)
m1 <- keras_model_sequential()
m1 %>%  
  layer_lstm(units = 50, return_sequences = TRUE , stateful = FALSE ,input_shape = dim(X)[-1]) %>%
  layer_lstm(units = 50, return_sequences = FALSE, stateful = FALSE) %>% 
  layer_dense(units = 2)
m1 %>% compile(loss = 'mse', optimizer = 'adam',metrics = c("accuracy"))

m2 <- keras_model_sequential()
m2 %>%  
  layer_masking(input_shape = dim(X)[-1],mask_value = missValueMarker) %>%
  layer_lstm(units = 50, return_sequences = TRUE, stateful = FALSE) %>%
  layer_lstm(units = 50, return_sequences = FALSE, stateful = FALSE) %>% 
  layer_dense(units = 2)
m2 %>% compile(loss = 'mse', optimizer = 'adam',metrics = c("accuracy"))

Я получаю более или менее одинаковые результаты при изучении данных:

cat('Training\n')
testLoss1 <- numeric(epochs)
testLoss2 <- numeric(epochs)
hist1 <- list()
hist2 <- list()
batch_size <- 100
for (i in 1:epochs) {

  hist1[[i]] <- m1 %>% fit(Xtrain, Ytrain, batch_size = batch_size,
                           epochs = 1, verbose = 1, shuffle = FALSE)

  hist2[[i]] <- m2 %>% fit(Xtrain, Ytrain, batch_size = batch_size,
                           epochs = 1, verbose = 1, shuffle = FALSE)

  m1 %>% reset_states()
  m2 %>% reset_states()
  predX1 <- m1 %>% predict(Xtest, batch_size = batch_size)
  predX2 <- m2 %>% predict(Xtest, batch_size = batch_size)
  testLoss1[i] <- mean((Ytest - predX1)^2)
  testLoss2[i] <- mean((Ytest - predX2)^2)

  #batch_size <- batch_size +5
}
windows()
par(mfrow=c(2,1))
trainLosses1 <- sapply(hist1,function(x)x$metrics$loss)
trainLosses2 <- sapply(hist2,function(x)x$metrics$loss)
allLosses <- c(trainLosses1,testLoss1,trainLosses2,testLoss2)
plot(trainLosses1,ylim=range(allLosses),type="b",main="w.o. mask layer")
points(testLoss1,type="b",col="red")
plot(trainLosses2,ylim=range(allLosses),type="b",main="w mask layer")
points(testLoss2,type="b",col="red")

Можно ли ожидать такого поведения?Что-то не так с моим кодом?Разве не гарантируется, что маскирующий слой вообще имеет какой-либо эффект или как это можно объяснить?Любая мысль на эту тему поможет мне.

...