kkandull's picture
Upload app.py
a685392 verified
# ํ•„์š”ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ž„ํฌํŠธ
import os
import pandas as pd # pandas๋Š” ํ˜„์žฌ ์ฝ”๋“œ์—์„œ๋Š” ์ง์ ‘ ์‚ฌ์šฉ๋˜์ง€ ์•Š์ง€๋งŒ, ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ๊ด€๋ จ ์œ ํ‹ธ๋ฆฌํ‹ฐ๋กœ ๋‚จ๊ฒจ๋‘˜ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
import numpy as np
import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.utils.data import Dataset, DataLoader # DataLoader์™€ Dataset์€ ์ถ”๋ก  ์‹œ ์ง์ ‘ ์‚ฌ์šฉ๋˜์ง„ ์•Š์ง€๋งŒ, ๋ชจ๋ธ ์ •์˜์— ํ•„์š”ํ•  ์ˆ˜ ์žˆ์–ด ๋‚จ๊ฒจ๋‘ 
from transformers import LongformerForSequenceClassification, AutoTokenizer
import gradio as gr
# =======================================================
# 1. ์ „์—ญ ์„ค์ • ๋ฐ ์ƒ์ˆ˜ ์ •์˜
# =======================================================
MODEL_NAME = 'kiddothe2b/longformer-mini-1024' # HuggingFace ๋ชจ๋ธ ์ด๋ฆ„
MAX_LEN = 1024 # ๋ชจ๋ธ ์ž…๋ ฅ ์ตœ๋Œ€ ๊ธธ์ด
# GPU ์‚ฌ์šฉ ๊ฐ€๋Šฅ ์—ฌ๋ถ€ ํ™•์ธ ๋ฐ ๋””๋ฐ”์ด์Šค ์„ค์ •
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
print(f"Using device: {device}")
# ํ† ํฌ๋‚˜์ด์ € ๋กœ๋“œ (์ถ”๋ก  ์‹œ ํ•„์š”)
tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME)
# =======================================================
# 2. PyTorch ๋ฐ์ดํ„ฐ์…‹ ์ •์˜ (ํ•™์Šต ์‹œ ์‚ฌ์šฉ๋˜์—ˆ๋˜ ํด๋ž˜์Šค. ์ถ”๋ก  ์‹œ ์ง์ ‘ ๋ฐ์ดํ„ฐ ๋กœ๋”๋ฅผ ๋งŒ๋“ค์ง€๋Š” ์•Š์Œ)
# =======================================================
# ์ด ํด๋ž˜์Šค๋Š” ๋ชจ๋ธ์ด ํ•™์Šต๋  ๋•Œ ์‚ฌ์šฉ๋˜์—ˆ๋˜ ๋ฐ์ดํ„ฐ ๊ตฌ์กฐ๋ฅผ ์ •์˜ํ•ฉ๋‹ˆ๋‹ค.
# ์ถ”๋ก  ์‹œ์—๋Š” ๋‹จ์ผ ํ…์ŠคํŠธ ์ž…๋ ฅ์ด ๋“ค์–ด์˜ค๋ฏ€๋กœ ์ง์ ‘ DataLoader๋ฅผ ๋งŒ๋“ค ํ•„์š”๋Š” ์—†์Šต๋‹ˆ๋‹ค.
# ํ•˜์ง€๋งŒ ๋ชจ๋ธ์ด ๊ธฐ๋Œ€ํ•˜๋Š” ์ž…๋ ฅ ํ˜•ํƒœ๋ฅผ ๋งž์ถ”๊ธฐ ์œ„ํ•ด encoding ๊ณผ์ •์ด ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.
class DepressionDataset(Dataset):
def __init__(self, texts, labels, tokenizer, max_len):
self.texts = texts
self.labels = labels
self.tokenizer = tokenizer
self.max_len = max_len
def __len__(self):
return len(self.texts)
def __getitem__(self, item):
text = str(self.texts[item])
label = self.labels[item]
encoding = self.tokenizer.encode_plus(
text,
add_special_tokens=True,
max_length=self.max_len,
return_token_type_ids=False,
padding='max_length',
truncation=True,
return_attention_mask=True,
return_tensors='pt',
)
return {
'input_ids': encoding['input_ids'].flatten(),
'attention_mask': encoding['attention_mask'].flatten(),
'labels': torch.tensor(label, dtype=torch.long)
}
# =======================================================
# 3. ๋ชจ๋ธ ๋กœ๋”ฉ (ํ•™์Šต๋œ ๊ฐ€์ค‘์น˜๋ฅผ ๋กœ๋“œ)
# =======================================================
print("\n--- Loading models for inference ---")
# ๋ชจ๋ธ ํŒŒ์ผ ๊ฒฝ๋กœ (saved_models ํด๋”๊ฐ€ ์—†์œผ๋ฏ€๋กœ ๋ฃจํŠธ ๋””๋ ‰ํ† ๋ฆฌ์— ์žˆ๋‹ค๊ณ  ๊ฐ€์ •)
# ์ด์ „์— ์žˆ๋˜ save_dir ๋ณ€์ˆ˜๋Š” ์ด์ œ ํ•„์š” ์—†์Šต๋‹ˆ๋‹ค.
p_model_path = 'p_text_best_model.bin' # ํŒŒ์ผ๋ช…์ด ๋ฃจํŠธ์— ๋ฐ”๋กœ ์žˆ๋‹ค๊ณ  ๊ฐ€์ •
e_model_path = 'e_text_best_model.bin' # ํŒŒ์ผ๋ช…์ด ๋ฃจํŠธ์— ๋ฐ”๋กœ ์žˆ๋‹ค๊ณ  ๊ฐ€์ •
# ๋ชจ๋ธ ๋กœ๋”ฉ ๋ฐ ํ‰๊ฐ€ ๋ชจ๋“œ ์„ค์ •
p_model_for_inference = None
e_model_for_inference = None
try:
# ์ฐธ๊ฐ€์ž ๋ฐœํ™” ๋ชจ๋ธ (P-model) ๋กœ๋“œ
if os.path.exists(p_model_path):
p_model_for_inference = LongformerForSequenceClassification.from_pretrained(MODEL_NAME, num_labels=2)
p_model_for_inference.load_state_dict(torch.load(p_model_path, map_location=device))
p_model_for_inference.to(device)
p_model_for_inference.eval() # ํ‰๊ฐ€ ๋ชจ๋“œ ์„ค์ •
print(f"P-model loaded successfully from {p_model_path}")
else:
print(f"Warning: P-model file not found at {p_model_path}. Please ensure it's uploaded to the root directory.")
# ์—˜๋ฆฌ ๋ฐœํ™” ๋ชจ๋ธ (E-model) ๋กœ๋“œ
if os.path.exists(e_model_path):
e_model_for_inference = LongformerForSequenceClassification.from_pretrained(MODEL_NAME, num_labels=2)
e_model_for_inference.load_state_dict(torch.load(e_model_path, map_location=device))
e_model_for_inference.to(device)
e_model_for_inference.eval() # ํ‰๊ฐ€ ๋ชจ๋“œ ์„ค์ •
print(f"E-model loaded successfully from {e_model_path}")
else:
print(f"Warning: E-model file not found at {e_model_path}. Please ensure it's uploaded to the root directory.")
except Exception as e:
print(f"Error loading models: {e}")
# ๋ชจ๋ธ ๋กœ๋”ฉ ์‹คํŒจ ์‹œ, UI๊ฐ€ ์‹คํ–‰๋˜์ง€ ์•Š๋„๋ก ์„ค์ •
p_model_for_inference = None
e_model_for_inference = None
# =======================================================
# 4. Gradio ์˜ˆ์ธก ํ•จ์ˆ˜ ์ •์˜
# =======================================================
def predict_depression(participant_text, ellie_text):
# ๋ชจ๋ธ์ด ์ œ๋Œ€๋กœ ๋กœ๋“œ๋˜์—ˆ๋Š”์ง€ ํ™•์ธ
if p_model_for_inference is None or e_model_for_inference is None:
return "**์˜ค๋ฅ˜:** ๋ชจ๋ธ์ด ๋กœ๋“œ๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ๊ด€๋ฆฌ์ž์—๊ฒŒ ๋ฌธ์˜ํ•˜๊ฑฐ๋‚˜ ๋ชจ๋ธ ํŒŒ์ผ ์—…๋กœ๋“œ ์—ฌ๋ถ€๋ฅผ ํ™•์ธํ•ด์ฃผ์„ธ์š”."
# ์—˜๋ฆฌ ๋ฐœํ™” ์ „์ฒ˜๋ฆฌ (ํ•™์Šต ์‹œ์™€ ๋™์ผํ•œ ๋กœ์ง ์ ์šฉ)
e_text_words = ellie_text.split()
if len(e_text_words) > 0:
ellie_text_processed = " ".join(e_text_words[len(e_text_words) // 2:])
else:
ellie_text_processed = ""
# P-model ์˜ˆ์ธก
p_encoding = tokenizer.encode_plus(
participant_text,
add_special_tokens=True,
max_length=MAX_LEN,
return_token_type_ids=False,
padding='max_length',
truncation=True,
return_attention_mask=True,
return_tensors='pt',
)
p_input_ids = p_encoding['input_ids'].to(device)
p_attention_mask = p_encoding['attention_mask'].to(device)
with torch.no_grad(): # ์ถ”๋ก  ์‹œ์—๋Š” ๊ทธ๋ผ๋””์–ธํŠธ ๊ณ„์‚ฐ ๋ถˆํ•„์š”
p_outputs = p_model_for_inference(input_ids=p_input_ids, attention_mask=p_attention_mask)
p_probs = F.softmax(p_outputs.logits, dim=1).cpu().numpy().flatten()
p_pred_label = np.argmax(p_probs)
# E-model ์˜ˆ์ธก
e_encoding = tokenizer.encode_plus(
ellie_text_processed,
add_special_tokens=True,
max_length=MAX_LEN,
return_token_type_ids=False,
padding='max_length',
truncation=True,
return_attention_mask=True,
return_tensors='pt',
)
e_input_ids = e_encoding['input_ids'].to(device)
e_attention_mask = e_encoding['attention_mask'].to(device)
with torch.no_grad(): # ์ถ”๋ก  ์‹œ์—๋Š” ๊ทธ๋ผ๋””์–ธํŠธ ๊ณ„์‚ฐ ๋ถˆํ•„์š”
e_outputs = e_model_for_inference(input_ids=e_input_ids, attention_mask=e_attention_mask)
e_probs = F.softmax(e_outputs.logits, dim=1).cpu().numpy().flatten()
e_pred_label = np.argmax(e_probs)
# ์•™์ƒ๋ธ” (OR ์ „๋žต): ๋‘˜ ์ค‘ ํ•˜๋‚˜๋ผ๋„ ์šฐ์šธ์ฆ(1)์œผ๋กœ ์˜ˆ์ธกํ•˜๋ฉด ์šฐ์šธ์ฆ์œผ๋กœ ๊ฐ„์ฃผ
ensemble_pred_label = 1 if p_pred_label == 1 or e_pred_label == 1 else 0
labels = ['Control (๋น„์šฐ์šธ)', 'Depressed (์šฐ์šธ)']
ensemble_result = labels[ensemble_pred_label]
p_model_result = labels[p_pred_label]
e_model_result = labels[e_pred_label]
return (f"**์ตœ์ข… ์•™์ƒ๋ธ” ์˜ˆ์ธก (OR ์ „๋žต): {ensemble_result}**\n\n"
f" - ์ฐธ๊ฐ€์ž ๋ชจ๋ธ (P-longBERT) ์˜ˆ์ธก: {p_model_result} (ํ™•๋ฅ : Control={p_probs[0]:.2f}, Depressed={p_probs[1]:.2f})\n"
f" - ์—˜๋ฆฌ ๋ชจ๋ธ (E-longBERT) ์˜ˆ์ธก: {e_model_result} (ํ™•๋ฅ : Control={e_probs[0]:.2f}, Depressed={e_probs[1]:.2f})\n\n"
f"**์ฐธ๊ณ :**\n"
f"- ์˜ˆ์ธก์€ ๊ฐ ๋Œ€ํ™” ๋‚ด์šฉ์—๋งŒ ๊ธฐ๋ฐ˜ํ•˜๋ฉฐ, ์‹ค์ œ ์ง„๋‹จ์€ ์ „๋ฌธ๊ฐ€์™€ ์ƒ๋‹ดํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.\n"
f"- GPU ํ™˜๊ฒฝ์—์„œ๋Š” ์˜ˆ์ธก์ด ๋น ๋ฅด๊ฒŒ ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค."
)
# =======================================================
# 5. Gradio UI ์ธํ„ฐํŽ˜์ด์Šค ์ƒ์„ฑ ๋ฐ ์‹คํ–‰
# =======================================================
print("\n--- Setting up Gradio UI ---")
# ๋ชจ๋ธ์ด ์„ฑ๊ณต์ ์œผ๋กœ ๋กœ๋“œ๋˜์—ˆ์„ ๊ฒฝ์šฐ์—๋งŒ Gradio UI๋ฅผ ์‹คํ–‰
if p_model_for_inference is not None and e_model_for_inference is not None:
gr.Interface(
fn=predict_depression,
inputs=[
gr.Textbox(lines=10, label="์ฐธ๊ฐ€์ž ๋ฐœํ™” ๋‚ด์šฉ (Participant's speech)", placeholder="์—ฌ๊ธฐ์— ์ฐธ๊ฐ€์ž์˜ ๋ฐœํ™” ๋‚ด์šฉ์„ ์ž…๋ ฅํ•˜์„ธ์š”..."),
gr.Textbox(lines=10, label="์—˜๋ฆฌ ๋ฐœํ™” ๋‚ด์šฉ (Ellie's speech)", placeholder="์—ฌ๊ธฐ์— ์—˜๋ฆฌ(๊ฐ€์ƒ ์—์ด์ „ํŠธ)์˜ ๋ฐœํ™” ๋‚ด์šฉ์„ ์ž…๋ ฅํ•˜์„ธ์š”... (์ „์ฒด ๋‚ด์šฉ ์ค‘ ํ›„๋ฐ˜๋ถ€๋งŒ ์‚ฌ์šฉ๋จ)")
],
outputs="markdown",
title="DAIC-WOZ ์šฐ์šธ์ฆ ๊ฐ์ง€ ์•™์ƒ๋ธ” ๋ชจ๋ธ (GPU ๊ฐ€์†)",
description=f"""์ด ์•ฑ์€ DAIC-WOZ ๋ฐ์ดํ„ฐ์…‹์„ ๊ธฐ๋ฐ˜์œผ๋กœ ์ฐธ๊ฐ€์ž์™€ ๊ฐ€์ƒ ์—์ด์ „ํŠธ(์—˜๋ฆฌ)์˜ ๋Œ€ํ™” ๋‚ด์šฉ์„ ๋ถ„์„ํ•˜์—ฌ ์šฐ์šธ์ฆ ์—ฌ๋ถ€๋ฅผ ์˜ˆ์ธกํ•ฉ๋‹ˆ๋‹ค.
P-longBERT (์ฐธ๊ฐ€์ž ๋ฐœํ™”)์™€ E-longBERT (์—˜๋ฆฌ ๋ฐœํ™”) ๋ชจ๋ธ์˜ ์•™์ƒ๋ธ” (OR ์ „๋žต) ๊ฒฐ๊ณผ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
**GPU ํ™˜๊ฒฝ์—์„œ๋Š” ์˜ˆ์ธก์ด ๋น ๋ฅด๊ฒŒ ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค.**
**์ฐธ๊ณ :** ์ด๋Š” AI ๋ชจ๋ธ์˜ ์˜ˆ์ธก์ผ ๋ฟ์ด๋ฉฐ, **์‹ค์ œ ์˜ํ•™์  ์ง„๋‹จ์€ ๋ฐ˜๋“œ์‹œ ์ „๋ฌธ๊ฐ€์™€ ์ƒ๋‹ดํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.**
์‚ฌ์šฉ ์ค‘์ธ ๋””๋ฐ”์ด์Šค: {device}
"""
).launch() # Hugging Face Spaces์—์„œ๋Š” share=True๊ฐ€ ํ•„์š” ์—†์Œ
else:
print("\nGradio UI could not be launched because models failed to load. Please check model files.")