【问题标题】:Tensorflow: oversampling with SMOTE giving highly skewed resultsTensorflow:使用 SMOTE 进行过采样会产生高度偏斜的结果
【发布时间】:2017-06-10 10:39:55
【问题描述】:

我有 2 个类别(1 和 0)的不平衡数据集。 1 比 0 的可能性小约 6 倍。因此,我使用SMOTE 通过过采样使数据集保持平衡。使用 SMOTE 会给出非常不准确的结果。我不明白为什么

from imblearn.over_sampling import SMOTE

def train_neural_network(x, y, features, labels):

   X_train, X_test, y_train, y_test = train_test_split(features, labels, test_size=0.2)

   print(len(y_train), len(y_train[y_train == 1]), len(y_train[y_train == 0]))

   sm = SMOTE()
   X_train, y_train = sm.fit_sample(X_train, y_train)

   print(len(y_train), len(y_train[y_train == 1]), len(y_train[y_train == 0]))

   prediction = neural_network_model(x, len(features.columns))
   cost = tf.reduce_mean(tf.nn.sparse_softmax_cross_entropy_with_logits(logits=prediction, labels=tf.cast(y, tf.int32)))
   optimizer = tf.train.AdamOptimizer().minimize(cost)

   hm_epochs = 1

   with tf.Session() as sess:
    sess.run(tf.initialize_all_variables())
    for epoch in range(hm_epochs):
        epoch_loss = 0

        for i in range(int(len(X_train) / batch_size)):
            epoch_x = X_train[i*batch_size: min((i + 1)*batch_size, len(X_train))]
            epoch_y = y_train[i*batch_size: min((i + 1)*batch_size, len(y_train))]
            i, c = sess.run([optimizer, cost], feed_dict = {x:epoch_x, y:epoch_y})
            epoch_loss += c

        print('Epoch', epoch + 1, ' completed out of ', hm_epochs, ' loss: ', epoch_loss)

    correct = tf.equal(tf.argmax(prediction, 1), y)

    accuracy = tf.reduce_mean(tf.cast(correct, tf.float32))

    print('Accuracy : ', sess.run(accuracy, feed_dict={x: X_test, y: y_test}))

    y1 = y_test[y_test == 1]
    X1 = X_test[y_test == 1]
    print('Accuracy 1: ', sess.run(accuracy, feed_dict={x: X1, y: y1}))

    y0 = y_test[y_test == 0]
    X0 = X_test[y_test == 0]
    print('Accuracy 0: ', sess.run(accuracy, feed_dict={x: X0, y: y0}))


with open("xdf.pickle", 'rb') as f:
   features = pickle.load(f)
with open("ydf.pickle", 'rb') as f:
   labels = pickle.load(f)
x = tf.placeholder('float', [None, len(features.columns)])
y = tf.placeholder(tf.int64)
train_neural_network(x, y, features, labels)

这是输出(打印语句)

1521207 255174 1266033 // initial dataset (total points, label = 1, label = 0)
2532066 1266033 1266033 // after smote
Epoch 1  completed out of  1  loss:  345947.933431 // after 1 epoch
Accuracy :  0.168227 // test accuracy
Accuracy 1:  1.0 // output of test with all labels = 1
Accuracy 0:  3.1613e-06 // output of test will all labels = 0

当我没有对数据集进行过度采样时,我得到以下结果

1521207 255174 1266033 // initial dataset (total points, label = 1, label = 0)
Epoch 1  completed out of  1  loss:  270053.921566 // after 1 epoch
Accuracy :  0.762063 // test accuracy
Accuracy 1:  0.1554 // output of test with all labels = 1
Accuracy 0:  0.883916 // output of test will all labels = 0

当数据集倾斜时,这给出了预期的输出。我在使用 SMOTE 的方法上犯了错误吗?为什么结果会如此偏斜?

【问题讨论】:

    标签: tensorflow


    【解决方案1】:

    您可以尝试在这里进行分层抽样吗?由于您尚未粘贴图形代码,因此除了分类类型之外,我无法猜测此处的任务类型。它可能是顺序数据,在这种情况下我们可能会看到这样的结果。

    我发现数据中有一些时间性质。 SMOTE 会在数据中不必要地添加更多不需要的指标。请在此处尝试加权损失函数,在该函数中,通过其相对于其他标签的详细程度来减轻主要类错误的权重。

    同样对于非常罕见的事件,训练有偏于不同罕见标签的分类器并使用带投票的集成方法可能会有所帮助。

    【讨论】:

    • 我确实想要一个分类。基本上,特征是股票市场指标值,标签是股票在未来 20 天内是否上涨了 10%。所以我想看看结合哪些指标值可以预测股票
    • 分层抽样并没有显着提高输出
    • 我看到数据中有一些时间性质。 SMOTE 会在数据中不必要地添加更多不需要的指标。您可以在这里尝试加权损失函数,通过其相对于其他标签的详细率来加权主要类错误。 (我认为在您的情况下,大多数频繁出现的数据是不会以任何方式增加库存的数据。我说的对吗?)
    • 我试过了……但这并不能提高准确性。我认为我以错误的方式看待问题。请将您的 SMOTE 评论添加到答案中...我会支持您的答案,但无法将其标记为正确,因为我的问题可能无法解决。
    【解决方案2】:

    我真的不知道您的数据的性质和建模的概念,但我不确定您是否总是需要对不平衡数据进行过采样 - 因为您的数据案例可能会出现 Data Drift & 在这种情况下,异常检测以及预训练可以帮助对已经发生的情况采用进一步的学习过程......只需注意 - Analyzing training-serving skew with TensorFlow Data Validation - 如果这可以是你的情况吗?

    我相信,盲目地对少数人进行过采样不是正确的方法,因为您只是在次要类中添加了一些随机数据,从而获得了另一个现实范围,== 如果您的数据分布本质上是真正的高斯分布,那么只有在这种情况下,您才有理由使用 SMOTE 作为过采样技术(也就是说-您的数据本质上应该是真正随机的-是这样吗?-您不是说“它们是歪斜的")

    顺便说一下,你的 SMOTE 结果给你的不是偏差,而是常态

    附:通常(如果您确实需要将偏斜数据处理为正态分布分析)可能的统计方法来建模偏斜数据是处理它们的 ln(自然对数),而不是过采样 [真正的不平衡看起来像偏斜数据的另一种方式!!]...在分析的最后阶段,您应该从 ln... 返回数据 - 尽管它是频率论方法,而不是贝叶斯方法

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-03-05
      • 2019-05-09
      • 2020-03-08
      • 2018-12-24
      • 2021-09-21
      • 2015-05-11
      • 2019-05-24
      • 2019-08-30
      相关资源
      最近更新 更多