我有一个具有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
,但它是如何工作的?例如,我不知道如何在我的例子中实现它。这是我解决问题的合理方法吗?优化器和损耗函数通常用于此类问题?
答案 0 :(得分: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)