【问题标题】:Machine learning: Classification on imbalanced data机器学习:不平衡数据的分类
【发布时间】:2017-03-26 21:08:23
【问题描述】:

我正在使用 Python 的 sklearn + xgboost 模块解决分类问题。我有一个高度不平衡的数据,大约 92% 的 0 类和只有 8% 的 1 类。火车数据集可以在这里下载。 http://www.filedropper.com/kangarootrain

我不能在这个数据集中使用 numclaims 和 claimcst0 变量。 该数据集中的变量是: id,claimcst0,veh_value,exposure,veh_body,veh_age,gender,area,agecat,clm,numclaims

gender、area 和 agecat 是分类变量,其余是连续变量。 Id 是该记录的 ID。

前 10 条记录是

id,claimcst0,veh_value,exposure,veh_body,veh_age,gender,area,agecat,clm,numclaims
1,0,6.43,0.241897754,STNWG,1,M,A,3,0,0
2,0,4.46,0.856522757,STNWG,1,M,A,3,0,0
3,0,1.7,0.417516596,HBACK,1,M,A,4,0,0
4,0,0.48,0.626974524,SEDAN,4,F,A,6,0,0
5,0,1.96,0.089770031,HBACK,1,F,A,2,0,0
6,0,1.78,0.25654335,HBACK,2,M,A,3,0,0
7,0,2.7,0.688128611,UTE,2,M,A,1,0,0
8,0,0.94,0.912765859,STNWG,4,M,A,2,0,0
9,0,1.98,0.157753423,SEDAN,2,M,A,4,0,0

我尝试了几种方法来预测我的目标变量“clm”。我试过 knn、RF、svm、nb。我什至尝试对数据进行二次抽样。但无论我做什么都不会使预测更好。通过树木/增强,我得到了大约 93% 的准确率,但这仅仅是因为我正确地预测了所有的 0。

模型也错误地将所有 1 预测为 0。

任何帮助都会非常有帮助。这是我为 NB 尝试的基本代码。

from sklearn.naive_bayes import GaussianNB

clfnb = GaussianNB()
clfnb.fit(x_train, y_train)
pred = clfnb.predict(x_test)
#print set(pred)
from sklearn.metrics import accuracy_score, confusion_matrix
print accuracy_score(y_test, pred)
print confusion_matrix(y_test, pred)

0.92816091954
[[8398    0]
[ 650    0]]

【问题讨论】:

  • This community 可能更适合您的问题。这实际上与实现无关,而是算法、参数和技术的选择。
  • 好的。谢谢@Maurice
  • 您可能想要添加有关数据集的特征和标签的更多详细信息 - 不要指望人们会从可疑来源下载数据集(无意冒犯)。

标签: python machine-learning scikit-learn


【解决方案1】:

如果不是更糟的话,我也确实有这个问题。我发现的一种解决方案是根据这些对 1 进行过采样:

http://www.data-mining-blog.com/tips-and-tutorials/overrepresentation-oversampling/

https://yiminwu.wordpress.com/2013/12/03/how-to-undo-oversampling-explained/

【讨论】:

    【解决方案2】:

    这是一个很常见的挑战,即您的 2 个类别不平衡。为了克服只能很好地预测一个类别的问题,您必须使用平衡的训练集。有几种解决方案,最基本的是对数据进行均匀采样。由于您有大约 1500 个 1 样本,因此您还应该得到 1500 个 0。

    n = 1500
    sample_yes = data.ix[data.y == 1].sample(n=n, replace=False, random_state=0)
    sample_no = data.ix[data.y == 0].sample(n=n, replace=False, random_state=0)
    df = pd.concat([sample_yes, sample_no])
    

    data 是原始数据框。您应该在将数据拆分为训练集和测试集之前执行此操作。

    【讨论】:

    • 我试过了,但这甚至使分类器的性能更差。
    • 当然,这是完全正常的。您的模型目前将所有内容分类为 0。所以基本上你对 0 有 100% 的准确度,对 1 有 0% 的准确度。 93% 只是因为你的测试集中有那么多 0。
    • 当您采样 50-50% 时,您的混淆矩阵看起来如何?如果这两个类别的准确率都达到 80%,那可能是一个很好的结果!
    • 在 50-50 的情况下,我的准确度约为 0.60,f 得分为 0.18。那很糟糕。我尝试在 R 中使用 SMOTE/ROSE 进行过采样,但没有太大帮助。
    【解决方案3】:

    您可以将 class_weight 参数分配给不平衡数据集。例如,在这种情况下,由于标签 1 仅包含 8% 的数据,因此您在进行分类时赋予标签更高的权重。

    class_weight : {dict, ‘balanced’}, optional Set the parameter C of class i to class_weight[i]*C for SVC. If not given, all classes are supposed to have weight one. The “balanced” mode uses the values of y to automatically adjust weights inversely proportional to class frequencies in the input data as n_samples / (n_classes * np.bincount(y))

    【讨论】:

      【解决方案4】:

      对于不平衡的数据集,我在 Xgboost 中使用了“weights”参数,其中 weights 是根据数据所属的类分配的权重数组。

      def CreateBalancedSampleWeights(y_train, largest_class_weight_coef):
      classes = np.unique(y_train, axis = 0)
      classes.sort()
      class_samples = np.bincount(y_train)
      total_samples = class_samples.sum()
      n_classes = len(class_samples)
      weights = total_samples / (n_classes * class_samples * 1.0)
      class_weight_dict = {key : value for (key, value) in zip(classes, weights)}
      class_weight_dict[classes[1]] = class_weight_dict[classes[1]] * 
      largest_class_weight_coef
      sample_weights = [class_weight_dict[y] for y in y_train]
      return sample_weights
      

      只需传递目标列和最频繁类的出现率(如果最频繁类在 100 个样本中有 75 个,则为 0.75)

      largest_class_weight_coef = 
      max(df_copy['Category'].value_counts().values)/df.shape[0]
      
      #pass y_train as numpy array
      weight = CreateBalancedSampleWeights(y_train, largest_class_weight_coef)
      
      #And then use it like this
      xg = XGBClassifier(n_estimators=1000, weights = weight, max_depth=20)
      

      就是这样:) 现在,您的模型将为频率较低的类数据赋予更多权重。

      【讨论】:

        猜你喜欢
        • 2018-03-02
        • 2018-12-14
        • 2017-09-19
        • 1970-01-01
        • 2017-03-29
        • 2020-01-11
        • 2016-02-22
        • 2016-09-19
        • 2023-03-12
        相关资源
        最近更新 更多