Skip to content

Các thí nghiệm liên quan tới LLMs cho tiếng Việt (insprised by Physics of LLMs Series)

Notifications You must be signed in to change notification settings

symato/physics_of_llms

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Tỉa và mapping vocab sao cho model chỉ sinh ra tiếng Anh và Việt

  • Các open source LLMs hiện tại khi dịch Anh, Việt thi thoảng model output tiếng Tàu
  • Bộ từ vựng Anh Việt có lẽ chỉ chiếm 1/2 trong tổng số 100k - 200k vocab size. Khi tỉa gọn lại thì sẽ giúp:
    • Không thể ouptut tokens nào khác ngoài En hoặc Vi
    • Giảm vram khi infer và finetune embeddings
    • Tăng tốc độ infer và finetune

llama 3.1 405b vẫn hallu ra tiếng Trung trong tác vụ dịch Anh Việt

Cách làm

  • Tạo En, Vi dataset chứa các tài liệu tiếng Anh Việt và giả sử đó là toàn bộ nội dung của 2 ngôn ngữ

  • Dùng En, Vi dataset trên chạy qua tokenizer để lọc lấy những tokens chỉ thuộc về En và Vi => Mảng used_token_ids

  • Dồn embedding bằng cách map used_token_ids[i] => i (original token id => new token id)

Tham khảo tác dụng của giảm tải vocab và can thiệp vào inference

Triển khai

  • Dataset
  • Lọc theo thống kê mới giảm được gần một nửa (qwen vocab)
    • bị mất một số emoji
  • Cần kết hợp với lọc theo bảng mã unicode
    • giữ lại emoji
    • loại bỏ cjk, thailand, chữ tượng hình ...
  • Target bộ từ vựng ~96k (63%)
  • Tạo final vocab từ qwen__1000__20000

Đối tượng thực hành

huggingface-cli download Qwen/Qwen2.5-1.5B-Instruct --local-dir ../Qwen2.5-1.5B-Instruct

python3 model_edit.py -m ../Qwen2.5-1.5B-Instruct -t trimm_vocab

python3 model_chat.py ../Qwen2.5-1.5B-Instruct
# Bạn: Translate following sentence into Chinese: tôi tên là Lý Quốc Dân
# Bot: 我的名字是李国定
# ../Qwen2.5-1.5B-Instruct: timespent 1.31 seconds

python3 model_chat.py ../Qwen2.5-1.5B-Instruct__trimm_vocab
# Bạn: Translate following sentence into Chinese: tôi tên là Lý Quốc Dân
# Bot: My name is Li Guo Dan.
# ../Qwen2.5-1.5B-Instruct__trimm_vocab: timespent 1.31 seconds

Vì bộ vocab mới chỉ hỗ trợ tiếng Anh và Việt là chính nên qwen không thể nói tiếng Trung được nữa


Physics of LMs: Sau khi tỉa gọn, từng bước một mở rộng vocab

  • tạo bộ từ điển từ ghép tiếng Việt thông dụng và chiếm nhiều tokens nhất, chỉ cần khoảng < 10k
# `impact = freq * (qwen_tokens_count - 1)` (`freq` là tần suất sử dụng của từ đó trong corpus)
xzcat data/vi_words_impact.jsonl.xz | head -n 10
{"word": "có▁thể",     "impact": 328134, "qwen_tokens": ["", " thể"], "freq": 328134, "qwen_tokens_count": 2}
{"word": "sử▁dụng",    "impact": 145168, "qwen_tokens": [" sử", " dụng"], "freq": 145168, "qwen_tokens_count": 2}
{"word": "thời▁gian",  "impact": 140172, "qwen_tokens": [" thời", " g", "ian"], "freq": 70086, "qwen_tokens_count": 3}
{"word": "Tại▁sao",    "impact": 109010, "qwen_tokens": [" Tại", " sa", "o"], "freq": 54505, "qwen_tokens_count": 3}
{"word": "Việt▁Nam",   "impact": 98771, "qwen_tokens": [" Việt", " Nam"], "freq": 98771, "qwen_tokens_count": 2}
{"word": "Hoa▁Kỳ",     "impact": 97200, "qwen_tokens": ["H", "oa", " Kỳ"], "freq": 48600, "qwen_tokens_count": 3}
{"word": "Tuy▁nhiên",  "impact": 94114, "qwen_tokens": ["T", "uy", " nhiên"], "freq": 47057, "qwen_tokens_count": 3}
{"word": "nghiên▁cứu", "impact": 83673, "qwen_tokens": [" nghiên", " cứu"], "freq": 83673, "qwen_tokens_count": 2}
{"word": "thay▁đổi",   "impact": 79270, "qwen_tokens": ["th", "ay", " đổi"], "freq": 39635, "qwen_tokens_count": 3}
{"word": "hoạt▁động",  "impact": 77248, "qwen_tokens": [" hoạt", " động"], "freq": 77248, "qwen_tokens_count": 2}

xzcat data/vi_words_impact.jsonl.xz | head -n 1000 | tail -n 10 
{"word": "Quân▁đoàn",  "impact": 5030, "qwen_tokens": [" Quân", " đoàn"], "freq": 5030, "qwen_tokens_count": 2}
{"word": "Tương▁tự",   "impact": 5028, "qwen_tokens": ["T", "ương", " tự"], "freq": 2514, "qwen_tokens_count": 3}
{"word": "Tư▁lệnh",    "impact": 5025, "qwen_tokens": ["", " lệnh"], "freq": 5025, "qwen_tokens_count": 2}
{"word": "hương▁vị",   "impact": 5017, "qwen_tokens": [" hương", " vị"], "freq": 5017, "qwen_tokens_count": 2}
{"word": "thị▁xã",     "impact": 5016, "qwen_tokens": [" thị", ""], "freq": 5016, "qwen_tokens_count": 2} 
{"word": "con▁số",     "impact": 5011, "qwen_tokens": ["con", " số"], "freq": 5011, "qwen_tokens_count": 2}  
{"word": "đánh▁dấu",   "impact": 5011, "qwen_tokens": [" đánh", " dấu"], "freq": 5011, "qwen_tokens_count": 2}
{"word": "lạm▁dụng",   "impact": 5010, "qwen_tokens": ["l", "ạm", " dụng"], "freq": 2505, "qwen_tokens_count": 3}
{"word": "dân▁chủ",    "impact": 5001, "qwen_tokens": [" dân", " chủ"], "freq": 5001, "qwen_tokens_count": 2}
{"word": "hiến▁pháp",  "impact": 5000, "qwen_tokens": ["hi", "ến", " pháp"], "freq": 2500, "qwen_tokens_count": 3}

xzcat data/vi_words_impact.jsonl.xz | head -n 2000 | tail -n 10 
{"word": "nhân▁khẩu",  "impact": 2388, "qwen_tokens": [" nhân", " khẩu"], "freq": 2388, "qwen_tokens_count": 2}
{"word": "tinh▁trùng", "impact": 2386, "qwen_tokens": ["t", "inh", " trùng"], "freq": 1193, "qwen_tokens_count": 3}
{"word": "bồi▁dưỡng",  "impact": 2386, "qwen_tokens": ["b", "ồi", " dưỡng"], "freq": 1193, "qwen_tokens_count": 3}
{"word": "Tòa▁Thánh",  "impact": 2386, "qwen_tokens": ["T", "òa", " Thánh"], "freq": 1193, "qwen_tokens_count": 3}
{"word": "thứ▁tự",     "impact": 2384, "qwen_tokens": [" thứ", " tự"], "freq": 2384, "qwen_tokens_count": 2} 
{"word": "The▁review", "impact": 2383, "qwen_tokens": ["The", " review"], "freq": 2383, "qwen_tokens_count": 2}
{"word": "sai▁lệch",   "impact": 2382, "qwen_tokens": [" sai", " lệ", "ch"], "freq": 1191, "qwen_tokens_count": 3}
{"word": "Tham▁mưu",   "impact": 2382, "qwen_tokens": ["Th", "am", " m", "ưu"], "freq": 794, "qwen_tokens_count": 4}
{"word": "quý▁tộc",    "impact": 2382, "qwen_tokens": [" quý", " tộc"], "freq": 2382, "qwen_tokens_count": 2}
{"word": "Hậu▁Giang",  "impact": 2379, "qwen_tokens": ["H", "ậu", " Gi", "ang"], "freq": 793, "qwen_tokens_count": 4}

=> Chọn khoảng 1k - 2k từ ghép để mở rộng vocab là đủ tạo impact

  • lọc và map những từ ghép này vào token ids mới

  • tìm các cách hiệu quả để khởi tạo embedding values của tokens mới => sử dụng embedding của từ TA tương đương!

    • Với 1 từ được chọn, tìm ra 1-3 câu liên quan tới từ đó:
      • thay toàn bộ embedding values của từ được chọn băng 01 embedding value mới được init bằng nhiều cách:
        • embedding value của từ đơn tương ứng trong tiếng Anh
        • lấy trung bình cộng của các embedding values của các tokens của từ đó
        • lấy trung bình cộng của toàn bộ embedding values của các từ gần với nó (trong TV và các ngôn ngữ khác) gần ở đây có thể là về ý nghĩa, về embdding values hoặc bất kỳ độ đo hợp lý nào ...
    • làm thế nào để đo lường được hiệu quả?
      • tính sự khác biệt của output (logits diff / perpelexity ...) trong các phép thay thế, khác biệt thấp nhất => hiệu quả nhất?
    • Việc lựa chọn embedding values có thực sự quan trọng? Vì đằng nào cũng cần continue pretrain.
  • Sinh dữ liệu tổng hợp giúp tạo và massage new embeddings cho ~1k từ tại data/vi_words_similarity.jsonl

  • Mát xa new embeddings (giữ nguyên old embeddings)

    • Sau khi tune new embeddings, cần thay thế giá trị gốc của old embeddings, ở cuối chu kỳ update params hoặc sau khi train xong.
  • freeze most layers, finetune embeddings và vài low layers trước

    • Lý do: từ vựng, ngữ pháp, các skills ngôn ngữ tập trung nhiều ở low layers
  • sau đó finetune toàn bộ model (lora + embedding or full finetune)

    • ./finetune_qwen__3_final.sh hỗ trợ 7b trên 40g vram
  • build datasets và giáo án huấn luyện phù hợp

python3 model_edit.py -t trimm_vocab

# `101011` làm tròn `101056` => 101011 - 101055 không dùng tới => kiểm tra xem embedding của nó có thay đổi không.
# Hãy gán nó == 0 để dễ check.

python3 model_edit.py -m ../Qwen2.5-1.5B-Instruct__trimm_vocab -t extend_vocab
# 101011 - 101055 được gán 0
# 102075 - 102079 được gán 0 too.

python3 model_edit.py -m ../Qwen2.5-1.5B-Instruct__extend_vocab__1_embeddings_massage -t view_embeddings

Bài toán: cho một từ (ví dụ "thực hiện") là thế nào để tìm ra một embding value mà khi dùng nó để thay thế chuỗi tokens "qwen_tokens": [" thực", " hiện"] trong các đoạn text mà nó xuất hiện thì không làm thay đổi đầu ra của model.

Đầu ra ở đây là một giá trị càng gần 0 càng tốt (0 = không thay đổi), có thể là logits diff hoặc perplexity,

Bạn: tạo ra một câu hoàn chỉnh với từ "thực hiện" Bot: "Tôi đã thực hiện kế hoạch của mình thành công."

Giờ ta sẽ mask từ "thực hiện" và được "Tôi đã ___ kế hoạch của mình thành công.", giờ ta để LLM tự điền vào chỗ trống 01 token thì liệu nó có tìm ra token có embedding value hợp lý nhất cho từ "thực hiện" không?

Hidden value (embedding) ở layer cuối, khi nhân với lm_head để tạo logits và chọn ra vị trí có logits cao nhất làm token_id, lm_head value ở ví trí đó với qwen 1.5 chính là embedding value vì qwen 1.5 dùng tied embeddings.

Câu hỏi

  • Với mỗi newly added token
    • Cần khoảng bao nhiêu samples liên quan để nó trở nên có hiệu quả? (bắt đầu xuất hiện trong inference)
    • Cần khoảng bao nhiêu samples liên quan để LLM sử dụng nó thuần thục?
    • => cần định nghĩa thế nào là sử dụng thuần thục?
      • perplexity?

Thử nghiệm In-context Pretraining xem khi trộn lẫn training sample trong ctxlen ảnh hưởng gì tới model?

Thử nghiệm Block Expansion

Thử nghiệm Layer Swapping

Physics of LMs: làm thí nghiệm về Knowledge Storage, Extraction and Manipulation

Physics of LMs: làm thí nghiệm TinyStories về học languages

  • Build dataset theo một hướng khác? TinyFantasy? TinyFunny?
  • Mở rộng: xây bộ data để chuyển knowledge đã học từ Vi => En
  • Mở rộng: Từ hiểu ngôn ngữ tới làm thơ và làm thơ thuận nghịch độc
  • Ý tưởng: dùng kỹ thuật FIM (fill in middle) của code LLM để tạo thơ có vần Yêu cầu chữ cuối phải rơi vào 1 từ hoặc 1 vần nào đó ...

About

Các thí nghiệm liên quan tới LLMs cho tiếng Việt (insprised by Physics of LLMs Series)

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published