BERT HuggingFace 给出 NaN 损失
Posted
技术标签:
【中文标题】BERT HuggingFace 给出 NaN 损失【英文标题】:BERT HuggingFace gives NaN Loss 【发布时间】:2020-10-07 16:41:56 【问题描述】:我正在尝试为文本分类任务微调 BERT,但我得到了 NaN 损失,无法弄清楚原因。
首先我定义一个 BERT 标记器,然后标记我的文本:
from transformers import DistilBertTokenizer, RobertaTokenizer
distil_bert = 'distilbert-base-uncased'
tokenizer = DistilBertTokenizer.from_pretrained(distil_bert, do_lower_case=True, add_special_tokens=True,
max_length=128, pad_to_max_length=True)
def tokenize(sentences, tokenizer):
input_ids, input_masks, input_segments = [],[],[]
for sentence in tqdm(sentences):
inputs = tokenizer.encode_plus(sentence, add_special_tokens=True, max_length=25, pad_to_max_length=True,
return_attention_mask=True, return_token_type_ids=True)
input_ids.append(inputs['input_ids'])
input_masks.append(inputs['attention_mask'])
input_segments.append(inputs['token_type_ids'])
return np.asarray(input_ids, dtype='int32'), np.asarray(input_masks, dtype='int32'), np.asarray(input_segments, dtype='int32')
train = pd.read_csv('train_dataset.csv')
d = train['text']
input_ids, input_masks, input_segments = tokenize(d, tokenizer)
接下来,我加载整数标签,它们是:0、1、2、3。
d_y = train['label']
0 0
1 1
2 0
3 2
4 0
5 0
6 0
7 0
8 3
9 1
Name: label, dtype: int64
然后我加载预训练的 Transformer 模型并在其上放置层。我在编译模型时使用了 SparseCategoricalCrossEntropy Loss:
from transformers import TFDistilBertForSequenceClassification, DistilBertConfig, AutoTokenizer, TFDistilBertModel
distil_bert = 'distilbert-base-uncased'
optimizer = tf.keras.optimizers.RMSprop(learning_rate=0.0000001)
config = DistilBertConfig(num_labels=4, dropout=0.2, attention_dropout=0.2)
config.output_hidden_states = False
transformer_model = TFDistilBertModel.from_pretrained(distil_bert, config = config)
input_ids_in = tf.keras.layers.Input(shape=(25,), name='input_token', dtype='int32')
input_masks_in = tf.keras.layers.Input(shape=(25,), name='masked_token', dtype='int32')
embedding_layer = transformer_model(input_ids_in, attention_mask=input_masks_in)[0]
X = tf.keras.layers.Bidirectional(tf.keras.layers.LSTM(50, return_sequences=True, dropout=0.1, recurrent_dropout=0.1))(embedding_layer)
X = tf.keras.layers.GlobalMaxPool1D()(X)
X = tf.keras.layers.Dense(50, activation='relu')(X)
X = tf.keras.layers.Dropout(0.2)(X)
X = tf.keras.layers.Dense(4, activation='softmax')(X)
model = tf.keras.Model(inputs=[input_ids_in, input_masks_in], outputs = X)
for layer in model.layers[:3]:
layer.trainable = False
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['sparse_categorical_accuracy'],
)
最后,我使用之前标记化的 input_ids 和 input_masks 作为模型的输入来运行模型,并在第一个 epoch 后获得 NAN Loss:
model.fit(x=[input_ids, input_masks], y = d_y, epochs=3)
Epoch 1/3
20/20 [==============================] - 4s 182ms/step - loss: 0.9714 - sparse_categorical_accuracy: 0.6153
Epoch 2/3
20/20 [==============================] - 0s 19ms/step - loss: nan - sparse_categorical_accuracy: 0.5714
Epoch 3/3
20/20 [==============================] - 0s 20ms/step - loss: nan - sparse_categorical_accuracy: 0.5714
<tensorflow.python.keras.callbacks.History at 0x7fee0e220f60>
编辑:模型在第一个 epoch 计算损失,但它开始返回 NaN 在第二个纪元。是什么导致了这个问题???
有人对我做错了什么有任何想法吗? 欢迎所有建议!
【问题讨论】:
这个答案可能会有所帮助:=> ***.com/a/40434284/8405902 我看过它并没有真正帮助 @beginner 你解决了吗?我面临同样的问题。 【参考方案1】:问题出在这里:
X = tf.keras.layers.Dense(1, activation='softmax')(X)
在网络的末端,你只有一个神经元,对应一个类。 0 类的输出概率始终为 100%。如果您有 0、1、2、3 类,则最后需要有 4 个输出。
【讨论】:
我已将其更改为 4 个输出,但问题似乎仍然存在。 它计算第一个时期的损失,但从第二个时期开始,以后的损失是 NaN。 现在的代码 sn-p 看起来不错。获得 nans 的最常见原因是除以零。它可能来自数据,例如,您可能将掩码设置为全零。【参考方案2】:我还建议在使用数据集进行训练和评估之前从 pandas 数据框中删除 NA 值。
train = pd.read_csv('train_dataset.csv')
d = train['text']
d = d.dropna()
【讨论】:
【参考方案3】:由于未指定num_labels
而出现问题
在最终输出层,默认 K = 1(标签数),如前所述
\sigma(\vecz)_i=\frace^z_i\sum_j=1^K e^z_j
因此,在进行多类分类时,我们需要在微调时提供 num_labels。
model = TFBertForSequenceClassification.from_pretrained('bert-base-cased', num_labels=5)
【讨论】:
【参考方案4】:我有一个类似的问题,我的模型仅在一个时期的最后一批产生 NaN 损失。所有其他批次均产生典型的损失值。就我而言,问题在于批次的大小并不总是相等。因此,该模型产生了 NaN 损失。在我使所有批次的大小相同之后,NaN 就消失了。如果您的情况也是如此,可能也值得调查。
【讨论】:
以上是关于BERT HuggingFace 给出 NaN 损失的主要内容,如果未能解决你的问题,请参考以下文章
如何微调 HuggingFace BERT 模型以进行文本分类 [关闭]
如何在 HuggingFace Transformers 库中获取中间层的预训练 BERT 模型输出?