当前位置: 首页 > 知识库问答 >
问题:

在不平衡数据中,如何以中等精度和召回率解释高AUC-ROC?

高和通
2023-03-14

我有一些机器学习的结果,我正试图弄明白。任务是预测/标记“爱尔兰人”与“非爱尔兰人”。Python 2.7的输出:

1= ir
0= non-ir
Class count:
0    4090942
1     940852
Name: ethnicity_scan, dtype: int64
Accuracy: 0.874921350119
Classification report:
             precision    recall  f1-score   support

          0       0.89      0.96      0.93   2045610
          1       0.74      0.51      0.60    470287

avg / total       0.87      0.87      0.87   2515897

Confusion matrix:
[[1961422   84188]
 [ 230497  239790]]
AUC-ir= 0.901238104773

如您所见,准确率和召回率一般,但AUC-ROC较高(~0.90)。我试图找出原因,我怀疑这是由于数据不平衡(大约1:5)。基于混淆矩阵,并使用Irish作为目标(),我计算了TPR=0.51和FPR=0.04。如果我将非爱尔兰人视为(),那么TPR=0.96,FPR=0.49。那么,当TPR在FPR=0.04时仅为0.5时,如何获得0.9 AUC?

代码:

try:
    for i in mass[k]:
        df = df_temp # reset df before each loop
        #$$
        #$$ 
        if 1==1:
        ###if i == singleEthnic:
            count+=1
            ethnicity_tar = str(i) # fr, en, ir, sc, others, ab, rus, ch, it, jp
            # fn, metis, inuit; algonquian, iroquoian, athapaskan, wakashan, siouan, salish, tsimshian, kootenay
            ############################################
            ############################################

            def ethnicity_target(row):
                try:
                    if row[ethnicity_var] == ethnicity_tar:
                        return 1
                    else:
                        return 0
                except: return None
            df['ethnicity_scan'] = df.apply(ethnicity_target, axis=1)
            print '1=', ethnicity_tar
            print '0=', 'non-'+ethnicity_tar

            # Random sampling a smaller dataframe for debugging
            rows = df.sample(n=subsample_size, random_state=seed) # Seed gives fixed randomness
            df = DataFrame(rows)
            print 'Class count:'
            print df['ethnicity_scan'].value_counts()

            # Assign X and y variables
            X = df.raw_name.values
            X2 = df.name.values
            X3 = df.gender.values
            X4 = df.location.values
            y = df.ethnicity_scan.values

            # Feature extraction functions
            def feature_full_name(nameString):
                try:
                    full_name = nameString
                    if len(full_name) > 1: # not accept name with only 1 character
                        return full_name
                    else: return '?'
                except: return '?'

            def feature_full_last_name(nameString):
                try:
                    last_name = nameString.rsplit(None, 1)[-1]
                    if len(last_name) > 1: # not accept name with only 1 character
                        return last_name
                    else: return '?'
                except: return '?'

            def feature_full_first_name(nameString):
                try:
                    first_name = nameString.rsplit(' ', 1)[0]
                    if len(first_name) > 1: # not accept name with only 1 character
                        return first_name
                    else: return '?'
                except: return '?'

            # Transform format of X variables, and spit out a numpy array for all features
            my_dict = [{'last-name': feature_full_last_name(i)} for i in X]
            my_dict5 = [{'first-name': feature_full_first_name(i)} for i in X]

            all_dict = []
            for i in range(0, len(my_dict)):
                temp_dict = dict(
                    my_dict[i].items() + my_dict5[i].items()
                    )
                all_dict.append(temp_dict)

            newX = dv.fit_transform(all_dict)

            # Separate the training and testing data sets
            X_train, X_test, y_train, y_test = cross_validation.train_test_split(newX, y, test_size=testTrainSplit)

            # Fitting X and y into model, using training data
            classifierUsed2.fit(X_train, y_train)

            # Making predictions using trained data
            y_train_predictions = classifierUsed2.predict(X_train)
            y_test_predictions = classifierUsed2.predict(X_test)

插入用于重新采样的代码:

try:
    for i in mass[k]:
        df = df_temp # reset df before each loop
        #$$
        #$$ 
        if 1==1:
        ###if i == singleEthnic:
            count+=1
            ethnicity_tar = str(i) # fr, en, ir, sc, others, ab, rus, ch, it, jp
            # fn, metis, inuit; algonquian, iroquoian, athapaskan, wakashan, siouan, salish, tsimshian, kootenay
            ############################################
            ############################################

            def ethnicity_target(row):
                try:
                    if row[ethnicity_var] == ethnicity_tar:
                        return 1
                    else:
                        return 0
                except: return None
            df['ethnicity_scan'] = df.apply(ethnicity_target, axis=1)
            print '1=', ethnicity_tar
            print '0=', 'non-'+ethnicity_tar

            # Resampled
            df_resampled = df.append(df[df.ethnicity_scan==0].sample(len(df)*5, replace=True))

            # Random sampling a smaller dataframe for debugging
            rows = df_resampled.sample(n=subsample_size, random_state=seed) # Seed gives fixed randomness
            df = DataFrame(rows)
            print 'Class count:'
            print df['ethnicity_scan'].value_counts()

            # Assign X and y variables
            X = df.raw_name.values
            X2 = df.name.values
            X3 = df.gender.values
            X4 = df.location.values
            y = df.ethnicity_scan.values

            # Feature extraction functions
            def feature_full_name(nameString):
                try:
                    full_name = nameString
                    if len(full_name) > 1: # not accept name with only 1 character
                        return full_name
                    else: return '?'
                except: return '?'

            def feature_full_last_name(nameString):
                try:
                    last_name = nameString.rsplit(None, 1)[-1]
                    if len(last_name) > 1: # not accept name with only 1 character
                        return last_name
                    else: return '?'
                except: return '?'

            def feature_full_first_name(nameString):
                try:
                    first_name = nameString.rsplit(' ', 1)[0]
                    if len(first_name) > 1: # not accept name with only 1 character
                        return first_name
                    else: return '?'
                except: return '?'

            # Transform format of X variables, and spit out a numpy array for all features
            my_dict = [{'last-name': feature_full_last_name(i)} for i in X]
            my_dict5 = [{'first-name': feature_full_first_name(i)} for i in X]

            all_dict = []
            for i in range(0, len(my_dict)):
                temp_dict = dict(
                    my_dict[i].items() + my_dict5[i].items()
                    )
                all_dict.append(temp_dict)

            newX = dv.fit_transform(all_dict)

            # Separate the training and testing data sets
            X_train, X_test, y_train, y_test = cross_validation.train_test_split(newX, y, test_size=testTrainSplit)

            # Fitting X and y into model, using training data
            classifierUsed2.fit(X_train, y_train)

            # Making predictions using trained data
            y_train_predictions = classifierUsed2.predict(X_train)
            y_test_predictions = classifierUsed2.predict(X_test)

共有1个答案

葛昕
2023-03-14

您的模型为其得分的测试集中的每一行输出概率P(介于0和1之间)。摘要统计数据(精度、召回率等)针对单个值P作为预测阈值,可能P=0.5,除非您在代码中对此进行了更改。然而,ROC包含更多信息,其想法是您可能不希望使用此默认值作为预测阈值,因此通过计算0和1之间每个预测阈值的真阳性与假阳性的比率来绘制ROC。

如果你在数据中对非爱尔兰人的抽样不足,那么你认为AUC和精确度会被高估是正确的;如果数据集只有5000行,那么在更大的训练集上运行模型不会有问题;只需重新平衡您的数据集(通过引导抽样来增加您的非爱尔兰人),直到您的数据集准确反映您的样本人口。

 类似资料:
  • 原始数据集中正负类不平衡比为1:10,采用过采样的方式处理过,也利用了分层交叉验证、网格搜素调参,最后模型训练精确率为92%,召回率只有69%。如何能提高呢?(特征选择使用卡方检验和随机森林算法进行筛选特征)

  • 问题内容: 我正在尝试在非常不平衡的数据集上使用LightGBM建立分类器。不平衡率,即: 我使用的参数和训练代码如下所示。 我运行简历来获得最好的模型和最好的回合。我的简历获得了0.994 AUC,并且在验证集中获得了类似的分数。 但是,当我在测试集上进行预测时,我得到的结果非常糟糕。我相信火车是完美采样的。 需要调整哪些参数?问题的原因是什么?我是否应该对数据集重新采样以减少最高等级? 问题答

  • 问题内容: 我正在使用Python,并且有一些混淆矩阵。我想通过多类分类中的混淆矩阵来计算精度,召回率和f测度。我的结果日志不包含和,仅包含混淆矩阵。 您能否告诉我如何从多类别分类的混淆矩阵中获得这些分数? 问题答案: 让我们考虑MNIST数据分类(10个类)的情况,对于10,000个样本的测试集,我们得到以下混淆矩阵(Numpy数组): 为了获得精度和召回率( 每类 ),我们需要计算 每类 的T

  • 本文向大家介绍如何解决数据不平衡问题?相关面试题,主要包含被问及如何解决数据不平衡问题?时的应答技巧和注意事项,需要的朋友参考一下 这主要是由于数据分布不平衡造成的。解决方法如下: 采样,对小样本进行加噪声采样,对大样本进行下采样 进行特殊的加权,如在Adaboost中或者SVM 采用对不平衡数据集不敏感的算法 改变评价标准:用AUC|ROC来进行评价 考虑数据的先验分布 https://blog

  • 问题内容: 我正在尝试使用PHP创建数据库驱动的网站,并使用PostgreSQL数据库中存储的数据(通过PDO访问),并且我将需要存储和处理高精度的十进制数(在某些情况下,十进制)。 我打算在数据库中使用NUMERIC或DECIMAL数据类型来存储此数据,以保持所需的高精度。 使用PHP来(1)访问这些值,以及(2)对这样的高精度数字执行基本算术的最佳方法是什么? 我不想只使用浮点数,因为该数据类

  • 我试图用斯坦福CRF常见问题解答中的Jane Austen文件验证我的基于Stanford CoreNLP的java代码。我正在使用以下命令进行CLI中常见问题解答中所述的培训: 这给了我以下结果: 现在我有了java代码来训练和测试模型程序: 这为精度/召回率/f1提供了不同的值: 测试、培训和奥斯汀。道具文件,未经修改,取自斯坦福大学。只有测试文件jane-austen-emma-ch2。ts