Huggingface TFBertForSequenceClassification 总是预测相同的标签
Huggingface TFBertForSequenceClassification always predicts the same label
长话短说:
我的模型总是预测相同的标签,我不知道为什么。下面是我微调的全部代码,希望有人能指出我哪里不对。
我正在使用 Huggingface 的 TFBertForSequenceClassification 进行序列分类任务,以预测德语文本中句子的 4 个标签。
我使用 bert-base-german-cased 模型,因为我不只使用小写文本(因为德语比英语更区分大小写)。
我从一个 csv 文件中获取输入,该文件是根据收到的带注释的语料库构建的。这是其中的一个示例:
0 Hier kommen wir ins Spiel Die App Cognitive At...
1 Doch wenn Athlet Lebron James jede einzelne Mu...
2 Wie kann ein Gehirn auf Hochleistung getrimmt ...
3 Wie schafft es Warren Buffett knapp 1000 Wörte...
4 Entfalte dein mentales Potenzial und werde ein...
Name: sentence_clean, Length: 3094, dtype: object
这些是我的标签,来自同一个 csv 文件:
0 e_1
1 e_4
2 e_4
3 e_4
4 e_4
不同的标签是:e_1、e_2、e_3 和 e_4
这是我用来微调模型的代码:
import pandas as pd
import numpy as np
import os
# read in data
# sentences_df = pd.read_csv('path/file.csv')
X = sentences_df.sentence_clean
Y = sentences_df.classId
# =============================================================================
# One hot encode labels
# =============================================================================
# integer encode labels
from numpy import array
from numpy import argmax
from sklearn.preprocessing import LabelEncoder
label_encoder = LabelEncoder()
Y_integer_encoded = label_encoder.fit_transform(list(Y))
# one hot encode labels
from sklearn.preprocessing import OneHotEncoder
onehot_encoder = OneHotEncoder(sparse=False)
Y_integer_encoded_reshaped = Y_integer_encoded.reshape(len(Y_integer_encoded), 1)
Y_one_hot_encoded = onehot_encoder.fit_transform(Y_integer_encoded_reshaped)
# train test split
from sklearn.model_selection import train_test_split
X_train_raw, X_test_raw, y_train, y_test = train_test_split(X, Y_one_hot_encoded, test_size=0.20, random_state=42)
# =============================================================================
# Perpare datasets for finetuning
# =============================================================================
import tensorflow as tf
physical_devices = tf.config.list_physical_devices('GPU')
tf.config.experimental.set_memory_growth(physical_devices[0], True)
from transformers import BertTokenizer, TFBertForSequenceClassification
tokenizer = BertTokenizer.from_pretrained('bert-base-german-cased') # initialize tokenizer
# tokenize trai and test sets
max_seq_length = 128
X_train_tokens = tokenizer(list(X_train_raw),
truncation=True,
padding=True)
X_test_tokens = tokenizer(list(X_test_raw),
truncation=True,
padding=True)
# create TF datasets as input for BERT model
bert_train_ds = tf.data.Dataset.from_tensor_slices((
dict(X_train_tokens),
y_train
))
bert_test_ds = tf.data.Dataset.from_tensor_slices((
dict(X_test_tokens),
y_test
))
# =============================================================================
# setup model and finetune
# =============================================================================
# define hyperparams
num_labels = 4
learninge_rate = 2e-5
epochs = 3
batch_size = 16
# create BERT model
bert_categorical_partial = TFBertForSequenceClassification.from_pretrained('bert-base-german-cased', num_labels=num_labels)
optimizer = tf.keras.optimizers.Adam(learning_rate=learninge_rate)
bert_categorical_partial.compile(optimizer=optimizer, loss='categorical_crossentropy', metrics=['accuracy'])
history = bert_categorical_partial.fit(bert_train_ds.shuffle(100).batch(batch_size),
epochs=epochs,
# batch_size=batch_size,
validation_data=bert_test_ds.shuffle(100).batch(batch_size))
这里是微调的输出:
Epoch 1/3
155/155 [==============================] - 31s 198ms/step - loss: 8.3038 - accuracy: 0.2990 - val_loss: 8.7751 - val_accuracy: 0.2811
Epoch 2/3
155/155 [==============================] - 30s 196ms/step - loss: 8.2451 - accuracy: 0.2913 - val_loss: 8.9314 - val_accuracy: 0.2779
Epoch 3/3
155/155 [==============================] - 30s 196ms/step - loss: 8.3101 - accuracy: 0.2913 - val_loss: 9.0355 - val_accuracy: 0.2746
最后,我尝试预测测试集的标签并使用混淆矩阵验证结果:
X_test_tokens_new = {'input_ids': np.asarray(X_test_tokens['input_ids']),
'token_type_ids': np.asarray(X_test_tokens['token_type_ids']),
'attention_mask': np.asarray(X_test_tokens['attention_mask']),
}
pred_raw = bert_categorical_partial.predict(X_test_tokens_new)
pred_proba = tf.nn.softmax(pred_raw).numpy()
pred = pred_proba[0].argmax(axis = 1)
y_true = y_test.argmax(axis = 1)
cm = confusion_matrix(y_true, pred)
打印输出(cm):
array([[ 0, 0, 0, 41],
[ 2, 0, 0, 253],
[ 2, 0, 0, 219],
[ 6, 0, 0, 96]], dtype=int64)
如您所见,我的准确性非常差,当我查看 cm 时,我可以看到我的模型几乎只预测一个标签。
我已经尝试了所有方法并多次 运行 模型,但我总是得到相同的结果。
我知道我正在使用的数据不是很好,我只训练大约 2k 个带有标签的句子。但我感觉准确率应该更高,更重要的是,模型不应该在 98% 的时间内只预测一个标签,对吗?
我将我正在使用的所有内容都发布到 运行 模型中,希望有人能指出我哪里出错了。
非常感谢您的帮助!
您训练了几分钟。即使是预训练的 BERT 也不够。
尝试降低学习率,以便在每个时期(前 10 个时期)后提高准确率。并训练更多的 epochs(直到你看到 10 个 epochs 的验证准确度下降)。
长话短说: 我的模型总是预测相同的标签,我不知道为什么。下面是我微调的全部代码,希望有人能指出我哪里不对。
我正在使用 Huggingface 的 TFBertForSequenceClassification 进行序列分类任务,以预测德语文本中句子的 4 个标签。
我使用 bert-base-german-cased 模型,因为我不只使用小写文本(因为德语比英语更区分大小写)。
我从一个 csv 文件中获取输入,该文件是根据收到的带注释的语料库构建的。这是其中的一个示例:
0 Hier kommen wir ins Spiel Die App Cognitive At...
1 Doch wenn Athlet Lebron James jede einzelne Mu...
2 Wie kann ein Gehirn auf Hochleistung getrimmt ...
3 Wie schafft es Warren Buffett knapp 1000 Wörte...
4 Entfalte dein mentales Potenzial und werde ein...
Name: sentence_clean, Length: 3094, dtype: object
这些是我的标签,来自同一个 csv 文件:
0 e_1
1 e_4
2 e_4
3 e_4
4 e_4
不同的标签是:e_1、e_2、e_3 和 e_4
这是我用来微调模型的代码:
import pandas as pd
import numpy as np
import os
# read in data
# sentences_df = pd.read_csv('path/file.csv')
X = sentences_df.sentence_clean
Y = sentences_df.classId
# =============================================================================
# One hot encode labels
# =============================================================================
# integer encode labels
from numpy import array
from numpy import argmax
from sklearn.preprocessing import LabelEncoder
label_encoder = LabelEncoder()
Y_integer_encoded = label_encoder.fit_transform(list(Y))
# one hot encode labels
from sklearn.preprocessing import OneHotEncoder
onehot_encoder = OneHotEncoder(sparse=False)
Y_integer_encoded_reshaped = Y_integer_encoded.reshape(len(Y_integer_encoded), 1)
Y_one_hot_encoded = onehot_encoder.fit_transform(Y_integer_encoded_reshaped)
# train test split
from sklearn.model_selection import train_test_split
X_train_raw, X_test_raw, y_train, y_test = train_test_split(X, Y_one_hot_encoded, test_size=0.20, random_state=42)
# =============================================================================
# Perpare datasets for finetuning
# =============================================================================
import tensorflow as tf
physical_devices = tf.config.list_physical_devices('GPU')
tf.config.experimental.set_memory_growth(physical_devices[0], True)
from transformers import BertTokenizer, TFBertForSequenceClassification
tokenizer = BertTokenizer.from_pretrained('bert-base-german-cased') # initialize tokenizer
# tokenize trai and test sets
max_seq_length = 128
X_train_tokens = tokenizer(list(X_train_raw),
truncation=True,
padding=True)
X_test_tokens = tokenizer(list(X_test_raw),
truncation=True,
padding=True)
# create TF datasets as input for BERT model
bert_train_ds = tf.data.Dataset.from_tensor_slices((
dict(X_train_tokens),
y_train
))
bert_test_ds = tf.data.Dataset.from_tensor_slices((
dict(X_test_tokens),
y_test
))
# =============================================================================
# setup model and finetune
# =============================================================================
# define hyperparams
num_labels = 4
learninge_rate = 2e-5
epochs = 3
batch_size = 16
# create BERT model
bert_categorical_partial = TFBertForSequenceClassification.from_pretrained('bert-base-german-cased', num_labels=num_labels)
optimizer = tf.keras.optimizers.Adam(learning_rate=learninge_rate)
bert_categorical_partial.compile(optimizer=optimizer, loss='categorical_crossentropy', metrics=['accuracy'])
history = bert_categorical_partial.fit(bert_train_ds.shuffle(100).batch(batch_size),
epochs=epochs,
# batch_size=batch_size,
validation_data=bert_test_ds.shuffle(100).batch(batch_size))
这里是微调的输出:
Epoch 1/3
155/155 [==============================] - 31s 198ms/step - loss: 8.3038 - accuracy: 0.2990 - val_loss: 8.7751 - val_accuracy: 0.2811
Epoch 2/3
155/155 [==============================] - 30s 196ms/step - loss: 8.2451 - accuracy: 0.2913 - val_loss: 8.9314 - val_accuracy: 0.2779
Epoch 3/3
155/155 [==============================] - 30s 196ms/step - loss: 8.3101 - accuracy: 0.2913 - val_loss: 9.0355 - val_accuracy: 0.2746
最后,我尝试预测测试集的标签并使用混淆矩阵验证结果:
X_test_tokens_new = {'input_ids': np.asarray(X_test_tokens['input_ids']),
'token_type_ids': np.asarray(X_test_tokens['token_type_ids']),
'attention_mask': np.asarray(X_test_tokens['attention_mask']),
}
pred_raw = bert_categorical_partial.predict(X_test_tokens_new)
pred_proba = tf.nn.softmax(pred_raw).numpy()
pred = pred_proba[0].argmax(axis = 1)
y_true = y_test.argmax(axis = 1)
cm = confusion_matrix(y_true, pred)
打印输出(cm):
array([[ 0, 0, 0, 41],
[ 2, 0, 0, 253],
[ 2, 0, 0, 219],
[ 6, 0, 0, 96]], dtype=int64)
如您所见,我的准确性非常差,当我查看 cm 时,我可以看到我的模型几乎只预测一个标签。 我已经尝试了所有方法并多次 运行 模型,但我总是得到相同的结果。 我知道我正在使用的数据不是很好,我只训练大约 2k 个带有标签的句子。但我感觉准确率应该更高,更重要的是,模型不应该在 98% 的时间内只预测一个标签,对吗?
我将我正在使用的所有内容都发布到 运行 模型中,希望有人能指出我哪里出错了。 非常感谢您的帮助!
您训练了几分钟。即使是预训练的 BERT 也不够。
尝试降低学习率,以便在每个时期(前 10 个时期)后提高准确率。并训练更多的 epochs(直到你看到 10 个 epochs 的验证准确度下降)。