개요
- Metrics는 평가 지표를 의미함
- qwk→ quadratic weighted kappa
- 단순 정확도 점수로는 의미가 없는 경우에 사용
- 두 평점의 동의도(agreement)를 측정함
- 동의도는 실제 평점과 예측 평점이 얼마나 가까운 지로 정의할 수 있다.
평가
- -1~1의 범위를 가진다
- 1에 가까울 수록 좋은 예측
- 0 미만은 무작위 예측 보다 성능이 떨어진다.
- 동의도(agreement)가 높을수록 1에 가까워지고, 동의도가 낮으면 0에 가까워진다.
예시
y_true = [1,2,3,1,2,3,1,2,3]
y_pred = [2,1,3,1,2,3,3,1,2]
metrics.cohen_kappa_score(y_true, y_pred, weights='quadratic'), metrics.accuracy_score(y_true, y_pred)
최적화
- 회귀 문제로 접근하기:
- 이 방법은 Quadratic Weighted Kappa (QWK)를 기본적으로 분류 지표로 사용하면서도 회귀 모델을 구축하여 Mean Squared Error (MSE)를 최소화하고 나서 결과를 반올림합니다. 이 접근 방식은 보다 나은 결과를 얻을 수 있으며, QWK를 손실 함수로 구현하는 것보다 훨씬 간단합니다.
- 예를 들어, 이전 섹션에서 나온 평균 예측에 반올림을 적용하고 모드 예측을 사용하여 반올림 임계값을 최적화하여 평균 예측을 개선할 수 있습니다.
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.metrics import cohen_kappa_score
# 데이터 생성 및 분할
np.random.seed(42)
data_size = 1000
X = np.random.rand(data_size, 10)
y = np.random.randint(0, 5, data_size)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 회귀 모델 훈련
model = LinearRegression()
model.fit(X_train, y_train)
# 예측값 생성
y_pred = model.predict(X_test)
# 예측값 변환
y_pred_clipped = y_pred.clip(0, 4) # 예측값을 0과 4 사이로 제한
y_pred_rounded = np.round(y_pred_clipped).astype(int) # 반올림 및 정수형 변환
# QWK 점수 계산
qwk_score = cohen_kappa_score(y_test, y_pred_rounded, weights='quadratic')
# 결과 출력
print(f"QWK Score: {qwk_score}")
- QWK를 직접 손실 함수로 사용하기:
- 이 방법은 TensorFlow/Keras 모델에서 직접적으로 QWK를 최적화합니다. 이를 위해 _cohen_kappa 함수를 사용하여 y_true와 y_pred 사이의 QWK를 계산하고, 이 값을 최대화하는 방향으로 모델을 훈련합니다.
- 이 함수는 내부적으로 QWK를 손실 값으로 반환하여 모델 훈련 시 QWK 점수를 최적화합니다
class QWKLoss(Loss):
def init(self, num_classes, name="QWKLoss"):
super().init(name=name)
self.num_classes = num_classes
def call(self, y_true, y_pred):
y_true = tf.cast(y_true, tf.int32)
y_pred = tf.clip_by_value(y_pred, 0, self.num_classes - 1)
y_pred = tf.round(y_pred)
y_true = tf.one_hot(y_true, depth=self.num_classes)
y_pred = tf.one_hot(tf.cast(y_pred, tf.int32), depth=self.num_classes)
weights = tf.constant([[1 - ((i - j) ** 2 / (self.num_classes - 1) ** 2)
for j in range(self.num_classes)]
for i in range(self.num_classes)], dtype=tf.float32)
hist_true = tf.reduce_sum(y_true, axis=0)
hist_pred = tf.reduce_sum(y_pred, axis=0)
expected_matrix = tf.tensordot(hist_true, hist_pred, axes=0) / tf.reduce_sum(hist_true)
observed_matrix = tf.tensordot(tf.transpose(y_true), y_pred, axes=1)
num = tf.reduce_sum(weights * observed_matrix)
denom = tf.reduce_sum(weights * expected_matrix)
return 1 - num / denom
# 3. 모델 정의 및 컴파일
model = Sequential([
Dense(64, input_dim=10, activation='relu'),
Dense(32, activation='relu'),
Dense(1, activation='linear')
])
model.compile(optimizer='adam', loss=QWKLoss(num_classes=5))
위 예시는 GPT로 생성한 예제로 정확하지 않음
추후 직접 사용해보면서 문제 발견시 수정하겠습니다.
'ai' 카테고리의 다른 글
미로 찾기 강화학습 과제 후기(3가지 열쇠, 3가지의 문 그리고 Q learning을 곁들인) (1) | 2024.11.10 |
---|---|
optimizer & adam (0) | 2024.05.08 |
분류 평가 지표 (0) | 2024.03.18 |