Keras LSTM для прогнозирования временных рядов: прогнозирование векторов признаков

У меня есть набор данных временных рядов с N наблюдениями и F функциями. Каждая функция может либо проявляться (1), либо не проявляться (0). Таким образом, набор данных будет выглядеть так:

T    F1    F2    F3    F4    F5 ... F
0    1     0     0     1     0      0
1    0     1     0     0     1      1
2    0     0     0     1     1      0
3    1     1     1     1     0      0
...
N    1     1     0     1     0      0

Я пытаюсь использовать архитектуру на основе LSTM, чтобы предсказать, какие функции проявляются во время T + 1, на основе наблюдений T-W - T, где W - ширина некоторого временного окна. Если W = 4, LSTM «видит» 4 временных шага в прошлое, чтобы сделать прогноз. LSTM ожидает 3D-ввод, который будет иметь вид (number_batches, W, F). Наивная реализация Keras может выглядеть так:

model = Sequential()
model.add(LSTM(128, stateful=True, batch_input_shape=(batch_size, W, F)))
model.add(Dense(F, activation='sigmoid'))

model.compile(loss='binary_crossentropy',
              optimizer='rmsprop',
              metrics=['accuracy'])
model.fit(x_train, y_train,
          batch_size=batch_size, epochs=250, shuffle=False,
          validation_data=(x_val, y_val))

Основная проблема, с которой я сталкиваюсь, заключается в следующем: полный набор данных имеет большое количество признаков (> 200), и признаки проявляются относительно редко, т.е. 0 встречается гораздо чаще, чем 1. Нейронная сеть просто учится устанавливать все значения до 0 и, таким образом, достигается высокая степень «точности».

По сути, я хочу взвесить каждый 1 во входной матрице некоторым значением, чтобы придать ему большее значение, но я не понимаю, как реализовать это в Keras. Я знаю, что в Keras есть опция sample_weight, но как она работает? Я бы не знал, как реализовать это, например, в моем примере. Это разумное решение моей проблемы? Какие оптимизаторы и функции потерь обычно используются для этого типа задач?


person Joris de Vries    schedule 08.10.2017    source источник
comment
вы пытались вместо этого использовать 0 = -1, 1 = 1 вместо этого?   -  person DJK    schedule 08.10.2017
comment
Дополнительное замечание: вы уверены, что хотите использовать stateful=True в своем случае? Подробнее о том, как данные обучения надо быть готовым в этом случае.   -  person Robert Pollak    schedule 13.04.2018


Ответы (1)


Это функция потерь, которую я использую для сильно несбалансированных 2D-данных, она работает очень хорошо. Вы можете заменить binary_crossentropy на другой вид потерь.

import keras.backend as K

def weightedByBatch(yTrue,yPred):

    nVec = K.ones_like(yTrue) #to sum the total number of elements in the tensor
    percent = K.sum(yTrue) / K.sum(nVec) #percent of ones relative to total
    percent2 = 1 - percent #percent of zeros relative to total   
    yTrue2 = 1 - yTrue #complement of yTrue (yTrue+ yTrue2 = full of ones)   

    weights = (yTrue2 * percent2) + (yTrue*percent)
    return K.mean(K.binary_crossentropy(yTrue,yPred)/weights)

Для ваших 3D-данных это может сработать, но, возможно, вы могли бы работать в столбцах, создавая пару весов для каждой функции, вместо того, чтобы суммировать все функции вместе.

Это будет сделано следующим образом:

def weightedByBatch2D(yTrue,yPred):

    nVec = K.ones_like(yTrue) #to sum the total number of elements in the tensor
    percent = K.sum(K.sum(yTrue,axis=0,keepdims=True),axis=1,keepdims=True) / K.sum(K.sum(nVec,axis=0,keepdims=True),axis=1,keepdims=True) #percent of ones relative to total
    percent2 = 1 - percent #percent of zeros relative to total   
    yTrue2 = 1 - yTrue #complement of yTrue (yTrue+ yTrue2 = full of ones)   

    weights = (yTrue2 * percent2) + (yTrue*percent)
    return K.mean(K.binary_crossentropy(yTrue,yPred)/weights)   
person Daniel Möller    schedule 08.10.2017
comment
Благодарю вас! Это похоже на то, что мне было нужно. - person Joris de Vries; 09.10.2017