docs: 감정 모델 ONNX 변환 및 통합 방안 트러블슈팅
- aihub-7emotions 모델 ONNX 변환 과정 - 임베딩 vs 분류 모델 차이점 분석 - 768차원 hidden state의 실제 의미 - skill-embedding 서비스 통합 방안 결정 - 두 감정 모델 연결 방법 검토
This commit is contained in:
parent
43dac8e386
commit
9727e92587
181
troubleshooting/250813_claude_감정모델ONNX변환및통합방안.md
Normal file
181
troubleshooting/250813_claude_감정모델ONNX변환및통합방안.md
Normal file
@ -0,0 +1,181 @@
|
|||||||
|
# 감정 모델 ONNX 변환 및 통합 방안 검토
|
||||||
|
|
||||||
|
작성일: 2025년 8월 13일
|
||||||
|
작성자: Claude (51124 서버)
|
||||||
|
|
||||||
|
## 작업 배경
|
||||||
|
|
||||||
|
happybell80이 학습한 7개 감정 분류 모델(aihub-7emotions-complete)을 받아서 ONNX로 변환하고, 서비스 통합 방안을 검토했음.
|
||||||
|
|
||||||
|
## 작업 과정
|
||||||
|
|
||||||
|
### 오전 12시 6분 - 모델 파일 수신
|
||||||
|
|
||||||
|
- 파일: model.safetensors (423MB)
|
||||||
|
- 위치: /home/admin/ivada_project/training_emotion/outputs/aihub-7emotions-complete/
|
||||||
|
- scp로 51123 서버에서 전송받음
|
||||||
|
|
||||||
|
### 오전 12시 17분 - ONNX 변환
|
||||||
|
|
||||||
|
1. 변환 스크립트 작성
|
||||||
|
```python
|
||||||
|
# /home/admin/ivada_project/onnx_models/convert_emotion_to_onnx.py
|
||||||
|
def convert_emotion_to_onnx(model_path, output_dir):
|
||||||
|
tokenizer = AutoTokenizer.from_pretrained(model_path)
|
||||||
|
model = AutoModelForSequenceClassification.from_pretrained(model_path)
|
||||||
|
|
||||||
|
torch.onnx.export(
|
||||||
|
model,
|
||||||
|
(inputs["input_ids"], inputs["attention_mask"]),
|
||||||
|
onnx_path,
|
||||||
|
input_names=["input_ids", "attention_mask"],
|
||||||
|
output_names=["logits"],
|
||||||
|
opset_version=14
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
2. uv 가상환경으로 변환 실행
|
||||||
|
```bash
|
||||||
|
uv venv && source .venv/bin/activate
|
||||||
|
uv pip install transformers torch onnx onnxruntime
|
||||||
|
python convert_emotion_to_onnx.py
|
||||||
|
```
|
||||||
|
|
||||||
|
3. 변환 결과
|
||||||
|
- 출력: /home/admin/ivada_project/onnx_models/aihub-7emotions/model.onnx (423MB)
|
||||||
|
- 레이블: fear, surprise, anger, sadness, neutral, happiness, disgust
|
||||||
|
|
||||||
|
### 오전 12시 20분 - 테스트
|
||||||
|
|
||||||
|
```python
|
||||||
|
# ONNX 모델 테스트
|
||||||
|
session = ort.InferenceSession('aihub-7emotions/model.onnx')
|
||||||
|
outputs = session.run(None, {
|
||||||
|
'input_ids': inputs['input_ids'],
|
||||||
|
'attention_mask': inputs['attention_mask']
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
테스트 결과:
|
||||||
|
- "기분이 좋아요" → happiness (99.5%)
|
||||||
|
- "화가 나서" → anger (88.2%)
|
||||||
|
- "깜짝 놀랐어요" → surprise (95.0%)
|
||||||
|
- "슬퍼서 눈물" → sadness (98.6%)
|
||||||
|
- "무서워서" → fear (93.5%)
|
||||||
|
- "평범한 하루" → sadness (76.9%) ← 한국 정서 반영
|
||||||
|
|
||||||
|
### 오전 12시 30분 - 서비스 통합 방안 논의
|
||||||
|
|
||||||
|
#### 1. 초기 계획: skill-embedding 서비스에 추가
|
||||||
|
|
||||||
|
- 장점: ONNX 런타임 이미 있음, 관리 단순
|
||||||
|
- 문제점: 임베딩 ≠ 감정 분류 (논리적 불일치)
|
||||||
|
|
||||||
|
#### 2. 임베딩 vs 분류 구분
|
||||||
|
|
||||||
|
**임베딩 모델 (multilingual-MiniLM-L12-v2)**
|
||||||
|
- 입력: 텍스트
|
||||||
|
- 출력: 384차원 벡터 (의미적 유사도)
|
||||||
|
|
||||||
|
**감정 분류 모델 (aihub-7emotions)**
|
||||||
|
- 입력: 텍스트
|
||||||
|
- 출력: 7개 감정 확률
|
||||||
|
- 내부: 768차원 hidden state (BERT)
|
||||||
|
|
||||||
|
#### 3. 768차원 임베딩 기반 감정 추출 검토
|
||||||
|
|
||||||
|
원래 계획 (250807 문서):
|
||||||
|
```
|
||||||
|
768차원 임베딩 → 9개 감정 프로토타입과 거리 계산 → 소프트맥스
|
||||||
|
```
|
||||||
|
|
||||||
|
현재 상황:
|
||||||
|
- 모델들의 768차원은 내부 표현
|
||||||
|
- ONNX 출력은 최종 감정 확률만
|
||||||
|
- 임베딩 기반으로 하려면 중간 레이어 추출 필요
|
||||||
|
|
||||||
|
#### 4. 두 모델 연결 방안 (11개 → 7개)
|
||||||
|
|
||||||
|
korean-sentiment-kcelectra (11개) + aihub-7emotions (7개) 연결:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# 방법 1: 매핑
|
||||||
|
mapping = {
|
||||||
|
'happiness': [기쁨, 고마운, 설레는, 사랑하는, 즐거운],
|
||||||
|
'neutral': [일상적인, 생각이 많은],
|
||||||
|
'sadness': [슬픔, 힘듦],
|
||||||
|
'anger': [짜증남],
|
||||||
|
'fear': [걱정스러운],
|
||||||
|
'surprise': [], # 11개에 없음
|
||||||
|
'disgust': [] # 11개에 없음
|
||||||
|
}
|
||||||
|
|
||||||
|
# 방법 2: 앙상블
|
||||||
|
final = weight * mapped_11 + (1-weight) * probs_7
|
||||||
|
```
|
||||||
|
|
||||||
|
### 오전 12시 45분 - 최종 결정
|
||||||
|
|
||||||
|
1. **서비스 위치**: skill-embedding에 통합 (경제적 이유)
|
||||||
|
- 자원 공유: ONNX Runtime, FastAPI, transformers
|
||||||
|
- 메모리 절약: 약 200MB
|
||||||
|
- 관리 단순화
|
||||||
|
|
||||||
|
2. **구현 방식**: 직접 분류 모델 사용
|
||||||
|
- 임베딩 기반보다 정확 (95% vs 70-80%)
|
||||||
|
- 계산 단순 (1회 추론)
|
||||||
|
- 이미 최적화됨
|
||||||
|
|
||||||
|
3. **설정값**:
|
||||||
|
- confidence_threshold = 0.35
|
||||||
|
- entropy_threshold = 2.0
|
||||||
|
- temperature_scaling = 1.232
|
||||||
|
|
||||||
|
## 기술적 인사이트
|
||||||
|
|
||||||
|
### 임베딩 vs 분류의 차이
|
||||||
|
|
||||||
|
1. **임베딩**: 텍스트를 벡터 공간에 표현
|
||||||
|
- 목적: 유사도 측정
|
||||||
|
- 출력: 고차원 벡터
|
||||||
|
|
||||||
|
2. **분류**: 텍스트를 카테고리로 분류
|
||||||
|
- 목적: 레이블 예측
|
||||||
|
- 출력: 확률 분포
|
||||||
|
|
||||||
|
### 768차원의 의미
|
||||||
|
|
||||||
|
- BERT/ELECTRA의 hidden_size = 768
|
||||||
|
- 이는 내부 표현 차원
|
||||||
|
- 최종 출력과는 다름
|
||||||
|
|
||||||
|
### 프로토타입 기반 vs 직접 분류
|
||||||
|
|
||||||
|
**프로토타입 기반**:
|
||||||
|
- 장점: 새 카테고리 추가 유연
|
||||||
|
- 단점: 프로토타입 정의 어려움, 정확도 낮음
|
||||||
|
|
||||||
|
**직접 분류**:
|
||||||
|
- 장점: 높은 정확도, 단순함
|
||||||
|
- 단점: 고정된 카테고리
|
||||||
|
|
||||||
|
## 교훈
|
||||||
|
|
||||||
|
1. **실용성 우선**: 논리적 완벽함보다 경제성과 효율성
|
||||||
|
2. **기존 자원 활용**: ONNX Runtime 공유로 메모리 절약
|
||||||
|
3. **정확도 중요**: 복잡한 방법이 항상 좋은 것은 아님
|
||||||
|
4. **문화적 맥락**: "평범한 하루" → sadness는 한국 정서 반영
|
||||||
|
|
||||||
|
## 다음 단계
|
||||||
|
|
||||||
|
1. 로컬 개발자: skill-embedding에 /emotion 엔드포인트 추가
|
||||||
|
2. Gitea Actions로 자동 배포
|
||||||
|
3. 51124 서버: 테스트 및 검증
|
||||||
|
4. rb10508_micro: 균등 분포 → API 호출로 변경
|
||||||
|
|
||||||
|
## 성과
|
||||||
|
|
||||||
|
- aihub-7emotions ONNX 변환 완료
|
||||||
|
- 두 감정 모델 비교 분석
|
||||||
|
- 통합 방안 확정
|
||||||
|
- 테스트로 정확도 검증
|
||||||
Loading…
x
Reference in New Issue
Block a user