Giải quyết vấn đề độ chính xác của mô hình sau khi huấn luyện LLM

Khi tiếp tục tiền huấn luyện (continual pre-training) dựa trên mô hình Qwen2.5-coder, trọng số của mô hình được lưu trữ tăng gấp đôi so với phiên bản gốc (Qwen2.5-coder 3b có kích thước 5 GB, sau khi huấn luyện và lưu trữ bằng safetensor là hơn 10 GB). Vấn đề này được phát hiện ngay sau khi hoàn thành quá trình huấn luyện, nhưng vì nó vẫn hoạt động bình thường khi sử dụng vllm để tải và lúc đó còn nhiều việc khác cần làm, nên tạm thời chưa xử lý. Gần đây, trong quá trình chuẩn bị triển khai, tôi đã điều tra sâu hơn về sự bất thường của trọng số mô hình. Hai yếu tố có thể dẫn đến thay đổi trọng số trước và sau khi huấn luyện:

  1. Số lượng giá trị bằng không trong trọng số đã thay đổi.
  2. Độ chính xác lưu trữ đã thay đổi.
Yếu tố đầu tiên khó có khả năng gây ra sự gia tăng gấp đôi kích thước của mô hình, do đó ưu tiên điều tra vấn đề liên quan đến độ chính xác lưu trữ. Mô hình Qwen2.5 series nên được lưu trữ ở độ chính xác fp16. Dưới đây là mã lệnh kiểm tra độ chính xác của mô hình:
from transformers import AutoModel

model = AutoModel.from_pretrained("DUONG_DAN")
print(model)
with open("qwen2.5-coder-3b-model_parameters.txt", "w") as f:
    for ten, tham_so in model.named_parameters():
        f.write(f"Layer: {ten}\n")
        f.write(f"Shape: {tham_so.shape}\n")
        f.write(f"Dtype: {tham_so.dtype}\n")
        f.write(f"Number of parameters: {tham_so.numel()}\n")
        f.write("---\n")
Sau khi chạy, thấy Shape và Dtype trước và sau huấn luyện đều giống nhau, điều này khiến tôi nghi ngờ rằng phương thức `from_pretrained` mặc định chỉ định độ chính xác tải (torch_dtype)? Dùng cách khác để xem xét độ chính xác của mô hình:
from safetensors import safe_open

with safe_open("DUONG_DAN.safetensors", framework="pt") as f:
    for ten_tensor in f.keys():
        tensor = f.get_tensor(ten_tensor)
        print(f"Tensor: {ten_tensor}")
        print(f"Data type: {tensor.dtype}")
Kết quả cho thấy:
# Độ chính xác trước huấn luyện
Data type: torch.bfloat16

# Độ chính xác sau huấn luyện
Data type: torch.float32
Vì khung huấn luyện sử dụng llama-factory, tôi kiểm tra các tham số huấn luyện. Chỉ tìm thấy một tham số liên quan đến độ chính xác:
bf16: true
Nhưng kết quả không như mong đợi, hoặc là thiếu một số tham số cấu hình, hoặc là lỗi từ llama-factory. Thử chuyển đổi độ chính xác đơn giản:
from transformers import AutoModel
import safetensors.torch

model = AutoModel.from_pretrained("DUONG_DAN")
model = model.half()
safetensors.torch.save_file(model.state_dict(), 'new_model.safetensors')
Mô hình này gặp hai vấn đề:
  1. Mô hình có độ chính xác fp16, phù hợp cho suy luận nhưng nếu muốn tiếp tục huấn luyện thì cần bf16 để tránh mất mát hoặc bùng nổ gradient.
  2. Mô hình chỉ có một tệp safetensor, không tiện lợi cho sử dụng.
Cách lưu trữ khác:
import torch
from transformers import Qwen2ForCausalLM

duong_dan = "DUONG_DAN"
model = Qwen2ForCausalLM.from_pretrained(duong_dan)
model = model.to(dtype=torch.bfloat16)
model.save_pretrained("DUONG_DAN_MOI")
Kết quả lưu trữ là một thư mục chứa các tệp chính như safetensor, config.json, generation_config.json, có thể dùng trực tiếp với vllm. Tuy nhiên, khi thử suy luận, vllm báo lỗi:
OSError: Không thể tải tokenizer cho '...'. Nếu bạn cố gắng tải từ 'https://huggingface.co/models', đảm bảo không có thư mục cục bộ cùng tên. Đảm bảo '...' là đường dẫn đúng tới thư mục chứa tất cả các tệp cần thiết cho tokenizer Qwen2TokenizerFast.
Rõ ràng tokenizer cũng cần được lưu trữ riêng biệt. Cập nhật mã lệnh:
import torch
from transformers import AutoTokenizer, Qwen2ForCausalLM

duong_dan = "DUONG_DAN"
model = Qwen2ForCausalLM.from_pretrained(duong_dan)
tokenizer = AutoTokenizer.from_pretrained(duong_dan)
model = model.to(dtype=torch.bfloat16)
model.save_pretrained("DUONG_DAN_MOI")
tokenizer.save_pretrained("DUONG_DAN_MOI")
Sau khi sửa đổi, mô hình có thể dễ dàng tải và suy luận với vllm.

Thẻ: Transformers safetensors vLLM Qwen2ForCausalLM bfloat16

Đăng vào ngày 9 tháng 6 lúc 17:36