BERT HuggingFace дает потерю NaN - PullRequest
1 голос
/ 17 июня 2020

Я пытаюсь точно настроить BERT для задачи классификации текста, но получаю NaN-потери и не могу понять почему.

Сначала я определяю BERT -tokenizer, а затем токенизировать мой текст:

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

Затем я загружаю предварительно обученный трансформатор модель и наложите на нее слои. Я использую 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 в качестве входных данных для модели, и получаю 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>

РЕДАКТИРОВАТЬ: Модель вычисляет потери в первую эпоху, но начинает возвращать NaN во второй эпохе. Что могло быть причиной этой проблемы ???

Есть ли у кого-нибудь идеи о том, что я делаю неправильно? Все предложения приветствуются!

Ответы [ 2 ]

2 голосов
/ 18 июня 2020

Проблема здесь:

X = tf.keras.layers.Dense(1, activation='softmax')(X)

В конце сети у вас есть только один нейрон, соответствующий одному классу. Вероятность выхода всегда равна 100% для класса 0. Если у вас есть классы 0, 1, 2, 3, вам нужно иметь 4 выхода в конце.

0 голосов
/ 22 июня 2020

Я бы также предложил удалить значения NA из кадра данных pandas перед использованием набора данных для обучения и оценки.

train = pd.read_csv('train_dataset.csv')
d = train['text']
d = d.dropna()
...