我面临着不平衡回归问题,我已经尝试了多种方法来解决这个问题。最终,我遇到了这个称为 SERA(平方误差相关区域)的新指标,作为本文中提到的不平衡回归的自定义评分函数。 https://link.springer.com/article/10.1007/s10994-020-05900-9
为了计算 SERA,您必须计算相关函数 phi,该函数以小步长从 0 变化到 1。对于每个相关性 (phi) 值(例如 0.45),选择训练数据集的一个子集,其中相关性大于或等于该值(例如 0.45)。对于选定的训练子集,计算平方误差之和,即 sum(y_true - y_pred)**2,称为平方误差相关性 (SER)。然后计算我们为 SER 与 phi 和曲线下面积创建的图,即 SERA。
这是我的实现,受到 this StackOverflow 中其他问题的启发:
import pandas as pd
from scipy.integrate import simps
from sklearn.metrics import make_scorer
def calc_sera(y_true, y_pred,x_relevance=None):
# creating a list from 0 to 1 with 0.001 interval
start_range = 0
end_range = 1
interval_size = 0.001
list_1 = [round(val * interval_size, 3) for val in range(1, 1000)]
list_1.append(start_range)
list_1.append(end_range)
epsilon = sorted(list_1, key=lambda x: float(x))
df = pd.concat([y_true,y_pred,x_relevance],axis=1,keys= ['true', 'pred', 'phi'])
# Initiating lists to store relevance(phi) and squared-error relevance (ser)
relevance = []
ser = []
# Converting the dataframe to a numpy array
rel_arr = x_relevance
# selecting a phi value
for phi in epsilon:
relevance.append(phi)
error_squared_sum = 0
error_squared_sum = sum((df[df.phi>=phi]['true'] - df[df.phi>=phi]['pred'])**2)
ser.append(error_squared_sum)
# squared-error relevance area (sera)
# numerical integration using simps(y, x)
sera = simps(ser, relevance)
return sera
sera = make_scorer(calc_sera, x_relevance=X['relevance'], greater_is_better=False)
我使用这个分数作为评估指标来实现一个简单的 GridSearch 来选择最佳模型:
model = CatBoostRegressor(random_state=0)
cv = KFold(n_splits = 5, shuffle = True, random_state = 42)
parameters = {'depth': [6,8,10],'learning_rate' : [0.01, 0.05, 0.1],'iterations': [100, 200, 500,1000]}
clf = GridSearchCV(estimator=model,
param_grid=parameters,
scoring=sera,
verbose=0,cv=cv)
clf.fit(X=X.drop(columns=['relevance']),
y=y,
sample_weight=X['relevance'])
print("Best parameters:", clf.best_params_)
print("Lowest SERA: ", clf.best_score_)
我还将相关性函数作为权重添加到模型中,以便它可以在学习任务中应用该权重。但是,我得到的输出是这样的:
Best parameters: {'depth': 6, 'iterations': 100, 'learning_rate': 0.01}
Lowest SERA: nan
关于为什么 SERA 值返回 nan 有任何线索吗?我应该以另一种方式实现吗?
每当您在网格搜索中获得意外的 NaN 分数时,您应该设置参数
error_score="raise"
来获取错误回溯,并从那里进行调试。
在这种情况下,我认为我看到了问题:
sera
是用x_relevance=X['relevance']
定义的,其中包括X
的所有行。但在搜索中,您正在交叉验证:每个测试集的行数较少,而这些行将被调用。我可以想到几个选择;我也没有测试过,所以如果有问题请告诉我。使用pandas索引
sera
中,只需设置
pd.concat
。如果 join="inner"
是原始 pandas 系列的一部分(我认为这就是 y_true
将如何传递它......),那么串联将连接到这些行索引,因此保留整个 GridSearchCV
就可以了:它只会删除不相关的行。 X['relevance']
很可能是一个 numpy 数组,因此您可能需要首先适当地设置其索引?保持相关性 y_pred
X
引用
relevance
列。为此,您需要从拟合数据中删除该列,这对于训练集可能很难做到,但对于测试集则不然;然而,CatBoost 有一个我认为应该起作用的 X
参数。