Skip to main content
 首页 » 编程设计

python之为什么我不能使用 TensorFlow 一次性编码我的标签 (坏切片索引 None of type type 'NoneType' >)

2025年04月02日29lhb25

我正在尝试将 CSV 输入管道构建到 TensorFlow 模型中,作为该管道的一部分,我想对标签进行一次性编码。

这是我的完整模型的代码:

from __future__ import print_function 
import numpy as np 
import tensorflow as tf 
import math as math 
import argparse 
 
parser = argparse.ArgumentParser() 
parser.add_argument('dataset') 
args = parser.parse_args() 
 
# hyperparameters 
num_labels = 2 
 
def file_len(fname): 
    with open(fname) as f: 
        for i, l in enumerate(f): 
            pass 
    return i + 1 
 
def read_from_csv(filename_queue): 
  reader = tf.TextLineReader(skip_header_lines=1) 
  _, csv_row = reader.read(filename_queue) 
  record_defaults = [[0],[0],[0],[0],[0]] 
  col1,col2,col3,col4,colLabel = tf.decode_csv(csv_row, record_defaults=record_defaults) 
  features = tf.pack([col1,col2,col3,col4])   
  label = tf.pack([colLabel])   
  return features, label 
 
def read_batches(batch_size, num_epochs=None): 
  filename_queue = tf.train.string_input_producer([args.dataset], num_epochs=num_epochs, shuffle=True)   
  example, label = read_from_csv(filename_queue) 
  min_after_dequeue = 10000 
  capacity = min_after_dequeue + 3 * batch_size 
  example_batch, label_batch = tf.train.shuffle_batch( 
      [example, label], batch_size=batch_size, capacity=capacity, 
      min_after_dequeue=min_after_dequeue) 
  return example_batch, label_batch 
 
def reformat(dataset, labels):   
  dataset = tf.to_float(dataset) 
  labels = tf.reshape(labels, [-1]) 
  # labels = (np.arange(num_labels) == labels[:,None]).astype(np.float32) 
  return dataset, labels 
 
def input_pipeline(batch_size, num_epochs=None): 
  example_batch, label_batch = read_batches(batch_size, num_epochs) 
  train_dataset, train_labels = reformat(example_batch, label_batch) 
  return train_dataset, train_labels 
 
file_length = file_len(args.dataset) - 1 
training_dataset, training_labels = input_pipeline(file_length, 1) 
 
with tf.Session() as sess: 
  tf.initialize_all_variables().run() 
 
  # start populating filename queue 
  coord = tf.train.Coordinator() 
  threads = tf.train.start_queue_runners(coord=coord) 
 
  try: 
    while not coord.should_stop(): 
      training_dataset_batch, training_labels_batch = sess.run([training_dataset, training_labels])  
      print("\nlabels:") 
      print(training_labels_batch) 
      print("\nlabels type:") 
      print(type(training_labels_batch)) 
      print("\nlabels shape:") 
      print(training_labels_batch.shape) 
      print("\nlabels rank:") 
      print(tf.rank(training_labels_batch)) 
  except tf.errors.OutOfRangeError: 
    print('\nDone training, epoch reached') 
  finally: 
    coord.request_stop() 
 
  coord.join(threads)  

下面是一些适用于此模型的 CSV 示例:

col1,col2,col3,col4,label 
0,0,0,0,0 
0,15,0,0,0 
0,30,0,0,1 
0,45,0,0,1 
1,0,0,0,2 
1,15,0,0,2 
1,30,0,0,3 
1,45,0,0,3 

如果我按原样运行这段代码,这就是我得到的输出——此时,我还没有启用任何单热编码,你在这里看到的或多或少是有道理的——我的标签数组有形状为 (8,) 因为有 8 个示例,等级为 0:

$ python model.py csv_test_data.csv  
 
labels: 
[0 2 2 0 3 3 1 1] 
 
labels type: 
<type 'numpy.ndarray'> 
 
labels shape: 
(8,) 
 
labels rank: 
Tensor("Rank:0", shape=(), dtype=int32) 
 
Done training, epoch reached 
(tensorflow)  

当我启用这行代码以在 reformat 中对标签进行单热编码时,问题就来了:

labels = (np.arange(num_labels) == labels[:,None]).astype(np.float32) 

我一介绍它,砰的一声——它让我大吃一惊:

$ python model.py csv_test_data.csv  
Traceback (most recent call last): 
  File "model.py", line 51, in <module> 
    training_dataset, training_labels = input_pipeline(file_length, 1) 
  File "model.py", line 47, in input_pipeline 
    train_dataset, train_labels = reformat(example_batch, label_batch) 
  File "model.py", line 42, in reformat 
    labels = (np.arange(num_labels) == labels[:,None]).astype(np.float32) 
  File "/Users/rringham/tensorflow/lib/python2.7/site-packages/tensorflow/python/ops/array_ops.py", line 161, in _SliceHelper 
    raise TypeError("Bad slice index %s of type %s" % (s, type(s))) 
TypeError: Bad slice index None of type <type 'NoneType'> 

我真的不清楚为什么;我在其他 TensorFlow 模型中使用了相同的技术,并且它在几乎相同的标签类型上工作得很好——一个值数组,一个 (#,) 的形状,其中 # 是示例的数量,以及一个等级 0——例如:

关于为什么这行不通,我在这里明显遗漏了什么吗?

请您参考如下方法:

问题似乎是 NumPy 切片语法和 TensorFlow 切片语法之间的(另一个)不兼容。在 NumPy 中,labels[:, None] 是向返回数组添加新维度的简写,将长度为 N 的向量转换为大小为 的矩阵N x 1。 TensorFlow 不理解这一点(目前),所以你使用了 tf.expand_dims() op 而不是:

tf.expand_dims(labels, 1)  # equivalent to `labels[:, None]` in NumPy. 

但是,一旦您解决了这个问题,您可能会遇到其他问题:

labels = (np.arange(num_labels) == labels[:,None]).astype(np.float32) 

由于 labels 是 TensorFlow 张量而不是 NumPy 数组,您将无法使用 NumPy 方法,例如 == 运算符和 astype () 就可以了。以下是使用 TensorFlow 运算符编写此行的方法:

labels = tf.cast( 
    tf.equal(tf.range(num_labels), tf.expand_dims(labels, 1)), tf.float32) 

PS. 新tf.one_hot() op 可能是将数据转换为单热编码的更简单方法。