使用Hugging Face Transformers库实现BERT模型

在自然语言处理(NLP)领域,BERT模型因其卓越的性能而广受欢迎。本文将探讨如何利用Hugging Face提供的Transformers库来简化BERT模型以及其他最先进模型的实现过程。使用TensorFlowHub实现BERT模型虽然可行,但过程繁琐,需要从零开始构建分词器、数据处理函数以及训练模型。而Hugging Face的Transformers库则提供了一种更为简便的方法,使得模型的加载和训练变得轻而易举。

Hugging FaceTransformers库的优势

Hugging Face是一个专注于NLP的初创公司,为TensorFlow和PyTorch提供了多种NLP解决方案。Transformers库包含了超过30种预训练模型和100种语言支持,覆盖了8种主要的自然语言理解(NLU)和自然语言生成(NLG)架构,如BERT、GPT-2、Transformer-XL等。使用该库,可以在几行代码内加载模型并进行训练,同时对数据进行预处理。这大大减少了对昂贵计算基础设施的需求,并简化了模型的实现过程。

数据集加载与预处理

本文使用的是情感数据集,该数据集包含了文本及其对应的情感标签,分为训练集、测试集和验证集。以下是如何使用Python代码加载和预处理这些数据的示例。

import pandas as pd df_train = pd.read_csv('train.txt', header=None, sep=';', names=['Input', 'Sentiment'], encoding='utf-8') df_test = pd.read_csv('test.txt', header=None, sep=';', names=['Input', 'Sentiment'], encoding='utf-8') print(df_train.head()) print(df_test.head())

接下来,将情感标签映射为数字,并使用to_categorical函数将整数编码的情感列转换为分类数据。

encoded_dict = {'anger': 0, 'fear': 1, 'joy': 2, 'love': 3, 'sadness': 4, 'surprise': 5} df_train['Sentiment'] = df_train.Sentiment.map(encoded_dict) df_test['Sentiment'] = df_train.Sentiment.map(encoded_dict) from tensorflow.keras.utils import to_categorical y_train = to_categorical(df_train.Sentiment) y_test = to_categorical(df_test.Sentiment)

获取Transformers

要使用Transformers库,首先需要安装并导入它。然后,可以从库中加载预训练的BERT模型及其分词器。

!pip install transformers import transformers from transformers import AutoTokenizer, TFBertModel tokenizer = AutoTokenizer.from_pretrained('bert-base-cased') bert = TFBertModel.from_pretrained('bert-base-cased')

分词器负责将输入文本的单词转换为令牌,而预训练的BERT模型则用于TensorFlow。这里加载的是bert-base-cased模型。

输入数据建模

在训练之前,需要使用分词器将输入文本数据转换为BERT的输入数据格式。由于已经加载了bert-base-cased,因此分词器也将是Bert-base-cased

x_train = tokenizer( text=df_train.Input.tolist(), add_special_tokens=True, max_length=70, truncation=True, padding=True, return_tensors='tf', return_token_type_ids=False, return_attention_mask=True, verbose=True) x_test = tokenizer( text=df_test.Input.tolist(), add_special_tokens=True, max_length=70, truncation=True, padding=True, return_tensors='tf', return_token_type_ids=False, return_attention_mask=True, verbose=True)

分词器接收所有必要的参数,并以BERT接受的格式返回张量。

模型构建

接下来,将使用TensorFlow的functional API来设计模型。

import tensorflow as tf from tensorflow.keras.optimizers import Adam from tensorflow.keras.callbacks import EarlyStopping from tensorflow.keras.initializers import TruncatedNormal from tensorflow.keras.losses import CategoricalCrossentropy from tensorflow.keras.metrics import CategoricalAccuracy from tensorflow.keras.utils import to_categorical from tensorflow.keras.layers import Input, Dense max_len = 70 input_ids = Input(shape=(max_len,), dtype=tf.int32, name="input_ids") input_mask = Input(shape=(max_len,), dtype=tf.int32, name="attention_mask") embeddings = bert(input_ids, attention_mask=input_mask)[0] out = tf.keras.layers.GlobalMaxPool1D()(embeddings) out = Dense(128, activation='relu')(out) out = tf.keras.layers.Dropout(0.1)(out) out = Dense(32, activation='relu')(out) y = Dense(6, activation='sigmoid')(out) model = tf.keras.Model(inputs=[input_ids, input_mask], outputs=y) model.layers[2].trainable = True

BERT层接受三个输入数组:input_ids, attention_mask, token_type_ids。在本例中,不会传递token_type_ids。对于BERT层,需要两个输入层,即input_ids和attention_mask。Embeddings包含BERT层的隐藏状态。使用GlobalMaxPooling1D然后是密集层来构建CNN层,使用BERT的隐藏状态作为输出。

模型编译

定义学习参数并编译模型。

optimizer = Adam( learning_rate=5e-05, # 这个学习率是为BERT模型设置的,取自huggingface网站 epsilon=1e-08, decay=0.01, clipnorm=1.0) # 设置损失和指标 loss = CategoricalCrossentropy(from_logits=True) metric = CategoricalAccuracy('balanced_accuracy'), # 编译模型 model.compile( optimizer=optimizer, loss=loss, metrics=metric)

学习率为5e-05,显著低于常规值。损失函数使用CategoricalCrossentropy,因为目标数据是分类数据。平衡准确度将照顾到所有类别的平均准确度。

模型训练

模型准备好后,可以使用x_train和y_train进行训练。训练和微调BERT模型需要一些时间,因此请耐心等待。

train_history = model.fit( x={'input_ids': x_train['input_ids'], 'attention_mask': x_train['attention_mask']}, y=y_train, validation_data=( {'input_ids': x_test['input_ids'], 'attention_mask': x_test['attention_mask']}, y_test ), epochs=1, batch_size=36 )

model.fit返回一个历史对象,保存了所有的训练历史。x_test在预处理后变成了一个包含'input_ids', 'attention_mask'的字典。在训练中传递input_ids和attention_mask。在验证数据中,传递测试数据。

模型评估

在测试数据上测试模型。

predicted_raw = model.predict({'input_ids': x_test['input_ids'], 'attention_mask': x_test['attention_mask']}) predicted_raw[0]

取最大概率值的索引。

y_predicted = np.argmax(predicted_raw, axis=1) y_true = df_test.Sentiment from sklearn.metrics import classification_report print(classification_report(y_true, y_predicted))

太棒了!输出是准确的。

将索引转换回情感标签:

texts = input(str('输入文本')) x_val = tokenizer( text=texts, add_special_tokens=True, max_length=70, truncation=True, padding='max_length', return_tensors='tf', return_token_type_ids=False, return_attention_mask=True, verbose=True) validation = model.predict({'input_ids': x_val['input_ids'], 'attention_mask': x_val['attention_mask']})*100 for key, value in zip(encoded_dict.keys(), validation[0]): print(key, value)

在推理步骤中,需要将模型数据格式化为训练数据的相同格式,然后调用model.predict,它返回一个概率数组,然后找到最大机会的索引,并将其映射到情感标签,这将是输出。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485