Initial commit
This commit is contained in:
183
train/classifier_dataset.py
Normal file
183
train/classifier_dataset.py
Normal file
@@ -0,0 +1,183 @@
|
||||
"""
|
||||
files/json/{LABEL}/{파일명}/page_xxx.json 구조를 읽어
|
||||
페이지 단위로 샘플을 생성하여 캐시 저장
|
||||
문서 1개 = 샘플 N개 (페이지 수만큼)
|
||||
"""
|
||||
import json
|
||||
import os
|
||||
import pickle
|
||||
from pathlib import Path
|
||||
|
||||
from loguru import logger
|
||||
|
||||
import config
|
||||
|
||||
# JSON_DIR = os.getenv("CLASSIFIER_JSON_DIR", "./files/json")
|
||||
# CACHE_PATH = os.getenv("CLASSIFIER_CACHE_PATH", "./files/classifier_dataset.pkl")
|
||||
# MIN_WORDS = int(os.getenv("CLASSIFIER_MIN_WORDS", "20")) # 페이지당 최소 단어 수
|
||||
|
||||
JSON_DIR = config.CLASSIFIER_JSON_DIR
|
||||
CACHE_PATH = config.CLASSIFIER_CACHE_PATH
|
||||
MIN_WORDS = config.CLASSIFIER_MIN_WORDS
|
||||
|
||||
_status: dict = {"status": "idle", "message": "", "total": 0}
|
||||
|
||||
|
||||
def get_status() -> dict:
|
||||
return _status
|
||||
|
||||
|
||||
# def build() -> None:
|
||||
# global _status
|
||||
# try:
|
||||
# _status = {"status": "building", "message": "JSON 파일 스캔 중...", "total": 0}
|
||||
# json_path = Path(JSON_DIR)
|
||||
#
|
||||
# if not json_path.exists():
|
||||
# raise FileNotFoundError(f"JSON 디렉토리 없음: {JSON_DIR}")
|
||||
#
|
||||
# data = []
|
||||
# skip_count = 0
|
||||
#
|
||||
# for label_dir in sorted(json_path.iterdir()):
|
||||
# if not label_dir.is_dir():
|
||||
# continue
|
||||
# label = label_dir.name
|
||||
# label_count = 0
|
||||
#
|
||||
# for doc_dir in sorted(label_dir.iterdir()):
|
||||
# if not doc_dir.is_dir():
|
||||
# continue
|
||||
#
|
||||
# for page_file in sorted(doc_dir.glob("page_*.json")):
|
||||
# try:
|
||||
# with open(page_file, encoding="utf-8") as f:
|
||||
# d = json.load(f)
|
||||
# words = d.get("words", [])
|
||||
# except Exception as e:
|
||||
# logger.warning(f"파일 읽기 실패 {page_file}: {e}")
|
||||
# continue
|
||||
#
|
||||
# # 단어 수 미달 페이지 제외
|
||||
# if len(words) < MIN_WORDS:
|
||||
# print(f"skip file : {len(words)} : {page_file}")
|
||||
# skip_count += 1
|
||||
# continue
|
||||
#
|
||||
# data.append({
|
||||
# "text": " ".join(words),
|
||||
# "label": label,
|
||||
# "src": str(page_file), # 디버깅용
|
||||
# })
|
||||
# label_count += 1
|
||||
#
|
||||
# _status["message"] = f"{label}: {label_count}페이지 샘플 추가 (누적 {len(data)}개)"
|
||||
# logger.info(_status["message"])
|
||||
#
|
||||
# if not data:
|
||||
# raise ValueError("수집된 데이터가 없습니다.")
|
||||
#
|
||||
# os.makedirs(os.path.dirname(CACHE_PATH), exist_ok=True)
|
||||
# with open(CACHE_PATH, "wb") as f:
|
||||
# pickle.dump(data, f)
|
||||
#
|
||||
# _status = {
|
||||
# "status": "done",
|
||||
# "message": f"데이터셋 생성 완료 (단어 {MIN_WORDS}개 미만 {skip_count}페이지 제외)",
|
||||
# "total": len(data),
|
||||
# }
|
||||
# logger.info(f"데이터셋 저장: {CACHE_PATH} ({len(data)}개, 제외 {skip_count}개)")
|
||||
#
|
||||
# except Exception as e:
|
||||
# _status = {"status": "error", "message": str(e), "total": 0}
|
||||
# logger.exception(f"데이터셋 생성 실패: {e}")
|
||||
|
||||
|
||||
def _process_page_file(page_file: Path, label: str, data: list, skip_count: int) -> tuple[int, int]:
|
||||
"""단일 page_*.json 파일 처리. (label_count 증가분, skip_count) 반환"""
|
||||
try:
|
||||
with open(page_file, encoding="utf-8") as f:
|
||||
d = json.load(f)
|
||||
words = d.get("words", [])
|
||||
except Exception as e:
|
||||
logger.warning(f"파일 읽기 실패 {page_file}: {e}")
|
||||
return 0, skip_count
|
||||
|
||||
if len(words) < MIN_WORDS:
|
||||
print(f"skip file : {len(words)} : {page_file}")
|
||||
return 0, skip_count + 1
|
||||
|
||||
data.append({"text": " ".join(words), "label": label, "src": str(page_file)})
|
||||
return 1, skip_count
|
||||
|
||||
|
||||
def _process_label_dir(label_dir: Path, data: list, skip_count: int) -> tuple[int, int]:
|
||||
"""label 폴더 처리. label_count, skip_count 반환"""
|
||||
label = label_dir.name
|
||||
label_count = 0
|
||||
|
||||
# label 폴더 직속 page_*.json
|
||||
for page_file in sorted(label_dir.glob("*.json")):
|
||||
added, skip_count = _process_page_file(page_file, label, data, skip_count)
|
||||
label_count += added
|
||||
|
||||
# 하위 doc_dir 폴더
|
||||
for doc_dir in sorted(label_dir.iterdir()):
|
||||
if not doc_dir.is_dir():
|
||||
continue
|
||||
for page_file in sorted(doc_dir.glob("*.json")):
|
||||
added, skip_count = _process_page_file(page_file, label, data, skip_count)
|
||||
label_count += added
|
||||
|
||||
return label_count, skip_count
|
||||
|
||||
|
||||
def build() -> None:
|
||||
global _status
|
||||
try:
|
||||
_status = {"status": "building", "message": "JSON 파일 스캔 중...", "total": 0}
|
||||
json_path = Path(JSON_DIR)
|
||||
|
||||
if not json_path.exists():
|
||||
raise FileNotFoundError(f"JSON 디렉토리 없음: {JSON_DIR}")
|
||||
|
||||
data = []
|
||||
skip_count = 0
|
||||
|
||||
for label_dir in sorted(json_path.iterdir()):
|
||||
if not label_dir.is_dir():
|
||||
continue
|
||||
|
||||
label_count, skip_count = _process_label_dir(label_dir, data, skip_count)
|
||||
|
||||
_status["message"] = f"{label_dir.name}: {label_count}페이지 샘플 추가 (누적 {len(data)}개)"
|
||||
logger.info(_status["message"])
|
||||
|
||||
if not data:
|
||||
raise ValueError("수집된 데이터가 없습니다.")
|
||||
|
||||
os.makedirs(os.path.dirname(CACHE_PATH), exist_ok=True)
|
||||
with open(CACHE_PATH, "wb") as f:
|
||||
pickle.dump(data, f)
|
||||
|
||||
_status = {
|
||||
"status": "done",
|
||||
"message": f"데이터셋 생성 완료 (단어 {MIN_WORDS}개 미만 {skip_count}페이지 제외)",
|
||||
"total": len(data),
|
||||
}
|
||||
logger.info(f"데이터셋 저장: {CACHE_PATH} ({len(data)}개, 제외 {skip_count}개)")
|
||||
|
||||
except Exception as e:
|
||||
_status = {"status": "error", "message": str(e), "total": 0}
|
||||
logger.exception(f"데이터셋 생성 실패: {e}")
|
||||
|
||||
|
||||
def load() -> list[dict]:
|
||||
if not os.path.exists(CACHE_PATH):
|
||||
return []
|
||||
try:
|
||||
with open(CACHE_PATH, "rb") as f:
|
||||
return pickle.load(f)
|
||||
except Exception as e:
|
||||
logger.error(f"데이터셋 로드 실패: {e}")
|
||||
return []
|
||||
Reference in New Issue
Block a user