我有一个数据集,包含1400个观测值和19列。目标变量的值为1(我最感兴趣的值)和0。类别分布不平衡(70:30)。
使用以下代码,我得到了奇怪的值(全部为1)。我无法确定这是由于过度拟合/不平衡数据还是特征选择问题(我使用了皮尔逊相关性,因为所有值都是数字/布尔类型)。我认为所采取的步骤可能有误。
import numpy as np
import math
import sklearn.metrics as metrics
from sklearn.metrics import f1_score
y = df['Label']
X = df.drop('Label',axis=1)
def create_cv(X,y):
if type(X)!=np.ndarray:
X=X.values
y=y.values
test_size=1/5
proportion_of_true=y[y==1].shape[0]/y.shape[0]
num_test_samples=math.ceil(y.shape[0]*test_size)
num_test_true_labels=math.floor(num_test_samples*proportion_of_true)
num_test_false_labels=math.floor(num_test_samples-num_test_true_labels)
y_test=np.concatenate([y[y==0][:num_test_false_labels],y[y==1][:num_test_true_labels]])
y_train=np.concatenate([y[y==0][num_test_false_labels:],y[y==1][num_test_true_labels:]])
X_test=np.concatenate([X[y==0][:num_test_false_labels] ,X[y==1][:num_test_true_labels]],axis=0)
X_train=np.concatenate([X[y==0][num_test_false_labels:],X[y==1][num_test_true_labels:]],axis=0)
return X_train,X_test,y_train,y_test
X_train,X_test,y_train,y_test=create_cv(X,y)
X_train,X_crossv,y_train,y_crossv=create_cv(X_train,y_train)
tree = DecisionTreeClassifier(max_depth = 5)
tree.fit(X_train, y_train)
y_predict_test = tree.predict(X_test)
print(classification_report(y_test, y_predict_test))
f1_score(y_test, y_predict_test)
输出:
precision recall f1-score support
0 1.00 1.00 1.00 24
1 1.00 1.00 1.00 70
accuracy 1.00 94
macro avg 1.00 1.00 1.00 94
weighted avg 1.00 1.00 1.00 94
在数据存在不平衡的情况下,使用交叉验证和/或欠采样构建分类器时,是否有人遇到类似的问题?如果您想要复制输出结果,我很乐意分享整个数据集。
我想要问您一些清晰的步骤,以便能够向我展示我正在做错了什么。
我知道为了减少过拟合并处理平衡数据,有一些方法,例如随机抽样(过度/欠采样),SMOTE,CV。我的想法是:
- 在考虑不平衡性的情况下将数据分成训练/测试集 - 对训练集进行交叉验证 - 仅对一个测试折进行欠采样 - 在通过CV选择模型后,对训练集进行欠采样并训练分类器 - 对未触及的测试集进行性能估计(f1分数)
就像在这个问题:CV and under sampling on a test fold中所概述的那样。
我认为上述步骤应该是有意义的,但我很乐意接受您可能对此的任何反馈。