Загрузить файлы в «T5_slovak_4_3_1»

This commit is contained in:
Vladyslav Korzun 2025-05-22 13:16:54 +00:00
parent 1a127f0b98
commit eb3374faed
3 changed files with 399 additions and 0 deletions

152
T5_slovak_4_3_1/T5_4.py Normal file
View File

@ -0,0 +1,152 @@
import os
import torch
from transformers import (
AutoTokenizer,
AutoModelForSeq2SeqLM,
Trainer,
TrainingArguments,
)
# ----------------------------------------------------------
# 1. Načítanie modelu a tokenizátora zo súborového systému
# ----------------------------------------------------------
# Zistenie aktuálnej cesty k projektu
script_dir = os.path.dirname(os.path.abspath(__file__))
# Načítanie slovenského modelu T5 a tokenizátora
tokenizer = AutoTokenizer.from_pretrained("TUKE-KEMT/slovak-t5-base", legacy=False)
tokenizer.pad_token = tokenizer.eos_token # Nastavenie koncového tokenu ako výplňového
model = AutoModelForSeq2SeqLM.from_pretrained("TUKE-KEMT/slovak-t5-base")
# Výber výpočtového zariadenia (v tomto prípade CPU)
device = "cuda" if torch.cuda.is_available() else "cpu"
model.to(device)
# ----------------------------------------------------------
# 2. Načítanie vstupných dát (zdravé a cieľové texty)
# ----------------------------------------------------------
# Cesty k priečinkom s textovými súbormi
healthy_folder = r"project\text\zdr_cleaned\4"
dementia_folder = r"project\text\chory_cleaned\4"
# Pomocná funkcia na načítanie všetkých textov z daného priečinka
def load_texts_from_folder(folder_path):
texts = []
for filename in os.listdir(folder_path):
if filename.endswith(".txt"):
with open(
os.path.join(folder_path, filename), "r", encoding="utf-8"
) as file:
texts.append(file.read().strip())
return texts
# Načítanie vstupných textov
healthy_texts = load_texts_from_folder(healthy_folder)
dementia_texts = load_texts_from_folder(dementia_folder)
# Kontrola: počet textov v oboch priečinkoch musí byť rovnaký
assert len(healthy_texts) == len(dementia_texts), "Počet textov musí byť rovnaký."
# Vytvorenie zoznamu trénovacích dvojíc (vstup → cieľ)
train_data = [{"input": h, "output": d} for h, d in zip(healthy_texts, dementia_texts)]
# ----------------------------------------------------------
# 3. Tokenizácia vstupných dát (na formát požadovaný modelom)
# ----------------------------------------------------------
def tokenize_function(example):
inputs = tokenizer(
example["input"], padding="max_length", truncation=True, max_length=128
)
outputs = tokenizer(
example["output"], padding="max_length", truncation=True, max_length=128
)
return {
"input_ids": inputs["input_ids"],
"attention_mask": inputs["attention_mask"],
"labels": outputs["input_ids"],
}
# Vykonanie tokenizácie pre všetky trénovacie dvojice
tokenized_train_data = {key: [] for key in ["input_ids", "attention_mask", "labels"]}
for example in train_data:
tokenized = tokenize_function(example)
for key in tokenized_train_data:
tokenized_train_data[key].append(tokenized[key])
# ----------------------------------------------------------
# 4. Vytvorenie datasetu pre PyTorch
# ----------------------------------------------------------
class CustomDataset(torch.utils.data.Dataset):
def __init__(self, data):
self.data = data
def __getitem__(self, idx):
return {
"input_ids": torch.tensor(self.data["input_ids"][idx], dtype=torch.long),
"labels": torch.tensor(self.data["labels"][idx], dtype=torch.long),
"attention_mask": torch.tensor(
self.data["attention_mask"][idx], dtype=torch.long
),
}
def __len__(self):
return len(self.data["input_ids"])
# Inicializácia trénovacieho datasetu
train_dataset = CustomDataset(tokenized_train_data)
# ----------------------------------------------------------
# 5. Nastavenie cieľovej cesty pre uloženie finálneho modelu
# ----------------------------------------------------------
model_save_path = os.path.join(script_dir, "trained_slovak_t5_cpu")
# ----------------------------------------------------------
# 6. Definícia parametrov trénovania modelu
# ----------------------------------------------------------
training_args = TrainingArguments(
save_strategy="no", # Automatické ukladanie checkpointov je vypnuté (model sa uloží len na konci ručne)
logging_steps=50, # Frekvencia logovania každých 50 krokov sa vypíšu metriky a stav
per_device_train_batch_size=2, # Veľkosť dávky pre jeden krok tréningu (na jedno zariadenie)
gradient_accumulation_steps=4, # Počet krokov, počas ktorých sa akumulujú gradienty pred aktualizáciou váh
# Efektívna veľkosť dávky = 2 × 4 = 8 príkladov
num_train_epochs=15, # Počet úplných prechodov cez celý trénovací dataset (15 epôch)
learning_rate=3e-5, # Rýchlosť učenia ovplyvňuje mieru zmien váh počas učenia
weight_decay=0.01, # Regularizácia váh zabraňuje pretrénovaniu tým, že penalizuje veľké váhy
optim="adamw_torch", # Optimalizátor použitý počas trénovania (AdamW implementovaný v PyTorch)
dataloader_num_workers=0, # Počet subprocessov použitých pri načítavaní dát (0 = hlavný proces)
logging_first_step=True, # Zabezpečí logovanie už po prvom kroku trénovania
disable_tqdm=False, # Zapína vizuálny progres bar (tqdm) počas trénovania v konzole
)
# ----------------------------------------------------------
# 7. Inicializácia a spustenie trénovania modelu
# ----------------------------------------------------------
trainer = Trainer(
model=model,
args=training_args,
train_dataset=train_dataset,
)
# Spustenie procesu trénovania
trainer.train()
# ----------------------------------------------------------
# 8. Uloženie finálneho modelu na disk
# ----------------------------------------------------------
model.save_pretrained(model_save_path)
tokenizer.save_pretrained(model_save_path)

123
T5_slovak_4_3_1/met_sk.py Normal file
View File

@ -0,0 +1,123 @@
import os
from rouge_score import rouge_scorer
from bert_score import score
import nltk
# Automatické stiahnutie 'punkt' ak ešte nie je k dispozícii
try:
nltk.data.find("tokenizers/punkt")
except LookupError:
nltk.download("punkt")
# ----------------------
# Funkcia na načítanie všetkých textových súborov z priečinka
# Používa sa na načítanie referenčných textov pacientov s Alzheimerom
# ----------------------
def load_texts_from_folder(folder_path):
texts = []
for filename in os.listdir(folder_path):
if filename.endswith(".txt"):
with open(
os.path.join(folder_path, filename), "r", encoding="utf-8"
) as file:
texts.append(file.read().strip())
return texts
# Cesta k referenčným textom pacientov
script_dir = os.path.dirname(os.path.abspath(__file__))
project_root = os.path.abspath(os.path.join(script_dir, ".."))
dementia_folder = os.path.join(project_root, "text", "chory_cleaned", "4")
reference_texts_dementia = load_texts_from_folder(dementia_folder)
# Kontrola: či súborový priečinok nie je prázdny
if not reference_texts_dementia:
raise ValueError(" V zložke nie sú žiadne .txt súbory! Skontroluj cestu.")
print(f" Načítaných {len(reference_texts_dementia)} chorých textov na porovnanie.")
# ----------------------
# Manuálne zadaný zdravý (originálny) text
# a text vygenerovaný modelom s "narušenou" štylistikou
# ----------------------
original_text_healthy = """no mamička ktorá má všetko sama na starosť. varí drží plačúce dieťa na rukách. telefonuje čiže asi aj pracuje alebo vybavuje alebo ska a nie rozmýšľa tam. nakupuje topánky cez telefón. na polici nám sedí mačka ktorá vysypala. neviem či sú to klinčeky alebo niečo. padá nám to do na počítač. máme tam rozložené jedlo. mamička samozrejme nestíha. vypráža vajíčka robí hemendex. áno lebo letí tam šunka aj vajíčka tam sú. na polici sú tri knihy. poobede čiže nestíhajú obed. už je po dvanástej hodine. a dieťa je hladné strašne plače. není naň čas. mamička je proste v jednom kole stále."""
generated_text = """na polici sú tri knihy. je tam ešte jedna kniha ktorá sa dá prečítať ale neviem či to má nejaký význam alebo čo to môže byť. a dieťa plače. v ruke drží fľašu s vodou. niečo jej chýba. no nič iné. všetko ostatné je už hotové. deti plačú. spia. mama varí obed."""
# ----------------------
# Výpočet metriky ROUGE (porovnávanie na úrovni slov a fráz)
# ----------------------
def evaluate_text(reference_texts, generated_text):
scorer = rouge_scorer.RougeScorer(["rouge1", "rougeL"], use_stemmer=False)
rouge1_scores = []
rougeL_scores = []
for ref_text in reference_texts:
scores = scorer.score(ref_text, generated_text)
rouge1_scores.append(scores["rouge1"].fmeasure)
rougeL_scores.append(scores["rougeL"].fmeasure)
return {
"ROUGE-1-best": max(rouge1_scores),
"ROUGE-1-mean": sum(rouge1_scores) / len(rouge1_scores),
"ROUGE-L-best": max(rougeL_scores),
"ROUGE-L-mean": sum(rougeL_scores) / len(rougeL_scores),
}
# ----------------------
# Výpočet metriky BERTScore (porovnávanie na úrovni významu)
# Používa sa multilingválny model (napr. XLM-RoBERTa)
# ----------------------
# BERTScore s explicitne zvoleným modelom pre slovenský jazyk
def compute_bert_score(reference_texts, generated_text):
try:
P, R, F1 = score(
cands=[generated_text] * len(reference_texts),
refs=[[ref] for ref in reference_texts],
lang="sk",
model_type="xlm-roberta-large", # 🔥 Multilingválny model s podporou SK
rescale_with_baseline=False,
)
return {
"BERTScore-F1-best": F1.max().item(),
"BERTScore-F1-mean": F1.mean().item(),
}
except Exception as e:
print(f"⚠ Chyba pri výpočte BERTScore: {e}")
return {"BERTScore-F1-best": 0, "BERTScore-F1-mean": 0}
# ----------------------
# Vyhodnotenie vygenerovaného textu:
# - v porovnaní s pacientmi
# - v porovnaní s pôvodným zdravým textom
# ----------------------
results_to_dementia = evaluate_text(reference_texts_dementia, generated_text)
bert_results_dementia = compute_bert_score(reference_texts_dementia, generated_text)
results_to_original = evaluate_text([original_text_healthy], generated_text)
bert_results_original = compute_bert_score([original_text_healthy], generated_text)
# ----------------------
# Výpis výsledkov do konzoly (pre vizuálne vyhodnotenie kvality transformácie)
# ----------------------
print("\n VÝSLEDKY POROVNANIA TEXTU\n")
print(" **Porovnanie s textami pacientov s Alzheimerom** (ČÍM VYŠŠIE, TÝM LEPŠIE):")
print(
f" ROUGE-1: najvyššie = {results_to_dementia['ROUGE-1-best']:.4f} | priemer = {results_to_dementia['ROUGE-1-mean']:.4f}"
)
print(
f" ROUGE-L: najvyššie = {results_to_dementia['ROUGE-L-best']:.4f} | priemer = {results_to_dementia['ROUGE-L-mean']:.4f}"
)
print(
f" BERTScore: najvyššie = {bert_results_dementia['BERTScore-F1-best']:.4f} | priemer = {bert_results_dementia['BERTScore-F1-mean']:.4f}"
)
print("\n **Porovnanie s pôvodným zdravým textom** (ČÍM NIŽŠIE, TÝM LEPŠIE):")
print(f" ROUGE-1: {results_to_original['ROUGE-1-best']:.4f}")
print(f" ROUGE-L: {results_to_original['ROUGE-L-best']:.4f}")
print(f" BERTScore: {bert_results_original['BERTScore-F1-mean']:.4f}")

View File

@ -0,0 +1,124 @@
import os
import torch
from transformers import AutoTokenizer, AutoModelForSeq2SeqLM
# ----------------------------------------------------------
# Načítanie predtrénovaného modelu a tokenizátora z disku
# ----------------------------------------------------------
# Cesta k priečinku s trénovanou slovenskou T5 verziou
script_dir = os.path.dirname(os.path.abspath(__file__))
model_path = os.path.join(script_dir, "trained_slovak_t5_cpu")
# Kontrola existencie modelu na disku
if not os.path.exists(model_path):
raise FileNotFoundError(f"Priečinok s modelom nebol nájdený: {model_path}")
# Načítanie modelu a tokenizátora z daného priečinka
tokenizer = AutoTokenizer.from_pretrained(model_path)
model = AutoModelForSeq2SeqLM.from_pretrained(model_path)
# Výber zariadenia (GPU ak je dostupné, inak CPU)
device = "cuda" if torch.cuda.is_available() else "cpu"
model.to(device)
print("Model bol úspešne načítaný a je pripravený na použitie.")
# ----------------------------------------------------------
# Vstupný text zdravého človeka na transformáciu
# ----------------------------------------------------------
healthy_text = """no mamička ktorá má všetko sama na starosť. varí drží plačúce dieťa na rukách. telefonuje čiže asi aj pracuje alebo vybavuje alebo ska a nie rozmýšľa tam. nakupuje topánky cez telefón. na polici nám sedí mačka ktorá vysypala. neviem či sú to klinčeky alebo niečo. padá nám to do na počítač. máme tam rozložené jedlo. mamička samozrejme nestíha. vypráža vajíčka robí hemendex. áno lebo letí tam šunka aj vajíčka tam sú. na polici sú tri knihy. poobede čiže nestíhajú obed. už je po dvanástej hodine. a dieťa je hladné strašne plače. není naň čas. mamička je proste v jednom kole stále."""
# Tokenizácia vstupného textu pre vstup do modelu
inputs = tokenizer(healthy_text, return_tensors="pt").to(device)
input_token_length = len(tokenizer.encode(healthy_text, add_special_tokens=False))
# Výpočet dynamických limitov pre generovanie výstupu
min_length_ratio = 0.6
max_new_tokens_ratio = 0.5
min_length = int(input_token_length * min_length_ratio)
max_new_tokens = min(75, int(input_token_length * max_new_tokens_ratio))
print(f"Počet tokenov vo vstupe: {input_token_length}")
print(
f"Minimálna dĺžka výstupu: {min_length}, maximálny počet nových tokenov: {max_new_tokens}"
)
# ----------------------------------------------------------
# Konfigurácie generovania textu (rôzne nastavenia)
# ----------------------------------------------------------
generation_configs = [
{
"max_new_tokens": max_new_tokens,
"do_sample": False,
"num_beams": 5,
"length_penalty": 1.5,
"no_repeat_ngram_size": 4,
"repetition_penalty": 3.5,
"early_stopping": True,
},
{
"max_new_tokens": max_new_tokens,
"do_sample": False,
"num_beams": 7,
"length_penalty": 1.5,
"no_repeat_ngram_size": 4,
"repetition_penalty": 3.5,
"early_stopping": True,
},
{
"max_new_tokens": max_new_tokens,
"do_sample": False,
"num_beams": 8,
"length_penalty": 1.5,
"no_repeat_ngram_size": 4,
"repetition_penalty": 3.5,
"early_stopping": True,
},
]
# ----------------------------------------------------------
# Vlastné generovanie textu podľa konfigurácií
# ----------------------------------------------------------
generated_texts = []
for i, config in enumerate(generation_configs):
print(f"\nGenerácia textu č. {i+1}:")
# Parametre pre funkciu generate()
gen_kwargs = {
"min_length": min(min_length, config["max_new_tokens"] - 10),
"max_new_tokens": config["max_new_tokens"],
"repetition_penalty": config["repetition_penalty"],
"num_beams": config.get("num_beams", 1),
"length_penalty": config.get("length_penalty", 1.0),
"early_stopping": config.get("early_stopping", True),
}
# Nepovinný parameter: zákaz opakovania n-gramov
if "no_repeat_ngram_size" in config:
gen_kwargs["no_repeat_ngram_size"] = config["no_repeat_ngram_size"]
# Sampling (ak by bol použitý, tu je vypnutý)
if config.get("do_sample", False):
gen_kwargs["do_sample"] = True
if "top_p" in config:
gen_kwargs["top_p"] = config["top_p"]
if "temperature" in config:
gen_kwargs["temperature"] = config["temperature"]
# Generovanie bez výpočtu gradientov
with torch.no_grad():
outputs = model.generate(inputs["input_ids"], **gen_kwargs)
# Dekódovanie výstupných tokenov na čitateľný text
generated_text = tokenizer.decode(outputs[0], skip_special_tokens=True)
generated_texts.append(generated_text)
# Výpis výsledku
print("Vygenerovaný text:")
print(generated_text)
print("-" * 80)