Download ai_modules/nlp/mlm_predictor.py from donghyun95/EpiText-Hanja-OCR: direct link, hf CLI and curl.
- Browser
- Download file 3.92 kB
-
https://huggingface.co/donghyun95/EpiText-Hanja-OCR/resolve/174c3e7b70dd557b2bb98a28b6a07ad26a109113/ai_modules/nlp/mlm_predictor.py
- Command line
-
hf download hf://donghyun95/EpiText-Hanja-OCR@174c3e7b70dd557b2bb98a28b6a07ad26a109113/ai_modules/nlp/mlm_predictor.py
-
curl -L -o mlm_predictor.py https://huggingface.co/donghyun95/EpiText-Hanja-OCR/resolve/174c3e7b70dd557b2bb98a28b6a07ad26a109113/ai_modules/nlp/mlm_predictor.py
3.92 kB
| """ | |
| MLM(Masked Language Model) 예측 모듈 | |
| BERT 기반 MLM을 사용하여 마스킹된 토큰을 예측합니다. | |
| """ | |
| import torch | |
| from typing import List, Dict | |
| from transformers import AutoTokenizer, AutoModelForMaskedLM | |
| from .utils import normalize_mask_tokens | |
| class MLMPredictor: | |
| """MLM 예측을 담당하는 클래스""" | |
| def __init__(self, config: Dict, device: str = "cpu"): | |
| """ | |
| MLM 예측기를 초기화합니다. | |
| Args: | |
| config: 설정 딕셔너리 (nlp_config.json에서 로드) | |
| device: 연산 디바이스 ('cpu' 또는 'cuda') | |
| """ | |
| mlm_cfg = config['mlm_model'] | |
| self.model_name = mlm_cfg['model_name'] | |
| self.top_k = mlm_cfg['top_k'] | |
| self.max_length = mlm_cfg['max_length'] | |
| self.device = device | |
| self.tokenizer = None | |
| self.model = None | |
| def load_model(self) -> None: | |
| """모델을 메모리에 로드합니다.""" | |
| print(f"[MLM] 모델 로드 중: {self.model_name}") | |
| self.tokenizer = AutoTokenizer.from_pretrained( | |
| self.model_name, | |
| use_fast=False | |
| ) | |
| self.model = AutoModelForMaskedLM.from_pretrained(self.model_name) | |
| self.model.to(self.device) | |
| self.model.eval() | |
| print(f"[MLM] ✓ MLM 모델 로드 완료") | |
| def predict_masks( | |
| self, | |
| text: str | |
| ) -> List[List[Dict[str, any]]]: | |
| """ | |
| 텍스트 내의 [MASK] 토큰을 예측합니다. | |
| Args: | |
| text: 마스크가 포함된 텍스트 | |
| Returns: | |
| 각 마스크 위치별 top-k 예측 결과 리스트 | |
| """ | |
| # [MASK1], [MASK2] -> [MASK] 정규화 | |
| text_normalized = normalize_mask_tokens(text) | |
| print(f"[MLM] 입력 텍스트 샘플: {text_normalized[:100]}...") | |
| print(f"[MLM] [MASK] 토큰 개수: {text_normalized.count('[MASK]')}") | |
| # 토크나이즈 | |
| inputs = self.tokenizer( | |
| text_normalized, | |
| return_tensors="pt", | |
| truncation=True, | |
| max_length=self.max_length | |
| ) | |
| # 디바이스로 이동 | |
| inputs = {k: v.to(self.device) for k, v in inputs.items()} | |
| # [MASK] 위치 찾기 | |
| mask_indices = torch.where( | |
| inputs["input_ids"] == self.tokenizer.mask_token_id | |
| )[1] | |
| print(f"[MLM] 토크나이저가 찾은 [MASK] 위치 개수: {len(mask_indices)}") | |
| if len(mask_indices) == 0: | |
| print("[MLM] ⚠️ 경고: [MASK] 토큰을 찾을 수 없습니다!") | |
| sample_tokens = self.tokenizer.convert_ids_to_tokens( | |
| inputs['input_ids'][0][:50] | |
| ) | |
| print(f"[MLM] 토큰화된 입력 샘플: {sample_tokens}") | |
| return [] | |
| # 예측 수행 | |
| with torch.no_grad(): | |
| outputs = self.model(**inputs) | |
| logits = outputs.logits | |
| # 각 마스크 위치별로 top-k 예측 | |
| all_predictions = [] | |
| for mask_idx in mask_indices: | |
| mask_logits = logits[0, mask_idx, :] | |
| # 전체 어휘에 대해 softmax 계산 후 top-k 선택 | |
| all_probs = torch.nn.functional.softmax(mask_logits, dim=-1) | |
| top_k_probs, top_k_indices = torch.topk(all_probs, self.top_k) | |
| top_k_tokens = self.tokenizer.convert_ids_to_tokens( | |
| top_k_indices.tolist() | |
| ) | |
| predictions = [ | |
| { | |
| "token": token, | |
| "probability": float(prob) | |
| } | |
| for token, prob in zip(top_k_tokens, top_k_probs.tolist()) | |
| ] | |
| all_predictions.append(predictions) | |
| return all_predictions | |