【问题标题】:Referencing and tokenizing single feature column in multi-feature TensorFlow Dataset在多特征 TensorFlow 数据集中引用和标记单个特征列
【发布时间】:2021-01-03 16:03:53
【问题描述】:

我正在尝试对 TensorFlow 数据集中的单个列进行标记。如果只有一个特征列,我一直使用的方法效果很好,例如:

text = ["I played it a while but it was alright. The steam was a bit of trouble."
        " The more they move these game to steam the more of a hard time I have"
        " activating and playing a game. But in spite of that it was fun, I "
        "liked it. Now I am looking forward to anno 2205 I really want to "
        "play my way to the moon.",
        "This game is a bit hard to get the hang of, but when you do it's great."]
target = [0, 1]

df = pd.DataFrame({"text": text,
                   "target": target})

training_dataset = (
    tf.data.Dataset.from_tensor_slices((
        tf.cast(df.text.values, tf.string), 
        tf.cast(df.target, tf.int32))))

tokenizer = tfds.features.text.Tokenizer()

lowercase = True
vocabulary = Counter()
for text, _ in training_dataset:
    if lowercase:
        text = tf.strings.lower(text)
    tokens = tokenizer.tokenize(text.numpy())
    vocabulary.update(tokens)


vocab_size = 5000
vocabulary, _ = zip(*vocabulary.most_common(vocab_size))


encoder = tfds.features.text.TokenTextEncoder(vocabulary,
                                              lowercase=True,
                                              tokenizer=tokenizer)

但是,当我尝试在有一组特征列的情况下执行此操作时,例如来自make_csv_dataset(每个特征列都被命名),上述方法失败了。 (ValueError: Attempt to convert a value (OrderedDict([]) to a Tensor.)。

我尝试使用以下方法在 for 循环中引用特定功能列:

text = ["I played it a while but it was alright. The steam was a bit of trouble."
        " The more they move these game to steam the more of a hard time I have"
        " activating and playing a game. But in spite of that it was fun, I "
        "liked it. Now I am looking forward to anno 2205 I really want to "
        "play my way to the moon.",
        "This game is a bit hard to get the hang of, but when you do it's great."]
target = [0, 1]
gender = [1, 0]
age = [45, 35]



df = pd.DataFrame({"text": text,
                   "target": target,
                   "gender": gender,
                   "age": age})

df.to_csv('test.csv', index=False)

dataset = tf.data.experimental.make_csv_dataset(
    'test.csv',
    batch_size=2,
    label_name='target')

tokenizer = tfds.features.text.Tokenizer()

lowercase = True
vocabulary = Counter()
for features, _ in dataset:
    text = features['text']
    if lowercase:
        text = tf.strings.lower(text)
    tokens = tokenizer.tokenize(text.numpy())
    vocabulary.update(tokens)


vocab_size = 5000
vocabulary, _ = zip(*vocabulary.most_common(vocab_size))


encoder = tfds.features.text.TokenTextEncoder(vocabulary,
                                              lowercase=True,
                                              tokenizer=tokenizer)

我收到错误:Expected binary or unicode string, got array([])。引用单个特征列以便我可以标记化的正确方法是什么?通常,您可以在 .map 函数中使用 feature['column_name'] 方法引用特征列,例如:

def new_age_func(features, target):
    age = features['age']
    features['age'] = age/2
    return features, targets

dataset = dataset.map(new_age_func)

for features, target in dataset.take(2):
    print('Features: {}, Target {}'.format(features, target))

我尝试组合方法并通过映射函数生成词汇表。

tokenizer = tfds.features.text.Tokenizer()

lowercase = True
vocabulary = Counter()

def vocab_generator(features, target):
    text = features['text']
    if lowercase:
        text = tf.strings.lower(text)
        tokens = tokenizer.tokenize(text.numpy())
        vocabulary.update(tokens)

dataset = dataset.map(vocab_generator)

但这会导致错误:

AttributeError: in user code:

    <ipython-input-61-374e4c375b58>:10 vocab_generator  *
        tokens = tokenizer.tokenize(text.numpy())

    AttributeError: 'Tensor' object has no attribute 'numpy'

tokenizer.tokenize(text.numpy()) 更改为tokenizer.tokenize(text) 会引发另一个错误TypeError: Expected binary or unicode string, got &lt;tf.Tensor 'StringLower:0' shape=(2,) dtype=string&gt;

【问题讨论】:

  • 您能否提供一个重现您的错误的示例?您可以将数据框转换为 CSV 并使用 make_csv_dataset 取回。
  • @NicolasGervais - 将第二个代码块更新为完全可重现的示例。

标签: python tensorflow nlp tensorflow2.0 tensorflow-datasets


【解决方案1】:

错误只是tokenizer.tokenize 需要一个字符串,而你给它一个列表。这个简单的编辑将起作用。我只是做了一个循环,将所有字符串都提供给标记器,而不是给它一个字符串列表。

dataset = tf.data.experimental.make_csv_dataset(
    'test.csv',
    batch_size=2,
    label_name='target',
    num_epochs=1)

tokenizer = tfds.features.text.Tokenizer()

lowercase = True
vocabulary = Counter()
for features, _ in dataset:
    text = features['text']
    if lowercase:
        text = tf.strings.lower(text)
    for t in text:
        tokens = tokenizer.tokenize(t.numpy())
        vocabulary.update(tokens)

【讨论】:

    【解决方案2】:

    make_csv_dataset 创建的数据集的每个元素都是 CVS 文件的 batch 行,而不是单行;这就是为什么它将batch_size 作为输入参数。另一方面,当前用于处理和标记文本特征的for 循环每次需要单个输入样本(即行)。因此,给定一批字符串,tokenizer.tokenize 将失败并引发TypeError: Expected binary or unicode string, got array(...)

    以最小的更改解决此问题的一种方法是首先取消批处理数据集,对数据集执行所有预处理,然后再次批处理数据集.幸运的是,我们可以在这里使用一个内置的unbatch 方法:

    dataset = tf.data.experimental.make_csv_dataset(
        ...,
        # This change is **IMPORTANT**, otherwise the `for` loop would continue forever!
        num_epochs=1
    )
    
    # Unbatch the dataset; this is required even if you have used `batch_size=1` above.
    dataset = dataset.unbatch()
    
    #############################################
    #
    # Do all the preprocessings on the dataset here...
    #
    ##############################################
    
    
    # When preprocessings are finished and you are ready to use your dataset:
    #### 1. Batch the dataset (only if needed for or applicable to your specific workflow)
    #### 2. Repeat the dataset (only if needed for or applicable to specific your workflow)
    dataset = dataset.batch(BATCH_SIZE).repeat(NUM_EPOCHS or -1)
    

    @NicolasGervais 的回答中建议的另一种解决方案是调整和修改您的所有预处理代码以处理批量样本,而不是一次处理单个样本。

    【讨论】:

    • num_epochs 参数非常有用。我将赏金授予@NicolasGervais,因为他是第一个做出回应的人,但我还有一个后续问题需要回答。如果您能提供帮助,很高兴获得类似的赏金。谢谢! stackoverflow.com/questions/64012816/…
    • @scribbles 别担心!我不是为了赏金而来的 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-08-16
    • 1970-01-01
    • 1970-01-01
    • 2018-10-16
    • 2018-03-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多