【问题标题】:ValueError: need at least one array to concatenate with sklearn cross_val_predict methodValueError:需要至少一个数组与 sklearn cross_val_predict 方法连接
【发布时间】:2020-12-22 01:58:14
【问题描述】:

我正在尝试使用 SVM 分类器使用自定义交叉验证折叠对二元分类问题进行建模,但它给了我错误 **need at least one array to concatenate ** 与 cross_val_predict。该代码在 cros_val_predict 中使用 cv=3 时可以正常工作,但是当我使用 custom_cv 时,它会出现此错误。

下面是代码:


from sklearn.model_selection import LeavePOut
import numpy as np
from sklearn.svm import SVC
from time import *
from sklearn.metrics import roc_auc_score
from sklearn.model_selection import cross_val_predict,cross_val_score
clf = SVC(kernel='linear',C=25)
X = np.array([[1, 2], [3, 4], [5, 6], [7, 8],[9,10]])
y = np.array([0,1,1,0,0])
lpo = LeavePOut(2)
print(lpo.get_n_splits(X))
LeavePOut(p=2)
test_index_list=[]
train_index_list=[]
for train_index, test_index in lpo.split(X,y):
  
  if(y[test_index[0]]==y[test_index[1]]):
    pass
  else:
    print("TRAIN:", train_index, "TEST:", test_index)
    X_train, X_test = X[train_index], X[test_index]
    y_train, y_test = y[train_index], y[test_index]
    train_index_list.append(train_index)
    test_index_list.append(test_index)
custom_cv = zip(train_index_list, test_index_list)
scores = cross_val_score(clf, X, y, cv=custom_cv)

print(scores)
print('accuracy:',scores.mean())
predicted=cross_val_predict(clf,X,y,cv=custom_cv) # error with this line
print('Confusion matrix:',confusion_matrix(labels, predicted))

以下是错误的完整跟踪:

ValueError                                Traceback (most recent call last)
<ipython-input-11-d78feac932b2> in <module>()
     31 print(scores)
     32 print('accuracy:',scores.mean())
---> 33 predicted=cross_val_predict(clf,X,y,cv=custom_cv)
     34 
     35 print('Confusion matrix:',confusion_matrix(labels, predicted))

/usr/local/lib/python3.6/dist-packages/sklearn/model_selection/_validation.py in cross_val_predict(estimator, X, y, groups, cv, n_jobs, verbose, fit_params, pre_dispatch, method)
    758     predictions = [pred_block_i for pred_block_i, _ in prediction_blocks]
    759     test_indices = np.concatenate([indices_i
--> 760                                    for _, indices_i in prediction_blocks])
    761 
    762     if not _check_is_permutation(test_indices, _num_samples(X)):

<__array_function__ internals> in concatenate(*args, **kwargs)

ValueError: need at least one array to concatenate

关于如何解决这个错误有什么建议吗?

【问题讨论】:

  • np.concatenate 的列表数组是空的。我必须更多地查看sklearn 代码以了解prediction_blockscross_val_predict 的输入之间的关系。但是您应该检查该函数的输入形状,特别是Xy。换句话说,将您的输入与函数文档进行比较。
  • 它的主要问题是自定义交叉验证折叠与 cross_val_score 配合得很好。如果我将 cv=cumtom_cv 更改为简单的交叉验证拆分,例如 3,这将成功运行。但我真的需要使用这组训练和测试索引。
  • 等一下!你让这个与一个值一起工作,而它与另一个值一起失败?你为什么一开始不提供这些细节。如果您真的需要帮助,请不要吝啬相关信息。如果没有此代码的经验,我倾向于关注x, y 等,但似乎cv 参数是真正的问题。我不给它一个zip() 是否可以,或者它是否应该是list(zip(...))) 或其他。
  • 是的,你是对的。将编辑问题。我只想在 train_index_list 中使用带有索引的样本来训练并忽略 test_index_list 中带有索引的样本,这些样本将在预测时使用。所以没有必要使用 zip()。

标签: python numpy scikit-learn cross-validation


【解决方案1】:

这里有2个错误:

  1. 如果您想重用zip 对象,请从中创建一个列表。该对象在您使用一次后会耗尽。你可以这样修复它:
custom_cv = [*zip(train_index_list, test_index_list)]
  1. cross_val_predict 的交叉验证列表应该是实际数组的分区 (Each sample should only belong to exactly one test set)。在你的情况下,它不是。如果您考虑一下,从交叉验证列表中堆叠输出将导致长度为 6 数组,而原始 y 的长度为 5。您可以像这样实现自定义交叉验证预测:
def custom_cross_val_predict(clf, X, y, cv):
    y_pred, y_true = [], []
    for tr_idx, vl_idx in cv:
        X_tr, y_tr = X[tr_idx], y[tr_idx]
        X_vl, y_vl = X[vl_idx], y[vl_idx]
        clf.fit(X_tr, y_tr)
        y_true.extend(y_vl)
        y_pred.extend(clf.predict(X_vl))
        
    return y_true, y_pred

labels, predicted = custom_cross_val_predict(clf,X,y,cv=custom_cv)
print('Confusion matrix:',confusion_matrix(labels, predicted))

【讨论】:

  • 你是对的,使用这个逻辑,交叉验证列表是重复 X 的样本。这样,混淆矩阵代表的结果不仅仅是样本。任何可能的方法来执行离开对交叉验证?对于交叉验证的每个拆分,从两个标签组 (0,1) 中获取一对?
  • @Aizayousaf 我建议您为这个新问题创建另一个问题,因为您在这里的问题已经得到解答。
猜你喜欢
  • 2019-07-24
  • 2021-04-23
  • 2016-06-01
  • 2020-04-11
  • 2023-02-10
  • 2021-08-07
  • 1970-01-01
  • 2022-12-18
  • 1970-01-01
相关资源
最近更新 更多