Я делаю классификацию на основе токенов, используя предварительно обученную BERT-модель для tenorflow, чтобы автоматически отмечать причины и следствия в предложениях.
Для доступа к BERT я использую интерфейс TFBertForTokenClassification из huggingface: https://huggingface.co/transformers/model_doc/bert.html#tfbertfortokenclassification.
Все предложения, которые я использую для обучения, преобразуются в токены (в основном отображение слов в числа) в соответствии с BERT-токенизатором, а затем дополняются до определенной длины перед обучением, поэтому, когда одно предложение имеет только 50 токенов, а другое - только 30 первый заполняется 50 маркерами падов, а второй - 70 из них, чтобы получить универсальную длину предложения ввода 100.
Затем я обучаю свою модель предсказанию для каждого токена, к какой метке принадлежит этот токен; является ли это частью причины, следствия или ничего из них.
Однако во время обучения и оценки моя модель также делает прогнозы для PAD-токенов, и они также учитываются в точности модели. Поскольку PAD-токены очень легко предсказать для модели (они всегда имеют один и тот же токен, и все они имеют метку none, что означает, что они не относятся ни к причине, ни к следствию предложения), они действительно искажают точность моей модели.
Например, если у вас есть предложение, содержащее 30 слов - ›30 токенов, и вы дополняете все предложения до длины 100, тогда это предложение получит оценку 70%, даже если модель не предсказала правильно ни один из реальных токенов. Таким образом, я очень быстро получаю точность обучения и проверки 90 +%, хотя модель плохо работает на реальных токенах падов.
Я думал, что маска внимания предназначена для решения этой проблемы, но, похоже, это не так.
Наборы входных данных создаются следующим образом:
def example_to_features(input_ids,attention_masks,token_type_ids,label_ids):
return {"input_ids": input_ids,
"attention_mask": attention_masks},label_ids
train_ds = tf.data.Dataset.from_tensor_slices((input_ids_train,attention_masks_train,token_ids_train,label_ids_train)).map(example_to_features).shuffle(buffer_size=1000).batch(32)
Создание модели:
from transformers import TFBertForTokenClassification
num_epochs = 30
model = TFBertForTokenClassification.from_pretrained('bert-base-uncased', num_labels=3)
model.layers[-1].activation = tf.keras.activations.softmax
optimizer = tf.keras.optimizers.Adam(learning_rate=1e-6)
loss = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True)
metric = tf.keras.metrics.SparseCategoricalAccuracy('accuracy')
model.compile(optimizer=optimizer, loss=loss, metrics=[metric])
model.summary()
А потом тренирую вот так:
history = model.fit(train_ds, epochs=num_epochs, validation_data=validate_ds)
Кто-нибудь сталкивался с этой проблемой до сих пор или знает, как исключить прогнозы на токенах падов из точности модели во время обучения и оценки?