我有一个多标签二进制(0/1)分类的数据集;一些标签永远不会存在(行/列索引的组合在我的应用程序中是不可能的),并且在输入中用-1表示。
我不希望网络学习与-1值相关的权重,并且我不希望损失函数受到它们的影响。为防止这种情况发生,我使用Masking
图层。
我试图修改accepted answer here以便在多标签案例中工作。
数据集(X)由大小为(124,124)并具有(0/1 / -1)值的numpy数组组成。有一系列7个这样的numpy数组。
另一个(124,124)数组中的标签(y_true)为(0/1 / -1)。
接受的答案建议对二进制值和屏蔽值使用单热编码,Keras LSTM期望输入为[num_samples, num_timesteps, num_features]
形状。这两件事意味着我的X和y_true形状分别变为(1,7,124 * 124 * 3)和(1,124 * 124 * 3)。
from keras.layers import Input, Masking, LSTM, Dense
from keras.models import Model
import numpy as np
import tensorflow as tf
from keras import backend as K
from keras.utils import to_categorical
from keras.optimizers import adam
import sys
#Creating some sample data
#Matrix has size 124*124, values -1, 0, 1
X = np.random.rand(1, 7, 124, 124).flatten()
X[X < 0.2] = 0.
X[X > 0.4] = -1.
X[(X > 0.2) & (X < 0.4)] = 1.
#Categories are 0, 1, -1 one-hot encoded
X = to_categorical(X, num_classes=3)
X = np.reshape(X, (7, 3, 124*124)) #X needs to be shape (num_samples, num_timesteps, num_features)
Y = np.random.rand(124, 124).flatten()
Y[Y < 0.2] = 0.
Y[Y > 0.4] = -1.
Y[np.where((Y > 0.2) & (Y < 0.4))] = 1.
Y = to_categorical(Y, num_classes=3)
y_true = np.reshape(Y, (1, 3, 124*124)) #predicting a single timestep
#Building the model
mask_val = np.tile([0,0,1], 124*124).reshape((3, 124*124))
input_tensor = Input(shape=(3, 124*124))
masking_input = Masking(mask_value=mask_val)(input_tensor)
lstm = LSTM(2, return_sequences=True)(masking_input)
output = Dense(124*124, activation='sigmoid')(lstm)
model = Model(input_tensor, output)
model.compile(loss='categorical_crossentropy', optimizer='adam')
print(model.summary())
y_pred = model.predict(X)
#See if the model's loss is the same as the unmasked loss (shouldn't be)
print(model.evaluate(np.expand_dims(X[0,:,:], axis=0), y_true))
现在,我不知道我是否采取了正确的方法。这是否会正确掩盖输入,而不是学习权重从-1到-1?
另外,如何将整个长度为7的输入序列输入model.evaluate
?
修改
通过this discussion重新审视,掩盖并没有按照我的想法行事。
首先,上面的单热编码的原因是因为屏蔽不能处理1D数据,因此屏蔽-1的出现将不起作用(屏蔽向量的出现完全由-1组成将起作用,但不是我想要的。)
其次,掩蔽层的预期用例是当序列中缺少时间步时。例如,如果一个句子中有10个单词的序列,而另一个句子中有12个单词的序列,则通常的做法是对输入进行零填充以使两个句子的长度相同(即将两个单词固定为两个零)第一个输入句子)。然后掩蔽将用于检测零填充输入值并且(可能)跳过这些值对更新权重的贡献。
结论:我需要一种方法来消除非时间依赖的输入值。我可以用固定的Dropout图层做到这一点吗?或者我应该假装我有两个序列:一个真正的时间序列(1 - 7)和一个可能出现[0,0,1]的子序列吗?