[실험] token_size 변경 후 PPL 변화 측정
1. 개요
- 원본 코드에서 원하는 token_size는 너무 길어서 현재 컴퓨팅 파워로는 결과를 보기 어려움.
- 적절한 token_size를 선택할 필요가 있음.
- 원본 코드의 token_size는 activation.py 실행에 약 7시간 소요.
- 따라서 token_size를 24K와 2.4M로 조절하여 PPL값을 분석한다.
- Activation 값은 0으로 고정한다.
2. Tokenizer.py
- Train token은 0번부터 원하는 size까지 조절하여 저장한다.
- valid token은 train token size까지는 버리고 그 뒤부터 저장한다.
import os
import torch
from datasets import load_dataset
from transformers import AutoTokenizer
from tqdm import tqdm
def process_language(lang, config_name):
"""
주어진 언어에 대해 위키백과 데이터셋을 로드, 토크나이즈하고,
토큰 리스트를 LongTensor로 변환한 뒤 별도의 파일로 저장합니다.
"""
print(f"\n[{lang}] 데이터 처리 시작 (config: {config_name})")
# 데이터셋 로드
dataset = load_dataset("wikimedia/wikipedia", config_name, cache_dir= "/mnt/data6/huggingface_cache")
# LLaMA와 호환되는 토크나이저 초기화 (필요에 따라 다른 모델로 변경 가능)
tokenizer = AutoTokenizer.from_pretrained("huggyllama/llama-7b", use_fast=True)
token_ids = []
token_len = 0
# 데이터셋의 "train" split에 대해 토크나이즈 진행
for example in tqdm(dataset["train"], desc=f"{lang} 토크나이즈 진행중"):
text = example["text"]
tokens = tokenizer.encode(text, add_special_tokens=False)
token_len += len(tokens)
if token_len <= 2400000: # valid token size 조절
continue
token_ids.extend(tokens)
if len(token_ids) >= 2400000: # train token size 조절
break
# 리스트를 LongTensor로 변환
tokens_tensor = torch.tensor(token_ids, dtype=torch.long)
# 출력 디렉토리 생성
os.makedirs("data", exist_ok=True)
# 언어별 파일명: data/{lang}.train.llama
output_file = f"data/token_size_2.4M/valid/id.{lang}.valid.llama"
torch.save(tokens_tensor, output_file)
print(len(token_ids))
print(f"[{lang}] 토크나이즈된 데이터가 {output_file} 에 저장되었습니다.")
def main():
# 언어별 구성: key는 언어 코드, value는 해당 구성 이름 (예: 최신 날짜 구성)
languages = {
"en": "20231101.en",
"zh": "20231101.zh",
"fr": "20231101.fr",
"es": "20231101.es",
"vi": "20231101.vi",
"id": "20231101.id",
"ja": "20231101.ja"
}
for lang, config_name in languages.items():
process_language(lang, config_name)
if __name__ == "__main__":
main()
2. Token_size: 24K
-
Token_size를 24K로 조절하여 PPL값을 분석한다.
-
아래의 표는 activation_mask를 씌운 PPL값에서 activation_mask를 하지 않은 PPL값을 뺸 값이다.
-
$$ P = P_a - P_0 $$
-
$P_a$ : 언어별 mask 씌운뒤 PPL 값
-
$P_0$: mask를 씌우지 않은 PPL 값
-
-
en | zh | fr | es | vi | id | ja | |
---|---|---|---|---|---|---|---|
en | 0.001085 | 0.014781 | 0.005042 | 0.007821 | 0.007438 | 0.005447 | 0.010051 |
zh | 0.001629 | 0.108548 | 0.005350 | 0.004944 | 0.024637 | 0.006502 | 0.082292 |
fr | 0.003134 | 0.005830 | 0.062286 | 0.037556 | 0.010154 | 0.014436 | 0.004016 |
es | 0.003797 | 0.006993 | 0.027820 | 0.078101 | 0.015346 | 0.018523 | 0.006489 |
vi | 0.002300 | 0.019806 | 0.013916 | 0.020379 | 0.169570 | 0.029632 | 0.008226 |
id | 0.003617 | 0.007540 | 0.012297 | 0.022278 | 0.018761 | 0.102763 | 0.004672 |
Ja | 0.001656 | 0.064267 | 0.006124 | 0.005797 | 0.015805 | 0.007045 | 0.159938 |
3. Token_size: 2.4M
-
Token_size를 2.4M로 조절하여 PPL값을 분석한다.
-
아래의 표는 activation_mask를 씌운 PPL값에서 activation_mask를 하지 않은 PPL값을 뺸 값이다.
-
$$ P = P_a - P_0 $$
-
$P_a$ : 언어별 mask 씌운뒤 PPL 값
-
$P_0$: mask를 씌우지 않은 PPL 값
-
-
en | zh | fr | es | vi | id | ja | |
---|---|---|---|---|---|---|---|
en | -0.027972 | -0.043170 | 0.044069 | 0.026746 | 0.064751 | 0.024219 | 0.027064 |
zh | -0.027634 | 0.034790 | 0.046063 | 0.028860 | 0.079462 | 0.028540 | 0.096886 |
fr | -0.026866 | -0.048197 | 0.117208 | 0.064232 | 0.068227 | 0.033389 | 0.021538 |
es | -0.026121 | -0.049498 | 0.069080 | 0.097998 | 0.074034 | 0.036817 | 0.024023 |
vi | -0.028003 | -0.035161 | 0.053906 | 0.038608 | 0.220909 | 0.046700 | 0.026712 |
id | -0.026389 | -0.046483 | 0.051871 | 0.040412 | 0.073968 | 0.116167 | 0.021801 |
ja | -0.028558 | 0.003986 | 0.046061 | 0.027811 | 0.076806 | 0.026932 | 0.205830 |
4. 분석
- Token size 조절 전후 PPL 값은 변화가 있지만, 논문과 비교했을 때 값의 차이가 있음
- Token_size가 24K일 때 논문 PPL값과 약 8배 차이
- Token_size가 2.4M일 때 논문 PPL 값과 약 4배 차이
- 하지만 target 언어에 대해서 mask를 한 PPL값과 하지 않은 PPL 값이 차이가 뚜렷한 것으로 보아 언어별 뉴런을 잘 찾아낸다고 보인다.