Первичная версия: стилометрия реплик, LSA и протокол экспериментов

This commit is contained in:
2026-10-24 01:17:36 +03:00
commit c390224500
52 changed files with 10099 additions and 0 deletions

View File

@@ -0,0 +1,86 @@
"""Подготовка таблицы реплик с токенами, тегами и текстами для LSA."""
from __future__ import annotations
from pathlib import Path
import pandas as pd
from .io import DEFAULT_DATA_PATH, corpus_fingerprint, read_corpus
from .tokenization import Tokenizer
DEFAULT_CACHE_PATH = Path(__file__).resolve().parents[1] / "data" / "processed" / "tokenized.pkl"
REQUIRED_COLUMNS = {
"line_id",
"character",
"text",
"tokens",
"ptb",
"upos",
"sentences",
"pos_text",
"fw_text",
"content_text",
}
def build_feature_frame(
data_path: str | Path | None = None,
tokenizer: Tokenizer | None = None,
verbose: bool = True,
) -> pd.DataFrame:
"""Читает корпус и добавляет результаты токенизации и разметки."""
data_path = Path(data_path) if data_path is not None else DEFAULT_DATA_PATH
frame = read_corpus(data_path)
tokenizer = tokenizer or Tokenizer(use_nltk=True)
features = tokenizer.analyze_frame(frame, verbose=verbose)
features.attrs["corpus_path"] = str(data_path)
features.attrs["corpus_sha256"] = corpus_fingerprint(data_path)
features.attrs["nltk_used"] = tokenizer.use_nltk
features.attrs["pos_available"] = tokenizer.pos_available
return features
def save_feature_frame(frame: pd.DataFrame, path: str | Path) -> Path:
path = Path(path)
path.parent.mkdir(parents=True, exist_ok=True)
frame.to_pickle(path)
return path
def load_feature_frame(
data_path: str | Path | None = None,
cache_path: str | Path | None = None,
force: bool = False,
verbose: bool = True,
) -> pd.DataFrame:
"""Загружает кэш токенизации или строит его заново.
Кэш проверяется по SHA-256 исходного файла. Если файл корпуса изменился,
токенизация выполняется повторно.
"""
data_path = Path(data_path) if data_path is not None else DEFAULT_DATA_PATH
cache_path = Path(cache_path) if cache_path is not None else DEFAULT_CACHE_PATH
if cache_path.exists() and not force:
try:
frame = pd.read_pickle(cache_path)
if REQUIRED_COLUMNS <= set(frame.columns):
cached_hash = frame.attrs.get("corpus_sha256")
current_hash = corpus_fingerprint(data_path)
if cached_hash == current_hash:
if verbose:
print(f"[datasets] загружен кэш: {cache_path}")
return frame
if verbose:
print("[datasets] корпус изменился, пересобираю признаки.")
except Exception as error:
if verbose:
print(f"[datasets] не удалось прочитать кэш ({error}), пересобираю.")
frame = build_feature_frame(data_path, verbose=verbose)
save_feature_frame(frame, cache_path)
if verbose:
print(f"[datasets] кэш сохранён: {cache_path}")
return frame