import torch
import torch.nn as nn
from transformers import AutoTokenizer, AutoModel
import streamlit as st
import os
import numpy as np
st.markdown("""
""", unsafe_allow_html=True)
KOTE_LABELS = [
'불평/불만', '환영/호의', '감동/감탄', '지긋지긋', '고마움', '슬픔', '화남/분노', '존경',
'기대감', '우쭐댐/무시함', '안타까움/실망', '비장함', '의심/불신', '뿌듯함', '편안/쾌적',
'신기함/관심', '아껴주는', '부끄러움', '공포/무서움', '절망', '한심함', '역겨움/징그러움',
'짜증', '어이없음', '없음', '패배/자기혐오', '귀찮음', '힘듦/지침', '즐거움/신남', '깨달음',
'죄책감', '증오/혐오', '흐뭇함(귀여움/예쁨)', '당황/난처', '경악', '부담/안_내킴', '서러움',
'재미없음', '불쌍함/연민', '놀람', '행복', '불안/걱정', '기쁨', '안심/신뢰'
]
class MLPClassifier(nn.Module):
def __init__(self, input_dim=1024, num_labels=44):
super(MLPClassifier, self).__init__()
self.mlp = nn.Sequential(
nn.Linear(input_dim, 512),
nn.BatchNorm1d(512),
nn.ReLU(),
nn.Dropout(0.3),
nn.Linear(512, 256),
nn.BatchNorm1d(256),
nn.ReLU(),
nn.Dropout(0.3),
nn.Linear(256, num_labels)
)
def forward(self, x):
return self.mlp(x)
@st.cache_resource
def load_model():
device = torch.device("cpu")
tokenizer = AutoTokenizer.from_pretrained("klue/roberta-large")
base_model = AutoModel.from_pretrained("klue/roberta-large").eval()
mlp_model = MLPClassifier().eval()
ckpt_path = os.path.join("checkpoints", "mlp_model.pth")
mlp_model.load_state_dict(torch.load(ckpt_path, map_location=device))
return tokenizer, base_model, mlp_model
tokenizer, base_model, mlp_model = load_model()
def predict_emotion(text, top_k=5):
encoded = tokenizer(text, return_tensors="pt", truncation=True, padding="max_length", max_length=512)
with torch.no_grad():
outputs = base_model(**encoded)
cls_emb = outputs.last_hidden_state[:, 0, :]
logits = mlp_model(cls_emb)
probs = torch.sigmoid(logits).squeeze(0).numpy()
result = sorted(zip(KOTE_LABELS, probs), key=lambda x: x[1], reverse=True)
return result[:top_k], probs
tabs = st.tabs(["감정 분석 체험", "AI는 어떻게 감정을 이해할까?", "Few-shot Fine-tuning이란?", "활용과 의의", "기타 자료료"])
with tabs[0]:
st.markdown('
🎭 한국어 감정 분석 AI 체험
', unsafe_allow_html=True)
st.markdown('2025년 1학기 디지털 인문학 입문 (SLA23501) · Team 샐러드볼
강수현 · 김동우 · 정예은 · 정현성 · 최종윤
', unsafe_allow_html=True)
st.markdown("""
인공지능은 입력된 문장을 분석해 감정이 어떻게 표현되었는지를 예측합니다.
아래에 문장을 입력하거나 예시 문장을 불러온 후, 감정 예측 버튼을 눌러 체험해보세요.
""", unsafe_allow_html=True)
if "text_input" not in st.session_state:
st.session_state.text_input = ""
col1, col2 = st.columns([1, 1])
with col1:
if st.button("📌 예시 문장 불러오기"):
st.session_state.text_input = "그걸 이제 말해줘? 친절하네 정말"
with col2:
predict_clicked = st.button("🔍 감정 예측하기")
text = st.text_area(
"✍️ 문장을 입력하세요:",
value=st.session_state.text_input,
height=120,
placeholder="예: 오늘 하루 정말 행복했어요."
)
st.session_state.text_input = text
if predict_clicked:
if text.strip():
with st.spinner("AI가 감정을 분석 중입니다..."):
results, full_probs = predict_emotion(text)
top_emotion, top_prob = results[0]
st.markdown(
f'✅ 가장 강하게 표현된 감정: {top_emotion} ({top_prob:.2f})
',
unsafe_allow_html=True
)
st.subheader("📊 상위 감정 결과")
for label, prob in results:
st.markdown(f"- **{label}**: `{prob:.3f}`")
st.subheader("📈 확률 분포 (Top 5)")
st.bar_chart({label: prob for label, prob in results})
st.markdown("
", unsafe_allow_html=True)
else:
st.warning("문장을 먼저 입력해주세요.")
with tabs[1]:
st.markdown('🤖 인공지능은 감정을 어떻게 이해할까요?
', unsafe_allow_html=True)
st.markdown("""
인공지능은 문장을 '숫자의 벡터'로 바꾸어 이해합니다.
이 과정은 다음과 같은 단계로 이루어집니다:
- 사전학습 언어 모델(KLUE-RoBERTa)이 문장을 읽고 핵심 의미를 추출합니다.
- 이 결과를 바탕으로 감정 분류기(MLP)가 감정을 예측합니다.
- 각 감정에 대한 가능성을 확률로 보여줍니다.
""", unsafe_allow_html=True)
with tabs[2]:
st.markdown('🧠 Few-shot Fine-tuning이란?
', unsafe_allow_html=True)
st.markdown("""
우리가 사용하는 KLUE-RoBERTa 모델은 이미 수많은 문장을 학습한 거대한 언어 모델입니다.
하지만 감정 분석이라는 특정한 작업에 맞게 조금 더 학습시키는 과정이 필요합니다.
이때 전체 모델을 다시 학습하지 않고, 마지막 분류기(MLP)만 학습하는 방식이 바로
Few-shot Fine-tuning입니다.
이 방법을 통해 적은 양의 감정 데이터만으로도 높은 성능을 달성할 수 있습니다.
""", unsafe_allow_html=True)
with tabs[3]:
st.markdown('📌 이 기술은 어디에 쓰일 수 있을까요?
', unsafe_allow_html=True)
st.markdown("""
이 감정 분석 기술은 단순히 문장의 감정을 분류하는 데 그치지 않고,
디지털 사회에서의 감정 흐름과
공론장의 정서적 구조를 이해하는 데까지 확장될 수 있습니다.
특히 다음과 같은 분야에 활용될 수 있습니다:
- 😡 악성 댓글 탐지: 유해 표현, 혐오 표현을 조기에 감지하고 필터링
- 📈 댓글 감정 흐름 시각화: 유튜브나 뉴스 댓글에서 감정 전파 구조 분석
- 📰 사회 이슈 공감/혐오 반응 추적: 특정 사건에 대한 감정 반응 모니터링
- 💬 온라인 공론장 감정 전염 연구: 감정이 댓글-대댓글로 어떻게 확산되는지 정량적 분석
나아가 이 기술은
디지털 인문학의 새로운 분석 도구로 활용되어,
텍스트 기반 여론의 정서적 구조를 보다 깊이 있게 이해하는 기반이 될 수 있습니다.
""", unsafe_allow_html=True)
with tabs[4]:
st.image("image/clustering-2.png", use_column_width=True)
st.image("image/clustering-10.png", use_column_width=True)
st.image("image/clustering-plutchiks.png", use_column_width=True)
st.image("image/clustering-plutchiks-bert.png", use_column_width=True)