【问题标题】:Tensorflow stratified_sample errorTensorflow 分层样本错误
【发布时间】:2017-12-12 04:38:28
【问题描述】:

我正在尝试在 Tensorflow 中使用 tf.contrib.training.stratified_sample 来平衡课程。我在下面做了一个简单的例子来测试它,以平衡的方式从两个不平衡的类中抽取样本并验证它,但是我得到了一个错误。

import tensorflow as tf
from tensorflow.python.framework import ops
from tensorflow.python.framework import dtypes

batch_size = 10
data = ['a']*9990+['b']*10
labels = [1]*9990+[0]*10
data_tensor = ops.convert_to_tensor(data, dtype=dtypes.string)
label_tensor = ops.convert_to_tensor(labels)
target_probs = [0.5,0.5]
data_batch, label_batch = tf.contrib.training.stratified_sample(
    data_tensor, label_tensor, target_probs, batch_size,
    queue_capacity=2*batch_size)

with tf.Session() as sess:
    d,l = sess.run(data_batch,label_batch)
print('percentage "a" = %.3f' % (np.sum(l)/len(l)))

我得到的错误是:

Traceback (most recent call last):   
File "/home/jason/code/scrap.py", line 56, in <module>
    test_stratified_sample()   
File "/home/jason/code/scrap.py", line 47, in test_stratified_sample
    queue_capacity=2*batch_size)   
File "/usr/local/lib/python3.4/dist-packages/tensorflow/contrib/training/python/training/sampling_ops.py", line 191, in stratified_sample
    with ops.name_scope(name, 'stratified_sample', tensors + [labels]):   
File "/usr/local/lib/python3.4/dist-packages/tensorflow/python/ops/math_ops.py", line 829, in binary_op_wrapper
    y = ops.convert_to_tensor(y, dtype=x.dtype.base_dtype, name="y")   
File "/usr/local/lib/python3.4/dist-packages/tensorflow/python/framework/ops.py", line 676, in convert_to_tensor
    as_ref=False)   File "/usr/local/lib/python3.4/dist-packages/tensorflow/python/framework/ops.py", line 741, in internal_convert_to_tensor
    ret = conversion_func(value, dtype=dtype, name=name, as_ref=as_ref)   
File "/usr/local/lib/python3.4/dist-packages/tensorflow/python/framework/constant_op.py", line 113, in _constant_tensor_conversion_function
    return constant(v, dtype=dtype, name=name)   
File "/usr/local/lib/python3.4/dist-packages/tensorflow/python/framework/constant_op.py", line 102, in constant
    tensor_util.make_tensor_proto(value, dtype=dtype, shape=shape, verify_shape=verify_shape))   
File "/usr/local/lib/python3.4/dist-packages/tensorflow/python/framework/tensor_util.py", line 374, in make_tensor_proto
    _AssertCompatible(values, dtype)   
File "/usr/local/lib/python3.4/dist-packages/tensorflow/python/framework/tensor_util.py", line 302, in _AssertCompatible
    (dtype.name, repr(mismatch), type(mismatch).__name__)) TypeError: Expected string, got list containing Tensors of type '_Message' instead.

错误并不能解释我做错了什么。我还尝试将原始数据和标签放入(不转换为张量),并尝试使用tf.train.slice_input_producer 创建数据和标签张量的初始队列。

有人让stratified_sample 工作吗?我找不到任何例子。

【问题讨论】:

    标签: python python-3.x machine-learning tensorflow


    【解决方案1】:

    我已将代码修改为适合我的内容。变更摘要:

    • 使用enqueue_many=True 将一批具有不同标签的示例排入队列。否则,它需要一个标量标签 Tensor(在队列运行者评估时可能是随机的)。
    • 第一个参数应该是张量列表。它应该有更好的错误消息(我认为这是您遇到的)。请发送拉取请求或在 Github 上打开问题以获得更好的错误消息。
    • 启动队列运行器。否则使用队列的代码会死锁。或者使用Estimators 或MonitoredSession,这样你就不用担心这个了。
    • (基于 cmets 编辑)stratified_sample 不会对数据进行洗牌,它只是接受/拒绝!因此,如果您的数据不是随机的,如果您希望它以随机顺序出现,请考虑在抽样之前将其通过slice_input_producer (enqueue_many=False) 或shuffle_batch (enqueue_many=True)。

    修改代码(基于Jason的cmets改进):

    import numpy
    import tensorflow as tf
    from tensorflow.python.framework import ops
    from tensorflow.python.framework import dtypes
    
    with tf.Graph().as_default():
      batch_size = 100
      data = ['a']*9000+['b']*1000
      labels = [1]*9000+[0]*1000
      data_tensor = ops.convert_to_tensor(data, dtype=dtypes.string)
      label_tensor = ops.convert_to_tensor(labels, dtype=dtypes.int32)
      shuffled_data, shuffled_labels = tf.train.slice_input_producer(
          [data_tensor, label_tensor], shuffle=True, capacity=3*batch_size)
      target_probs = numpy.array([0.5,0.5])
      data_batch, label_batch = tf.contrib.training.stratified_sample(
          [shuffled_data], shuffled_labels, target_probs, batch_size,
          queue_capacity=2*batch_size)
    
      with tf.Session() as session:
        tf.local_variables_initializer().run()
        tf.global_variables_initializer().run()
        coordinator = tf.train.Coordinator()
        tf.train.start_queue_runners(session, coord=coordinator)
        num_iter = 10
        sum_ones = 0.
        for _ in range(num_iter):
          d, l = session.run([data_batch, label_batch])
          count_ones = l.sum()
          sum_ones += float(count_ones)
          print('percentage "a" = %.3f' % (float(count_ones) / len(l)))
        print('Overall: {}'.format(sum_ones / (num_iter * batch_size)))
        coordinator.request_stop()
        coordinator.join()
    

    输出:

    percentage "a" = 0.480
    percentage "a" = 0.440
    percentage "a" = 0.580
    percentage "a" = 0.570
    percentage "a" = 0.580
    percentage "a" = 0.520
    percentage "a" = 0.480
    percentage "a" = 0.460
    percentage "a" = 0.390
    percentage "a" = 0.530
    Overall: 0.503
    

    【讨论】:

    • 如果我在您的代码中将 data = ['a']*9990+['b']*10 labels = [1]*9990+[0]*10 更改为 data = ['a']*9000+['b']*1000 labels = [1]*9000+[0]*1000,它会中断并仅生成 1 类示例(“a”)。您的代码确实可以按照发布的方式工作,但我无法弄清楚为什么上述更改(这显然使其更现实,因为批量大小远小于任一类中的数量)会破坏它。它也更加平衡,但结果完全不平衡。
    • 太棒了,应该明白这一点。 stratified_sample 不会shuffle,它只是接受/拒绝。因此,如果输入是非随机顺序的,则输出也是如此。我在示例中添加了一个高min_after_dequeue 的洗牌步骤,以确保在采样之前对数据进行洗牌。即使在更高的不平衡情况下,这也是一个问题,它只是被隐藏了,因为很多多数类都被丢弃了。
    • 这是有道理的。谢谢。
    • 为了完整起见,因为我更喜欢单个示例输出(用于文件加载、扩充等),我将 shuffled_data, shuffled_labels = tf.train.shuffle_batch(...) 替换为 shuffled_data,shuffled_labels = tf.train.slice_input_producer([data_tensor, label_tensor], shuffle=True, capacity=3*batch_size) 并将 enqueue_many 设置为 false。这更快(~9s vs.120s),因为它拒绝单个示例而不是全批次。
    • 呵呵,速度还挺快的。我已经编辑了答案以纳入您的改进。我有点惊讶,因为stratified_sample 确实重新批处理了数据,所以它不会拒绝整个批次。
    猜你喜欢
    • 2022-08-18
    • 1970-01-01
    • 2021-06-10
    • 2022-11-20
    • 1970-01-01
    • 1970-01-01
    • 2017-04-23
    • 2019-12-27
    • 1970-01-01
    相关资源
    最近更新 更多