如何在 TensorFlow 中使用 Hugging Face Transformers 库对自定义数据进行文本分类?

Posted

技术标签:

【中文标题】如何在 TensorFlow 中使用 Hugging Face Transformers 库对自定义数据进行文本分类?【英文标题】:How to use Hugging Face Transformers library in Tensorflow for text classification on custom data? 【发布时间】:2020-05-15 15:38:19 【问题描述】:

我正在尝试使用 Hugging Face 'Transformers' 库提供的不同转换器架构对自定义数据(csv 格式)进行二进制文本分类。我使用这个Tensorflow blog post 作为参考。

我正在使用以下代码将自定义数据集加载为“tf.data.Dataset”格式:

def get_dataset(file_path, **kwargs):
   dataset = tf.data.experimental.make_csv_dataset(
     file_path,
     batch_size=5, # Artificially small to make examples easier to show.
     na_value="",
     num_epochs=1,
     ignore_errors=True, 
     **kwargs)
   return dataset 

之后,当我尝试使用'glue_convert_examples_to_features' 方法进行标记时,如下所示:

train_dataset = glue_convert_examples_to_features(
                           examples = train_data,
                           tokenizer = tokenizer, 
                           task = None,
                           label_list = ['0', '1'],
                           max_length = 128
                           )

在以下位置引发错误“UnboundLocalError: local variable 'processor' referenced before assignment”:

 if is_tf_dataset:
    example = processor.get_example_from_tensor_dict(example)
    example = processor.tfds_map(example)

在所有示例中,我看到他们正在使用诸如“mrpc”之类的任务,这些任务是预先定义的并且有一个glue_processor 来处理。 source code 中的“第 85 行”出现错误。

任何人都可以使用“自定义数据”来帮助解决这个问题吗?

【问题讨论】:

【参考方案1】:

我有同样的启动问题。

这个Kaggle submission 帮助了我很多。在那里您可以看到如何根据所选的预训练模型对数据进行标记:

from transformers import BertTokenizer
from keras.preprocessing.sequence import pad_sequences

bert_model_name = 'bert-base-uncased'

tokenizer = BertTokenizer.from_pretrained(bert_model_name, do_lower_case=True)
MAX_LEN = 128

def tokenize_sentences(sentences, tokenizer, max_seq_len = 128):
    tokenized_sentences = []

    for sentence in tqdm(sentences):
        tokenized_sentence = tokenizer.encode(
                            sentence,                  # Sentence to encode.
                            add_special_tokens = True, # Add '[CLS]' and '[SEP]'
                            max_length = max_seq_len,  # Truncate all sentences.
                    )
        
        tokenized_sentences.append(tokenized_sentence)

    return tokenized_sentences

def create_attention_masks(tokenized_and_padded_sentences):
    attention_masks = []

    for sentence in tokenized_and_padded_sentences:
        att_mask = [int(token_id > 0) for token_id in sentence]
        attention_masks.append(att_mask)

    return np.asarray(attention_masks)

input_ids = tokenize_sentences(df_train['comment_text'], tokenizer, MAX_LEN)
input_ids = pad_sequences(input_ids, maxlen=MAX_LEN, dtype="long", value=0, truncating="post", padding="post")
attention_masks = create_attention_masks(input_ids)

之后,您应该拆分 id 和掩码:

from sklearn.model_selection import train_test_split

labels =  df_train[label_cols].values

train_ids, validation_ids, train_labels, validation_labels = train_test_split(input_ids, labels, random_state=0, test_size=0.1)
train_masks, validation_masks, _, _ = train_test_split(attention_masks, labels, random_state=0, test_size=0.1)

train_size = len(train_inputs)
validation_size = len(validation_inputs)

此外,我查看了glue_convert_examples_to_features 的source。在那里你可以看到如何创建与 BERT 模型兼容的tf.data.dataset。我为此创建了一个函数:

def create_dataset(ids, masks, labels):
    def gen():
        for i in range(len(train_ids)):
            yield (
                
                    "input_ids": ids[i],
                    "attention_mask": masks[i]
                ,
                labels[i],
            )

    return tf.data.Dataset.from_generator(
        gen,
        ("input_ids": tf.int32, "attention_mask": tf.int32, tf.int64),
        (
            
                "input_ids": tf.TensorShape([None]),
                "attention_mask": tf.TensorShape([None])
            ,
            tf.TensorShape([None]),
        ),
    )

train_dataset = create_dataset(train_ids, train_masks, train_labels)

然后我像这样使用数据集:

from transformers import TFBertForSequenceClassification, BertConfig

model = TFBertForSequenceClassification.from_pretrained(
    bert_model_name, 
    config=BertConfig.from_pretrained(bert_model_name, num_labels=20)
)

# Prepare training: Compile tf.keras model with optimizer, loss and learning rate schedule
optimizer = tf.keras.optimizers.Adam(learning_rate=3e-5, epsilon=1e-08, clipnorm=1.0)
loss = tf.keras.losses.CategoricalCrossentropy(from_logits=True)
metric = tf.keras.metrics.CategoricalAccuracy('accuracy')
model.compile(optimizer=optimizer, loss=loss, metrics=[metric])

# Train and evaluate using tf.keras.Model.fit()
history = model.fit(train_dataset, epochs=1, steps_per_epoch=115, validation_data=val_dataset, validation_steps=7)

【讨论】:

对我来说,生成器不起作用,我不得不使用tf.reshape(tf.constant(labels[i]), [1,num_labels]) 而不是labels[i],这样tf 就不会抱怨形状不匹配。无论如何,谢谢你,你的回答对我帮助很大! 您能否提供一个示例,说明您将如何获得在第二个 sn-p 中使用的 train_masks 参数?另外,我猜你是用和train_dataset一样的程序来获取你的val_dataset的吧? 嗨,我根据您的评论更新了我的答案。你也可以点击 Kaggle 比赛来找出答案。是的,我正在使用与train_dataset 相同的程序获得val_dataset

以上是关于如何在 TensorFlow 中使用 Hugging Face Transformers 库对自定义数据进行文本分类?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 tensorflow 中使用 intel-mkl

如何在 pytorch 和 tensorflow 中使用张量核心?

如何在 TensorFlow 中使用批量标准化?

如何让 Keras 在 Anaconda 中使用 Tensorflow 后端?

如何使用 tensorflow 在 C++ 中训练模型?

如何使用 django 保持 tensorflow 会话在内存中运行