"TypeError: Singleton array...cannot be considered a valid collection" и "ValueError: Found input ...inconsistent num...samples" в train_test_split
Не могу понять что является причиной ошибки на второй итерации в функции ниже:
# create empty pandas DF:
model_q = pd.DataFrame(columns=['model', 'set', 'threshold','set_size','tn','fp','fn','tp'])
# get seed
cv_seed = random.sample(range(1, 1000), 10)
def bootstraping_estimator(clf, model_name, X, y, cv_seed=cv_seed):
for i in cv_seed:
print(i)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.20, shuffle=True, random_state=i, stratify=y)
# StandartScaler
scaler.fit(X_train.values)
X_train = scaler.transform(X_train)
X_test = scaler.transform(X_test)
# compute TEST ############################################################
y_pred_test = clf.predict_proba(X_test)[:, 1]
fpr, tpr, ths = roc_curve(y_test, y_pred_test)
roc_auc = auc(fpr, tpr)
optimal_ths_idx = np.argmax(tpr - fpr)
optimal_ths = ths[optimal_ths_idx]
# round predicts ##########################################################
for y in y_pred_test:
y_pred_test_round = [1 if y >= 0.5 else 0 for y in y_pred_test]
y_pred_test_round_ths = [1 if y >= optimal_ths else 0 for y in y_pred_test]
# cm with default ths = 0.5 ##################################################
cm = confusion_matrix(y_test, y_pred_test_round)
cm_norm = cm.astype('float') / cm.sum() # normalize cm
tn, fp, fn, tp = cm.ravel() # compute estimetor answers
# cm with ths = optimal_ths
cm_ths = confusion_matrix(y_test, y_pred_test_round_ths)
cm_norm_ths = cm_ths.astype('float') / cm_ths.sum() # normalize cm
tn_ths, fp_ths, fn_ths, tp_ths = cm_ths.ravel()
fpr_ths, tpr_ths, _ = roc_curve(y_test, y_pred_test_round_ths) # ... for test with optimal_threshold
roc_auc_ths = auc(fpr_ths, tpr_ths)
# get global var and appned metrics
global model_q
model_q = model_q.append({'model': f'{model_name}_{i}',
'threshold': 0.5,
'set_size': len(y_test),
'tn': tn,'fp': fp, 'fn': fn, 'tp': tp,
'roc_auc': roc_auc},
ignore_index=True)
model_q = model_q.append({'model': f'{model_name}_{i}',
'threshold': optimal_ths,
'set_size': len(y_test),
'tn': tn_ths,'fp': fp_ths, 'fn': fn_ths, 'tp': tp_ths,
'roc_auc': roc_auc_ths},
ignore_index=True)
model_q['sensitivity'] = model_q.tp/(model_q.tp+model_q.fn)
model_q['specificity'] = model_q.tn/(model_q.tn+model_q.fp)
model_q['accuracy'] = (model_q.tp+model_q.tn)/(model_q.tp+model_q.tn+model_q.fn+model_q.fp)
model_q.iloc[:,1:] = model_q.iloc[:,1:].apply(pd.to_numeric)
model_q = model_q.round({'roc_auc':3,
'threshold':3,
'sensitivity':3,
'specificity':3,
'accuracy':3})
return (model_q.sort_values(by='accuracy', ascending=False)[:10].style.hide_index()\
.bar(color='#FFA07A', vmin=500, subset=['fp', 'fn'], align='zero')\
.bar(color='lightgreen', vmin=500, subset=['tp', 'tn'], align='zero')
.set_caption('Top-10 accuracy'))
Есть сохранение данных в переменную, второй train_test_split падает:
TypeError Traceback (most recent call last)
<ipython-input-22-bb1482942a86> in <module>
----> 1 bootstraping_estimator(clf_NB, 'NBGaussian', X, y)
<ipython-input-16-836a8d7da60e> in bootstraping_estimator(clf, model_name, X, y, cv_seed)
6 for i in cv_seed:
7 print(i)
----> 8 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.20, shuffle=True, random_state=i, stratify=y)
9
10 # StandartScaler
~\Anaconda3\lib\site-packages\sklearn\model_selection\_split.py in train_test_split(*arrays, **options)
2182 test_size = 0.25
2183
-> 2184 arrays = indexable(*arrays)
2185
2186 if shuffle is False:
~\Anaconda3\lib\site-packages\sklearn\utils\validation.py in indexable(*iterables)
258 else:
259 result.append(np.array(X))
--> 260 check_consistent_length(*result)
261 return result
262
~\Anaconda3\lib\site-packages\sklearn\utils\validation.py in check_consistent_length(*arrays)
229 """
230
--> 231 lengths = [_num_samples(X) for X in arrays if X is not None]
232 uniques = np.unique(lengths)
233 if len(uniques) > 1:
~\Anaconda3\lib\site-packages\sklearn\utils\validation.py in <listcomp>(.0)
229 """
230
--> 231 lengths = [_num_samples(X) for X in arrays if X is not None]
232 uniques = np.unique(lengths)
233 if len(uniques) > 1:
~\Anaconda3\lib\site-packages\sklearn\utils\validation.py in _num_samples(x)
140 if len(x.shape) == 0:
141 raise TypeError("Singleton array %r cannot be considered"
--> 142 " a valid collection." % x)
143 # Check that shape is returning an integer or default to len
144 # Dask dataframes may not return numeric shape[0] value
TypeError: Singleton array 6.80836481004117e-07 cannot be considered a valid collection.
Ответы (1 шт):
А, всё, я понял. Вы используете y как переменную цикла for y in y_pred_test:. А потом на второй итерации тот же y используете в train_test_split(X, y, ...). Типичная ошибка начинающего питониста - использовать одни и те же названия переменных для разных целей.
Ну и до кучи вы где-то потеряли clf.fit(X_train, y_train). Если б вы не использовали scaler я бы подумал, что так и задумано, но если вы скейлите X_test каждый раз заново, вам придётся заново обучать модель на X_train, иначе это вообще не пойми что будет в результате.
