- vừa được xem lúc

Finetune BERT cho bài toán che thông tin cá nhân - Phần 2: Huấn luyện và đánh giá mô hình

0 0 13

Người đăng: Trinh Quang

Theo Viblo Asia

Tổng quan

Phần 1 chúng ta đã cùng nhau xác định các bước để tạo ra một mô hình xử lý bài toán NER thông qua việc finetuning BERT

Quá trình finetune BERT cho bài toán masking thông tin cá nhân bao gồm các bước sau:

  • Chuẩn bị dữ liệu: Tùy thuộc vào mục tiêu bài toán chúng ta sẽ tập chung vào từng bộ dữ liệu cụ thể

  • Tiền xử lý dữ liệu: Xử lý dữ liệu văn bản để đưa vào mô hình BERT, bao gồm tokenization, padding, và chuyển đổi các thẻ nhãn thành số.

  • Finetune BERT: Sử dụng kiến trúc BERT pre-trained và tiếp tục training mô hình trên tập dữ liệu đã chuẩn bị. Trong quá trình này, mô hình sẽ học cách nhận dạng và che dấu các thông tin cá nhân.

  • Đánh giá và tối ưu hóa: Kiểm tra hiệu suất của mô hình trên tập dữ liệu test, và tiến hành các bước tối ưu hóa như điều chỉnh siêu tham số, thay đổi kiến trúc mô hình, hoặc thu thập thêm dữ liệu nếu cần thiết.

Vậy thì ở phần trước chúng ta đã xử lý xong 2 bước đầu tiên, trong phần 2 này mình sẽ tiếp tục với quá trình finetune BERT và đánh giá mô hình.

Huấn luyện mô hình

Chúng ta cần định nghĩa optimizer. Ở đây, đơn giản sử dụng Adam với learning rate mặc định. Người ta cũng có thể quyết định sử dụng những cái nâng cao hơn như AdamW (Adam với bản sửa lỗi suy giảm trọng số), SGD, hoặc một learning rate schedule. Tuy nhiên để đơn giản ở đây mình chỉnh sử dụng Adam()

optimizer = torch.optim.Adam(params=model.parameters(), lr=LEARNING_RATE)

Xây dựng training functions

# Defining the training function on the 80% of the dataset for tuning the bert model
def train(epoch): tr_loss, tr_accuracy = 0, 0 nb_tr_examples, nb_tr_steps = 0, 0 tr_preds, tr_labels = [], [] # put model in training mode model.train() for idx, batch in enumerate(training_loader): ids = batch['ids'].to(device, dtype = torch.long) mask = batch['mask'].to(device, dtype = torch.long) targets = batch['targets'].to(device, dtype = torch.long) outputs = model(input_ids=ids, attention_mask=mask, labels=targets) loss, tr_logits = outputs.loss, outputs.logits tr_loss += loss.item() nb_tr_steps += 1 nb_tr_examples += targets.size(0) if idx % 100==0: loss_step = tr_loss/nb_tr_steps print(f"Training loss per 100 training steps: {loss_step}") # compute training accuracy flattened_targets = targets.view(-1) # shape (batch_size * seq_len,) active_logits = tr_logits.view(-1, model.num_labels) # shape (batch_size * seq_len, num_labels) flattened_predictions = torch.argmax(active_logits, axis=1) # shape (batch_size * seq_len,) # now, use mask to determine where we should compare predictions with targets (includes [CLS] and [SEP] token predictions) active_accuracy = mask.view(-1) == 1 # active accuracy is also of shape (batch_size * seq_len,) targets = torch.masked_select(flattened_targets, active_accuracy) predictions = torch.masked_select(flattened_predictions, active_accuracy) tr_preds.extend(predictions) tr_labels.extend(targets) tmp_tr_accuracy = accuracy_score(targets.cpu().numpy(), predictions.cpu().numpy()) tr_accuracy += tmp_tr_accuracy # gradient clipping torch.nn.utils.clip_grad_norm_( parameters=model.parameters(), max_norm=MAX_GRAD_NORM ) # backward pass optimizer.zero_grad() loss.backward() optimizer.step() epoch_loss = tr_loss / nb_tr_steps tr_accuracy = tr_accuracy / nb_tr_steps print(f"Training loss epoch: {epoch_loss}") print(f"Training accuracy epoch: {tr_accuracy}")

Vì là finetuning nên việc chúng ta huấn luyện quá nhiều epoch thì sẽ dẫn đến việc mô hình quá bị fit vào dữ liệu huấn luyện mà mất đi tính tổng quát của nó (pretrain model đã được huấn luyện trên 1 tập dữ liệu lớn hơn rất nhiều). Ở đây chúng ta chỉ cần huấn luyện thêm 1,2 epochs để mô hình học được những đặc trưng mới từ dữ liệu huấn luyện

for epoch in range(EPOCHS): print(f"Training epoch: {epoch + 1}") train(epoch)

Đánh giá mô hình

Sau khi chúng ta đã huấn luyện mô hình của mình, chúng ta có thể đánh giá hiệu suất của nó trên tập kiểm tra được giữ lại (chiếm 20% dữ liệu). Lưu ý rằng ở đây sẽ không cập nhật gradient , mô hình chỉ đơn giản đưa ra các logits của nó.

def valid(model, testing_loader): # put model in evaluation mode model.eval() eval_loss, eval_accuracy = 0, 0 nb_eval_examples, nb_eval_steps = 0, 0 eval_preds, eval_labels = [], [] with torch.no_grad(): for idx, batch in enumerate(testing_loader): ids = batch['ids'].to(device, dtype = torch.long) mask = batch['mask'].to(device, dtype = torch.long) targets = batch['targets'].to(device, dtype = torch.long) outputs = model(input_ids=ids, attention_mask=mask, labels=targets) loss, eval_logits = outputs.loss, outputs.logits eval_loss += loss.item() nb_eval_steps += 1 nb_eval_examples += targets.size(0) if idx % 100==0: loss_step = eval_loss/nb_eval_steps print(f"Validation loss per 100 evaluation steps: {loss_step}") # compute evaluation accuracy flattened_targets = targets.view(-1) # shape (batch_size * seq_len,) active_logits = eval_logits.view(-1, model.num_labels) # shape (batch_size * seq_len, num_labels) flattened_predictions = torch.argmax(active_logits, axis=1) # shape (batch_size * seq_len,) # now, use mask to determine where we should compare predictions with targets (includes [CLS] and [SEP] token predictions) active_accuracy = mask.view(-1) == 1 # active accuracy is also of shape (batch_size * seq_len,) targets = torch.masked_select(flattened_targets, active_accuracy) predictions = torch.masked_select(flattened_predictions, active_accuracy) eval_labels.extend(targets) eval_preds.extend(predictions) tmp_eval_accuracy = accuracy_score(targets.cpu().numpy(), predictions.cpu().numpy()) eval_accuracy += tmp_eval_accuracy #print(eval_labels) #print(eval_preds) labels = [id2label[id.item()] for id in eval_labels] predictions = [id2label[id.item()] for id in eval_preds] #print(labels) #print(predictions) eval_loss = eval_loss / nb_eval_steps eval_accuracy = eval_accuracy / nb_eval_steps print(f"Validation Loss: {eval_loss}") print(f"Validation Accuracy: {eval_accuracy}") return labels, predictions

Chúng ta có thể dễ dàng tính được

Validation Loss: 0.02922834331467394
Validation Accuracy: 0.9602300367723403

Tuy nhiên, chỉ số "Validation Accuracy" là không đáng tin cậy, vì nhiều nhãn là "ngoài" (O), thậm chí sau khi loại bỏ các dự đoán trên các token [PAD]. Điều quan trọng là xem xét độ chính xác, giá trị f1 của từng thẻ riêng lẻ.

from seqeval.metrics import classification_report
labels, predictions = valid(model, testing_loader)
print(classification_report([labels], [predictions]))
precision recall f1-score support geo 0.79 0.88 0.83 4613 gpe 0.89 0.89 0.89 1523 org 0.71 0.56 0.63 2761 per 0.78 0.81 0.79 2183 tim 0.82 0.81 0.81 1772 micro avg 0.79 0.79 0.79 12852 macro avg 0.80 0.79 0.79 12852
weighted avg 0.79 0.79 0.79 12852

Có một cánh nhanh để kiểm tra tính hiệu quả của mô hình, chúng ta có thể đưa vào một câu của tập test hoặc câu bất kỳ nào đó để kiểm tra

from transformers import pipeline pipe = pipeline(task="token-classification", model=model.to("cpu"), tokenizer=tokenizer, aggregation_strategy="simple")
pipe("My name is Niels and New York is a city")

Kết quả khá ổn khi mô hình có thể bắt được các token được đánh nhãn là 'per' hoặc 'geo', chúng ta có thể sử đánh giá trên trên một tập dữ liệu lớn để kiểm tra tính hiệu quả và xem xét những điểm cần tối ưu.

[{'end': None, 'entity_group': 'per', 'score': 0.71306735, 'start': None, 'word': 'ni'}, {'end': None, 'entity_group': 'per', 'score': 0.8921481, 'start': None, 'word': '##els'}, {'end': None, 'entity_group': 'geo', 'score': 0.95278734, 'start': None, 'word': 'new york'}]

Lưu mô hình

Cuối cùng, hãy lưu các tệp mô hình và bộ mã hóa để chúng ta có thể dễ dàng sử dụng lại chúng sau này. Có 2 options:

  • Chúng ta có thể lưu tất cả cục bộ, chỉ đơn giản bằng cách gọi model.save_pretrained() và tokenizer.save_pretrained(), cung cấp đường dẫn thư mục làm đối số.
  • Cách khác là có thể đẩy các tệp lên HuggingFace hub. Bằng cách này, bạn có thể chia sẻ mô hình của mình với cộng đồng. Tất cả các tệp sẽ được theo dõi bởi git, vì mỗi mô hình trên hub có kho lưu trữ git riêng của nó. Cả hai tùy chọn đều cho phép tái sử dụng mô hình/bộ mã hóa bằng cách sử dụng phương thức from_pretrained()

Các bạn có thể sử dụng đoạn code dưới đây để thực hiện cách 2 nhé

from huggingface_hub import notebook_login
notebook_login()
model_name = "bert-finetuned-ner" # upload files to the hub
tokenizer.push_to_hub( repo_path_or_name=model_name, organization="nielsr", commit_message="Add tokenizer", use_temp_dir=True,
)
model.push_to_hub( repo_path_or_name=model_name, organization="nielsr", commit_message="Add model", use_temp_dir=True,
)

Kết luận

Trong bài viết này, chúng ta đã thảo luận về cách Finetune mô hình BERT để giải quyết bài toán che thông tin cá nhân. Chúng ta đã xây dựng một pipeline từ xử lý dữ liệu, đào tạo và đánh giá mô hình, sau đó sử dụng mô hình sau khi training để thực hiện suy luận nhanh chóng trên các câu mới. Kết quả cho thấy việc Finetune BERT đạt hiệu suất ổn trên bộ dữ liệu này, với độ chính xác, F1 ở tương đối tốt. Điều này cho thấy BERT là một nền tảng mạnh mẽ có thể được điều chỉnh để giải quyết các bài toán NLP phức tạp như che thông tin cá nhân. Cũng như cách chia sẻ chúng trên HuggingFace hub để dễ dàng sử dụng lại hoặc chia sẽ với cộng đồng. Hy vọng rằng bài viết này đã cung cấp cho bạn một cái nhìn tổng quan về cách Finetune BERT cho bài toán che thông tin cá nhân. Hãy tiếp tục khám phá và sáng tạo với các kỹ thuật học máy và các bài toán thực tế nhiều hơn nữa để tạo thêm nhiều giá trị mới nhé.

Bình luận

Bài viết tương tự

- vừa được xem lúc

Toonify: Biến chân dung thành nhân vật hoạt hình với StyleGAN

Hello mọi người và chúc mừng năm mới!!. .

0 0 105

- vừa được xem lúc

[Deep Learning] Kỹ thuật Dropout (Bỏ học) trong Deep Learning

. Trong bài viết này, mình xin phép giới thiệu về Dropout (Bỏ học) trong mạng Neural, sau đó là mình sẽ có 1 số đoạn code để xem Dropout ảnh hưởng thế nào đến hiệu suất của mạng Neural. 1.1. Dropout trong mạng Neural là gì.

0 0 63

- vừa được xem lúc

Triển khai các mô hình với OpenVINO

I. Giới thiệu.

0 0 70

- vừa được xem lúc

ArcFace: Một Bước Tiến Trong Nhận Diện Khuôn Mặt

Lời Giới Thiệu. Các mô hình Deep Convolutional Neural Networks (DCNN) đã trở thành một lựa chọn thường nhật cho việc bóc tách các đặc điểm của khuôn mặt và đã chứng tỏ được các ưu thế vượt trội trong

0 0 448

- vừa được xem lúc

Cats vs Dogs Classification using CNN Keras

Overview. Trong bài viết truớc Spark - Distributed ML model with Pandas UDFs mình có sử dụng model CNN keras để classify Dogs vs Cats vì bài viết quá dài nên phần hướng dẩn train model mình viết ở đây

0 0 38

- vừa được xem lúc

Sinh ảnh cùng với MixNMatch: độ chân thực đến đáng gờm

Tổng quan. .

0 0 29