如何在 Sklearn 的随机森林分类器中将训练模型用于另一个数据集?

Posted

技术标签:

【中文标题】如何在 Sklearn 的随机森林分类器中将训练模型用于另一个数据集?【英文标题】:How to use trained model for another dataset in Sklearn's Random Forest Classifier? 【发布时间】:2019-05-08 03:48:33 【问题描述】:

更新:一些“术语” 示例:行 特点:列 'labels' :预测的类(特征中的一列)。

基本上我想知道: 我有 dataset1 和 dataset2 在形状和大小方面相同。在使用 dataset1 进行训练和测试之后,我正在使用这个模型来预测 dataset2。 (特征数量也相同)。

如果我预测 dataset2 中的所有项目,准确率接近 dataset1 测试结果。但如果我从 dataset2 中为每个类选择 1 个项目,准确率约为 30%。完整数据集 2 的准确度怎么可能与“二次抽样”数据集 2 大不相同?

我正在使用 RandomForestClassifier。

我有一个包含大约 90 个类的 200K 样本(行)的数据集。经过训练和测试,准确率足够高(约 96%)。

现在,由于我有一个经过训练的模型,我正在使用另一个不同的数据库(同样有 20 万个样本和 90 个类)进行预测。

如果我提交第二个数据库中的所有样本,准确度就足够接近训练准确度(约 92%)。

但是,如果我从第二个数据库中选择 90 个样本(每个类别中的一个),则准确度不是我所期望的。 (约 30%)

.... data preprocessing is done.

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3)

from sklearn.ensemble import RandomForestClassifier
clf=RandomForestClassifier(n_estimators=nestimators, bootstrap=False, 
class_weight=None, criterion='entropy',
        max_features='auto', max_leaf_nodes=None,
        min_impurity_decrease=0.0, min_impurity_split=None,

        min_weight_fraction_leaf=0.0, n_jobs=6,
        oob_score=False, random_state=np.random.seed(1234), verbose=0, warm_start=False)
clf.fit(X_train,y_train)
y_pred=clf.predict(X_test)    

from sklearn import metrics
print("Accuracy:",metrics.accuracy_score(y_test, y_pred))

准确率约为 96%。

现在我正在使用这个训练有素的模型和一个新的数据库(形状相同):

df2=pd.read_csv("newdata.csv", low_memory=False, skipinitialspace=True, na_filter=False)
features=['col1','col2','col3','col4']
Xnew=df2[features].values
ynew=df2['labels'].values  # Labels
y_prednew=clf.predict(Xnew)

准确度高于 ~90%。接近第一个数据库准确性。但是

如果我用这个过滤这个新数据集为每个类的 1 个样本:

df2=pd.read_csv("newdata.csv", low_memory=False, skipinitialspace=True, na_filter=False)

samplesize=1
df2=df2.sample(frac=1)
df2=df2.groupby('labels')
df2=df2.head(samplesize).reset_index(drop=True)

features=['col1','col2','col3','col4']
Xnew=df2[features].values
ynew=df2['labels'].values  # Labels
y_prednew=clf.predict(Xnew)

... 准确度约为 35%。但是如果我不过滤这些新数据并将其提交给模型,准确率在 ~90% 以上。

第一和第二个数据集在形状上是相同的。如果我将第二个数据集中的所有样本都提供给这个训练好的模型,accurayc 接近第一个数据集的测试结果。但如果我从每个类中过滤出 1 个样本,准确度约为 30%。

我不知道我在哪里弄错了。

【问题讨论】:

你确定这里有错误吗?如果我使用样本量 = 1 而不是样本量 = 200K,那么获得低分我不会感到惊讶。 “类”是指features,对吗? 我说“类”是为了预测。特征是我的输入:col1 col2 col3 etc. 基本上,如果我将这个训练有素的模型用于另一个具有相同形状的数据库,准确度就是我所期望的。但是,如果我对第二个数据库进行二次抽样(eac 1234562 的 1 个样本 = 90 个样本而不是 200K 样本),准确率约为 30% 你用一个模型做出 90 种不同的预测?那你用多少特征来训练呢?我仍然不确定这是否真的是代码的问题。没有人向您保证,您为每个“类”抽取的一个样本(无论如何,我仍然与您的术语不太相关)可以由模型以与整个数据集相同的准确度进行预测。跨度> 是的数据集有 90 个不同的“类”。特征在256~左右。我没有得到的部分是,如果我使用包含所有 200K 样本的第二个数据库进行预测,模型准确性是合理的。但是,如果我将此数据集子采样到每个类中的 1 个样本(这意味着总共 90 个样本),准确率约为 35% 【参考方案1】:

通常代码看起来还可以。这很难知道,但我会冒险猜测这些类在数据集中的表示并不相同(至少是第二个,也许也是第一个),并且更占主导地位的类被更准确地识别出来。

经典示例是一些极其不平衡的二元分类任务,其中 99% 的样本为正样本。通过始终预测为正,您可以获得 99% 的准确率,但每个类的 1 个数据点的样本将有 50% 的准确率(虽然脱离上下文,准确率可能看起来不错,但该模型并不是很有用)。

我建议检查类频率,并使用其他指标(参见@​​987654321@、recall 和f1)和适当的average 参数来更准确地评估模型的性能。

总而言之,整个数据集的 90% 以上准确率和每个类的 1 个数据点样本的 30% 准确率并不一定相互冲突,例如如果数据集中的类不平衡。

编辑:简而言之,我想说的是,您可能正在体验Accuracy Paradox。

【讨论】:

感谢您抽出宝贵时间回答我的问题。我无法得到这样一个事实,即如果我将 dataset2 中的所有项目提交到训练模型,准确率超过 90%。但是,如果我从 dataset2 中为每个类选择 1 个样本(总共 90 个样本),准确率约为 30%。我还为每个类迭代地选择了 1 个样本,并对模型进行了 20 次测试。每次准确率都在 30% 左右。 你检查班级频率了吗?假设你有 90 个类,c1c2,...c90。还假设大约 92% 的样本是c42,并且模型几乎总是预测c42。那么对于整个数据集,您的准确度约为 92%,而对于每个类的一个数据点样本,您的准确度约为 1/90 =~ 1.1%。所以你所描述的可以用这种不平衡的不太严重的例子来解释(尽管这不是唯一的解释)。 简而言之,我的意思是您可能正在经历准确性悖论 - en.wikipedia.org/wiki/Accuracy_paradox 再次感谢您的宝贵时间。模型训练后的分数如下图。 (DataSet1)F1_Score - 宏:0.5922192285564758 F1_Score - Micro:0.9633939516061324 F1_Score - 加权:0.9585028022207839 Precision_Score - Macro:0.851618083669928 Precision_Score - Micro:0.0963939516061324 Precision_Score - 加权:0.0963924354819605 SPAN> 感谢这个有用的答案。我发现,如果我用 dataset1 训练我的模型,每个类的项目数量几乎相等,那么 dataset2 的准确率和每个类的 1 个样本的准确率都会达到峰值。我将其标记为 aswer。感谢您的宝贵时间。

以上是关于如何在 Sklearn 的随机森林分类器中将训练模型用于另一个数据集?的主要内容,如果未能解决你的问题,请参考以下文章

sklearn 随机森林分类器可以处理分类变量吗?

[机器学习python实践]Sklearn实现集成

sklearn中的随机森林

来自 sklearn 的 SelectFromModel 在随机森林和梯度提升分类器上提供了显着不同的特征

如何序列化大型随机森林分类器

sklearn库学习----随机森林(RandomForestClassifier,RandomForestRegressor)