如何有效地比较所有模型的准确性

Posted

技术标签:

【中文标题】如何有效地比较所有模型的准确性【英文标题】:How to effectively compare all models accuracy [closed] 【发布时间】:2019-07-09 17:14:01 【问题描述】:

我已经拆分了训练数据并初始化了 11 个我现在想要比较的分类器模型。

我在 Ubuntu 18.04 上运行 VS Code。

我试过了:

# Prepare lists
models = [ran, knn, log, xgb, gbc, svc, ext, ada, gnb, gpc, bag]         
scores = []

# Sequentially fit and cross validate all models
for mod in models:
    mod.fit(X_train, y_train)
    acc = cross_val_score(mod, X_train, y_train, scoring = 
    "accuracy", cv = 10)
scores.append(acc.mean())

# Creating a table of results, ranked highest to lowest
results = pd.DataFrame(
    'Model': ['Random Forest', 'K Nearest Neighbour', 'Logistic 
     Regression', 'XGBoost', 'Gradient Boosting', 'SVC', 'Extra 
     Trees', 'AdaBoost', 'Gaussian Naive Bayes', 'Gaussian Process', 
     'Bagging Classifier'],
     'Score': scores)

在最后一部分返回:

ValueError: 数组的长度必须相同

我数了 2 倍,确实有 11 个模型。

我错过了什么?

【问题讨论】:

究竟在哪里弹出错误?请包含完整的错误跟踪... @desertnaut 熊猫数据框返回错误。 您是否检查了下面的答案(即将scores.append()for 循环的其余部分内联)? 欢迎来到 SO;如果其中一个答案解决了您的问题,请接受(请参阅What should I do when someone answers my question?) 没有一个好到可以接受的答案? 【参考方案1】:

您的代码中似乎存在缩进错误,请参阅下面的编辑代码。在您的代码中,如果您执行len(scores),您将获得1,因为只有最后一个值被添加,因为在循环外调用了追加。

# Prepare lists
models = [ran, knn, log, xgb, gbc, svc, ext, ada, gnb, gpc, bag]         
scores = []

# Sequentially fit and cross validate all models
for mod in models:
    mod.fit(X_train, y_train)
    acc = cross_val_score(mod, X_train, y_train, scoring = 
    "accuracy", cv = 10)
    scores.append(acc.mean())

【讨论】:

不,这不是问题。代码的最后一部分 pandas 数据帧返回错误。 @StanislavJirak 这并不意味着答案是错误的;正如您的代码一样,scores 原来是一个单元素列表(即,您只附加了 for 循环中的最后一个 acc.mean()),这确实会产生您在下游报告的错误;请包含完整的错误跟踪... @StanislavJirak,您可以在您的代码中查看scores 的长度,即1。您正在尝试创建一个数据框,其中一列中包含 11 条目,另一列中包含 1 条目,这会引发错误。 Pandas 抛出错误,该错误的发生是因为列的长度不正确。 我现在明白了。但是如何创建一个有 11 列的空数组呢?我试过代码。 什么意思?为什么要创建任何空数组?此处建议的补救措施可以解决您的问题,另请参阅我的佐证答案...,【参考方案2】:

已经对上一个答案投了赞成票,我继续证明该错误确实是由于您的score.append() 在您的for 循环之外:

我们不需要实际拟合任何模型;我们可以通过对您的代码进行以下修改来模拟这种情况,这不会改变问题的本质:

import numpy as np
import pandas as pd

models = ['ran', 'knn', 'log', 'xgb', 'gbc', 'svc', 'ext', 'ada', 'gnb', 'gpc', 'bag']         
scores = []
cv=10

# Sequentially fit and cross validate all models
for mod in models:
    acc = np.array([np.random.rand() for i in range(cv)]) # simulate your accuracy here
scores.append(acc.mean()) # as in your code, i.e outside the for loop

# Create a dataframe of results
results = pd.DataFrame(
    'Model': ['Random Forest', 'K Nearest Neighbour', 'Logistic Regression', 'XGBoost', 'Gradient Boosting',  
    'SVC', 'Extra Trees', 'AdaBoost', 'Gaussian Naive Bayes', 'Gaussian Process', 'Bagging Classifier'],
    'Score': scores)

不出所料,这基本上复制了您的错误:

ValueError: arrays must all be same length

因为,正如在另一个答案中已经讨论过的,您的 scores 列表只有一个元素,即仅来自循环的 last 迭代的 acc.mean()

len(scores)
# 1
scores
# [0.47317491043203785]

因此 pandas 抱怨,因为它无法填充 11 行数据框...

for 循环内移动scores.append(),正如另一个答案中已经建议的那样,解决了这个问题:

for mod in models:
    acc = np.array([np.random.rand() for i in range(cv)])
    scores.append(acc.mean()) # moved inside the loop

# Create a dataframe of results
results = pd.DataFrame(
    'Model': ['Random Forest', 'K Nearest Neighbour', 'Logistic Regression', 'XGBoost', 'Gradient Boosting',  
    'SVC', 'Extra Trees', 'AdaBoost', 'Gaussian Naive Bayes', 'Gaussian Process', 'Bagging Classifier'],
    'Score': scores)
print(results)
# output:
                   Model     Score
0          Random Forest  0.492364
1    K Nearest Neighbour  0.624068
2    Logistic Regression  0.613653
3                XGBoost  0.536488
4      Gradient Boosting  0.484195
5                    SVC  0.381556
6            Extra Trees  0.274922
7               AdaBoost  0.509297
8   Gaussian Naive Bayes  0.362866
9       Gaussian Process  0.606538
10    Bagging Classifier  0.393950

您可能还需要记住,您的代码中不需要 model.fit() 部分 - cross_val_score 会自行完成所有必要的拟合...

【讨论】:

很好的解释。 @StanislavJirak 希望您了解您的代码有什么问题。

以上是关于如何有效地比较所有模型的准确性的主要内容,如果未能解决你的问题,请参考以下文章

如何比较不同的模型配置[关闭]

如何仅针对键的子集有效地比较 C++ 中的两个字符串映射

如何有效地比较同一类的两个对象并检查哪些是不同的字段?

如何有效地逐项比较两个大 XML 文件?

如何有效地比较列表并获得最频繁的对?

如何在处理负零时有效地比较两个浮点值的符号