Tôi đang kiểm tra các trình phân loại khác nhau trên một tập dữ liệu có 5 lớp và mỗi trường hợp có thể thuộc về một hoặc nhiều lớp trong số đó, vì vậy, tôi đang sử dụng các trình phân loại đa nhãn của scikit-learn, cụ thể sklearn.multiclass.OneVsRestClassifier
. Bây giờ tôi muốn thực hiện xác nhận chéo bằng cách sử dụng sklearn.cross_validation.StratifiedKFold
. Điều này tạo ra lỗi sau:
Traceback (most recent call last):
File "mlfromcsv.py", line 93, in <module>
main()
File "mlfromcsv.py", line 77, in main
test_classifier_multilabel(svm.LinearSVC(), X, Y, 'Linear Support Vector Machine')
File "mlfromcsv.py", line 44, in test_classifier_multilabel
scores = cross_validation.cross_val_score(clf_ml, X, Y_list, cv=cv, score_func=metrics.precision_recall_fscore_support, n_jobs=jobs)
File "/usr/lib/pymodules/python2.7/sklearn/cross_validation.py", line 1046, in cross_val_score
X, y = check_arrays(X, y, sparse_format='csr')
File "/usr/lib/pymodules/python2.7/sklearn/utils/validation.py", line 144, in check_arrays
size, n_samples))
ValueError: Found array with dim 5. Expected 98816
Lưu ý rằng đào tạo trình phân loại đa nhãn không bị sập, nhưng xác thực chéo thì có. Làm cách nào để thực hiện xác thực chéo cho trình phân loại nhiều nhãn này?
Tôi cũng đã viết một phiên bản thứ hai phân tích vấn đề thành đào tạo và xác nhận hợp lệ 5 phân loại riêng biệt. Điều này chỉ hoạt động tốt.
Đây là mã của tôi. Các chức năng test_classifier_multilabel
là một trong những vấn đề. test_classifier
là nỗ lực khác của tôi (chia vấn đề thành 5 phân loại và 5 xác nhận chéo).
import numpy as np
from sklearn import *
from sklearn.multiclass import OneVsRestClassifier
from sklearn.neighbors import KNeighborsClassifier
import time
def test_classifier(clf, X, Y, description, jobs=1):
print '=== Testing classifier {0} ==='.format(description)
for class_idx in xrange(Y.shape[1]):
print ' > Cross-validating for class {:d}'.format(class_idx)
n_samples = X.shape[0]
cv = cross_validation.StratifiedKFold(Y[:,class_idx], 3)
t_start = time.clock()
scores = cross_validation.cross_val_score(clf, X, Y[:,class_idx], cv=cv, score_func=metrics.precision_recall_fscore_support, n_jobs=jobs)
t_end = time.clock();
print 'Cross validation time: {:0.3f}s.'.format(t_end-t_start)
str_tbl_fmt = '{:>15s}{:>15s}{:>15s}{:>15s}{:>15s}'
str_tbl_entry_fmt = '{:0.2f} +/- {:0.2f}'
print str_tbl_fmt.format('', 'Precision', 'Recall', 'F1 score', 'Support')
for (score_class, lbl) in [(0, 'Negative'), (1, 'Positive')]:
mean_precision = scores[:,0,score_class].mean()
std_precision = scores[:,0,score_class].std()
mean_recall = scores[:,1,score_class].mean()
std_recall = scores[:,1,score_class].std()
mean_f1_score = scores[:,2,score_class].mean()
std_f1_score = scores[:,2,score_class].std()
support = scores[:,3,score_class].mean()
print str_tbl_fmt.format(
lbl,
str_tbl_entry_fmt.format(mean_precision, std_precision),
str_tbl_entry_fmt.format(mean_recall, std_recall),
str_tbl_entry_fmt.format(mean_f1_score, std_f1_score),
'{:0.2f}'.format(support))
def test_classifier_multilabel(clf, X, Y, description, jobs=1):
print '=== Testing multi-label classifier {0} ==='.format(description)
n_samples = X.shape[0]
Y_list = [value for value in Y.T]
print 'Y_list[0].shape:', Y_list[0].shape, 'len(Y_list):', len(Y_list)
cv = cross_validation.StratifiedKFold(Y_list, 3)
clf_ml = OneVsRestClassifier(clf)
accuracy = (clf_ml.fit(X, Y).predict(X) != Y).sum()
print 'Accuracy: {:0.2f}'.format(accuracy)
scores = cross_validation.cross_val_score(clf_ml, X, Y_list, cv=cv, score_func=metrics.precision_recall_fscore_support, n_jobs=jobs)
str_tbl_fmt = '{:>15s}{:>15s}{:>15s}{:>15s}{:>15s}'
str_tbl_entry_fmt = '{:0.2f} +/- {:0.2f}'
print str_tbl_fmt.format('', 'Precision', 'Recall', 'F1 score', 'Support')
for (score_class, lbl) in [(0, 'Negative'), (1, 'Positive')]:
mean_precision = scores[:,0,score_class].mean()
std_precision = scores[:,0,score_class].std()
mean_recall = scores[:,1,score_class].mean()
std_recall = scores[:,1,score_class].std()
mean_f1_score = scores[:,2,score_class].mean()
std_f1_score = scores[:,2,score_class].std()
support = scores[:,3,score_class].mean()
print str_tbl_fmt.format(
lbl,
str_tbl_entry_fmt.format(mean_precision, std_precision),
str_tbl_entry_fmt.format(mean_recall, std_recall),
str_tbl_entry_fmt.format(mean_f1_score, std_f1_score),
'{:0.2f}'.format(support))
def main():
nfeatures = 13
nclasses = 5
ncolumns = nfeatures + nclasses
data = np.loadtxt('./feature_db.csv', delimiter=',', usecols=range(ncolumns))
print data, data.shape
X = np.hstack((data[:,0:3], data[:,(nfeatures-1):nfeatures]))
print 'X.shape:', X.shape
Y = data[:,nfeatures:ncolumns]
print 'Y.shape:', Y.shape
test_classifier(svm.LinearSVC(), X, Y, 'Linear Support Vector Machine', jobs=-1)
test_classifier_multilabel(svm.LinearSVC(), X, Y, 'Linear Support Vector Machine')
if __name__ =='__main__':
main()
Tôi đang sử dụng Ubuntu 13.04 và scikit-learn 0.12. Dữ liệu của tôi ở dạng hai mảng (X và Y) có hình dạng (98816, 4) và (98816, 5), tức là 4 tính năng cho mỗi phiên bản và 5 nhãn lớp. Các nhãn là 1 hoặc 0 cho thành viên được chỉ định trong lớp đó. Tôi có đang sử dụng định dạng đúng vì tôi không thấy nhiều tài liệu về điều đó?
OneVsRestClassifier
chấp nhận một mảng 2D (ví dụ nhưy
trong mã ví dụ của bạn) hoặc một bộ danh sách các nhãn lớp không? Tôi hỏi bởi vì tôi đã xem ví dụ phân loại đa nhãn trên scikit-learn vừa rồi và thấy rằngmake_multilabel_classification
hàm trả về một danh sách các danh sách nhãn lớp, ví dụ như([2], [0], [0, 2], [0]...)
khi sử dụng 3 lớp?