1.F1值优化
https://www.jianshu.com/p/51debab91824
from functools import partial
import numpy as np
import scipy as sp
from sklearn.metrics import f1_score
class OptimizedF1(object):
def __init__(self):
self.coef_ = []
def _kappa_loss(self, coef, X, y):
"""
y_hat = argmax(coef*X, axis=-1)
:param coef: (1D array) weights
:param X: (2D array)logits
:param y: (1D array) label
:return: -f1
"""
X_p = np.copy(X)
X_p = coef*X_p
ll = f1_score(y, np.argmax(X_p, axis=-1), average=‘macro‘)
return -ll
def fit(self, X, y):
loss_partial = partial(self._kappa_loss, X=X, y=y)
initial_coef = [1. for _ in range(len(set(y)))]#权重都初始化为1
self.coef_ = sp.optimize.minimize(loss_partial, initial_coef, method=‘nelder-mead‘)
def predict(self, X, y):
X_p = np.copy(X)
X_p = self.coef_[‘x‘] * X_p
return f1_score(y, np.argmax(X_p, axis=-1), average=‘macro‘)
def coefficients(self):
return self.coef_[‘x‘]
可以发现这个和https://mp.weixin.qq.com/s/jH9grYg-xiuQxMTDq99olg所提供的有序关系的离散标签优化所提供的代码,
主要是_kappa_loss和fit/predict函数的实现不同。
调用时:
op = OptimizedF1()
op.fit(logits,labels)
logits = op.coefficients()*logits
那么在进行预测时,就使用predict函数和logist相乘,然后再softmax取最值,这样就对每个都有一个缩放的权重。
2.优化分类阈值的实现
https://mp.weixin.qq.com/s/jH9grYg-xiuQxMTDq99olg
from functools import partial import numpy as np import scipy as sp class OptimizedRounder(object): def __init__(self): self.coef_ = 0 def _kappa_loss(self, coef, X, y): X_p = np.copy(X) for i, pred in enumerate(X_p): if pred < coef[0]: X_p[i] = 0 elif pred >= coef[0] and pred < coef[1]: X_p[i] = 1 elif pred >= coef[1] and pred < coef[2]: X_p[i] = 2 elif pred >= coef[2] and pred < coef[3]: X_p[i] = 3 else: X_p[i] = 4 ll = quadratic_weighted_kappa(y, X_p) return -ll def fit(self, X, y): loss_partial = partial(self._kappa_loss, X=X, y=y) initial_coef = [0.5, 1.5, 2.5, 3.5] self.coef_ = sp.optimize.minimize(loss_partial, initial_coef, method=‘nelder-mead‘) def predict(self, X, coef): X_p = np.copy(X) for i, pred in enumerate(X_p): if pred < coef[0]: X_p[i] = 0 elif pred >= coef[0] and pred < coef[1]: X_p[i] = 1 elif pred >= coef[1] and pred < coef[2]: X_p[i] = 2 elif pred >= coef[2] and pred < coef[3]: X_p[i] = 3 else: X_p[i] = 4 return X_p def coefficients(self): return self.coef_[‘x‘]
也学到了,那么在调用它的时候应该先fit,然后coefficients获取阈值参数,或者调用predict,然后和real labels做交叉熵损失这样。