我正在Keras上训练一个时间序列LSTM模型来解决二进制分类问题。
标签非常不平衡(0约占75%)。
这影响了我的结果,因此我决定纠正这一点(特别是因为我想减少假阳性)。
我的型号:
model = Sequential()
model.add(LSTM(64, input_shape=(X_train.shape[1], X_train.shape[2]), use_bias=True, unroll=True, kernel_initializer='glorot_normal', return_sequences=True))
model.add(BatchNormalization())
model.add(Dropout(.25))
model.add(LSTM(32, return_sequences=False, use_bias=True, unroll=True))
model.add(Dense(num_points_per_inp, activation='sigmoid'))
model.compile(optimizer=Adam(beta_1=.8, beta_2=.9), loss=tf.keras.losses.CategoricalCrossentropy(from_logits=True), metrics=tf.keras.metrics.BinaryAccuracy()) # loss=weighted_binary_crossentropy, metrics='accuracy')
model.summary()
我尝试了BN和DO的不同排列,但如果这里有问题,请仍然让我知道。
输入大小为:
X_train.shape --> (8000, 100, 4)
X_test.shape --> (2000, 100, 4)
y_train.shape --> (8000, 100)
y_test.shape --> (2000, 100)
当不使用class_weights运行这个时,模型会编译和训练,但是当我添加class_weights时,它会产生以下错误:
---------------------------------------------------------------------------
InvalidArgumentError Traceback (most recent call last)
<ipython-input-113-2ebc95d5f9f5> in <module>()
7 validation_data=(X_test, y_test),
8 class_weight=weights,
----> 9 verbose=1)
1 frames
/usr/local/lib/python3.7/dist-packages/tensorflow/python/eager/execute.py in quick_execute(op_name, num_outputs, inputs, attrs, ctx, name)
53 ctx.ensure_initialized()
54 tensors = pywrap_tfe.TFE_Py_Execute(ctx._handle, device_name, op_name,
---> 55 inputs, attrs, num_outputs)
56 except core._NotOkStatusException as e:
57 if name is not None:
InvalidArgumentError: Graph execution error:
2 root error(s) found.
(0) INVALID_ARGUMENT: indices[2] = 52 is not in [0, 2)
[[{{node GatherV2}}]]
[[IteratorGetNext]]
[[IteratorGetNext/_2]]
(1) INVALID_ARGUMENT: indices[2] = 52 is not in [0, 2)
[[{{node GatherV2}}]]
[[IteratorGetNext]]
0 successful operations.
0 derived errors ignored. [Op:__inference_train_function_769866]
class_weights是以两种不同的方式生成的(两者都不起作用):方法一:
# based on https://scikit-learn.org/stable/modules/generated/sklearn.utils.class_weight.compute_class_weight.html
from sklearn.utils import class_weight
w = class_weight.compute_class_weight(
class_weight = 'balanced',
classes = np.unique(y_train),
y = y_train.flatten())
weights = dict(enumerate(np.round(w,2)))
方法二:
# based on https://www.youtube.com/watch?v=f6awaKc1L-Q (@ ~12mins)
counts = np.bincount(y_train.flatten().astype(int))
w0 = 1 / counts[0]
w1 = 1 / counts[1]
weights = {0: w0, 1: w1}
我的假设是,问题与我在每个预测中有100个时间点的事实有关(?),而我看到的例子每次只有1个。但即使在这里我也不确定。
尝试使用分类交叉熵,如建议的here也没有帮助
如何解决这个问题?
我也尝试了其他方法,例如。- 自定义损失,但他们也没有按预期工作:
import keras.backend as K
def weighted_binary_crossentropy(y_true, y_pred):
weights =(tf.math.abs(y_true) * 59.) + 1.
bce = K.binary_crossentropy(y_true, y_pred)
weighted_bce = K.mean(bce * weights)
return weighted_bce
(重定向自this medium article)
有什么建议可以解决这个问题吗?
1条答案
按热度按时间xfyts7mz1#
我今天遇到了这个问题。问题是类加权不适用于多维输出
为了解决这个问题,你可以使用样本加权,基本上你需要创建一个数组,形状与
y_train
减去最后一个维度相同(假设你使用的是one-hot编码),每个例子的权重,然后将sample_weight
参数传递给model.fit
。