如何在python中修复“IndexError:元组索引超出范围”?

Posted

技术标签:

【中文标题】如何在python中修复“IndexError:元组索引超出范围”?【英文标题】:How to fix "IndexError: tuple index out of range" in python? 【发布时间】:2019-11-25 09:48:44 【问题描述】:

我正在使用sklearn 模块来寻找最佳拟合模型和模型参数。但是,我在下面遇到了意外的索引错误:

> IndexError                                Traceback (most recent call
> last) <ipython-input-38-ea3f99e30226> in <module>
>      22             s = mean_squared_error(y[ts], best_m.predict(X[ts]))
>      23             cv[i].append(s)
> ---> 24     print(np.mean(cv, 1))
> IndexError: tuple index out of range

我想做的是找到最合适的回归器及其参数,但我得到了上述错误。我查看了SO 并尝试了this solution,但仍然出现同样的错误。任何想法来修复这个错误?谁能指出我为什么会发生这个错误?有什么想法吗?

我的代码

from sklearn.model_selection import KFold
from sklearn.metrics import mean_squared_error
from sklearn.linear_model import LinearRegression, Ridge, Lasso
from xgboost.sklearn import XGBRegressor

from sklearn.datasets import make_regression

models = [SVR(), RandomForestRegressor(), LinearRegression(), Ridge(), Lasso(), XGBRegressor()]
params = ['C': [0.01, 1], 'n_estimators': [10, 20]]

X, y = make_regression(n_samples=10000, n_features=20)

with warnings.catch_warnings():
    warnings.filterwarnings("ignore")
    cv = [[] for _ in range(len(models))]
    fold = KFold(5,shuffle=False)
    for tr, ts in fold.split(X):
        for i, (model, param) in enumerate(zip(models, params)):
            best_m = GridSearchCV(model, param)
            best_m.fit(X[tr], y[tr])
            s = mean_squared_error(y[ts], best_m.predict(X[ts]))
            cv[i].append(s)
    print(np.mean(cv, 1))

想要的输出

如果有办法解决上述错误,我希望能挑选出带有参数的最佳拟合模型,然后将其用于估计。有什么想法可以改进上述尝试吗?谢谢

【问题讨论】:

@desertnaut 你认为我该如何优化这段代码?有更好的主意吗? 这是一个非常笼统的问题,但是在 每个 中的 5 个折叠之一中进行网格搜索听起来有点矫枉过正。我建议您打开另一个问题寻求建议(确保您的代码完全可重现,包括所有相关的导入)。 这个错误可以用np.mean([],1)复现,支持cv[]的想法,或者包含[]列表。 【参考方案1】:

当你定义时

cv = [[] for _ in range(len(models))]

每个模型都有一个空列表。 但是,在循环中,您会遍历只有 两个 元素的 enumerate(zip(models, params)),因为您的 params 列表有两个元素(因为 list(zip(x,y)) has length 等于 min(len(x),len(y))。

因此,您会得到一个 IndexError,因为当您使用 np.mean 计算平均值时,cv 中的一些列表是空的(除了前两个)。

解决方案: 如果您不需要在其余模型上使用 GridSearchCV,您可以使用空字典扩展 params 列表:

params = ['C': [0.01, 1], 'n_estimators': [10, 20], , , , ]

【讨论】:

我认为这不是这个问题的答案。请阅读SO社区规则。 @Dan 由于您尚未发布 MWE,我无法确定这是解决方案,但在导入适当的模块后它可以与您的代码一起使用,并且它与您提供的输出相匹配cv 的 cmets(有关您必须对 params 进行的具体更改,请参阅最后的编辑)。 这确实是正确的答案(赞成) - 无法理解反对票;我继续更详细地解释......【参考方案2】:

您的问题的根本原因是,当您要求评估 GridSearchCV 中的 6 个模型时,您只提供了前 2 个模型的参数:

models = [SVR(), RandomForestRegressor(), LinearRegression(), Ridge(), Lasso(), XGBRegressor()]
params = ['C': [0.01, 1], 'n_estimators': [10, 20]]

enumerate(zip(models, params)) 在此设置中的结果,即:

for i, (model, param) in enumerate(zip(models, params)):
    print((model, param))

(SVR(C=1.0, cache_size=200, coef0=0.0, degree=3, epsilon=0.1, gamma='auto',
  kernel='rbf', max_iter=-1, shrinking=True, tol=0.001, verbose=False), 'C': [0.01, 1])
(RandomForestRegressor(bootstrap=True, criterion='mse', max_depth=None,
           max_features='auto', max_leaf_nodes=None,
           min_impurity_decrease=0.0, min_impurity_split=None,
           min_samples_leaf=1, min_samples_split=2,
           min_weight_fraction_leaf=0.0, n_estimators=10, n_jobs=1,
           oob_score=False, random_state=None, verbose=0, warm_start=False), 'n_estimators': [10, 20])

即最后 4 个模型被简单地忽略,因此您在 cv 中获得它们的空条目:

print(cv)
# result:
[[5950.6018771284835, 5987.293514740653, 6055.368320208183, 6099.316091619069, 6146.478702335218], [3625.3243553665975, 3301.3552182952058, 3404.3321983193728, 3521.5160621260898, 3561.254684271113], [], [], [], []]

这会在尝试获取 np.mean(cv, 1) 时导致下游错误。

正如 Psi 在他们的回答中已经正确指出的那样,解决方案是在您实际上执行任何 CV 搜索的模型中查找空字典;省略XGBRegressor(尚未安装),结果如下:

models = [SVR(), RandomForestRegressor(), LinearRegression(), Ridge(), Lasso()]
params2 = ['C': [0.01, 1], 'n_estimators': [10, 20], , , ]

cv = [[] for _ in range(len(models))]
fold = KFold(5,shuffle=False)
for tr, ts in fold.split(X):
    for i, (model, param) in enumerate(zip(models, params2)):
        best_m = GridSearchCV(model, param)
        best_m.fit(X[tr], y[tr])
        s = mean_squared_error(y[ts], best_m.predict(X[ts]))
        cv[i].append(s)

print(cv) 给出:

[[4048.660483326826, 3973.984055352062, 3847.7215568088545, 3907.0566348092684, 3820.0517432992765], [1037.9378737329769, 1025.237441119364, 1016.549294695313, 993.7083268195154, 963.8115632611381], [2.2948917095935095e-26, 1.971022007799432e-26, 4.1583774042712844e-26, 2.0229469068846665e-25, 1.9295075684919642e-26], [0.0003350178681602639, 0.0003297411022124562, 0.00030834076832371557, 0.0003355298330301431, 0.00032049282437794516], [10.372789356303688, 10.137748082073076, 10.136028304131141, 10.499159069700834, 9.80779910439471]]

print(np.mean(cv, 1)) 工作正常,给:

[3.91949489e+03 1.00744890e+03 6.11665355e-26 3.25824479e-04
 1.01907048e+01]

因此,在您的情况下,您确实应该将params 更改为:

params = ['C': [0.01, 1], 'n_estimators': [10, 20], , , , ]

正如 Psi 已经建议的那样。

【讨论】:

以上是关于如何在python中修复“IndexError:元组索引超出范围”?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用python修复在bigquery中上传csv文件

如何修复我的 python 安装?

如何在 Python 中修复“<string> DeprecationWarning: invalid escape sequence”?

如何在 Python 中进行 POST 时修复 <Response [400]>?

如何在Python中修复“DeprecationWarning:无效的转义序列”?

如何修复python中graphql查询中的“解析错误(VAR_SIGN)”