我试图在scikit-learn中使用Pipeline\onevsrest分类器实现多标签分类。代码如下,但让我首先提一下,我从 pandas 数据帧构建了我的多标签示例。
代码如下:
df = pd.read_csv(fileIn, header = 0, encoding='utf-8-sig')
rows = random.sample(df.index, int(len(df) * 0.9))
work = df.ix[rows]
work_test = df.drop(rows)
X_train = []
y_train = []
X_test = []
y_test = []
for i in work[[i for i in list(work.columns.values) if i.startswith('Change')]].values:
X_train.append(','.join(i.T.tolist()))
X_train = np.array(X_train)
for i in work[[i for i in list(work.columns.values) if i.startswith('Corax')]].values:
y_train.append(list(i))
for i in work_test[[i for i in list(work_test.columns.values) if i.startswith('Change')]].values:
X_test.append(','.join(i.T.tolist()))
X_test = np.array(X_test)
for i in work_test[[i for i in list(work_test.columns.values) if i.startswith('Corax')]].values:
y_test.append(list(i))
lb = preprocessing.MultiLabelBinarizer()
Y = lb.fit_transform(y_train)
classifier = Pipeline([('vectorizer', CountVectorizer()),('tfidf', TfidfTransformer()),('clf', OneVsRestClassifier(SVC(kernel='rbf')))])
classifier.fit(X_train, Y)
predicted = classifier.predict(X_test)
但问题是,当你使用这组变换时:CountVectorizer -> TfidfTransformer
你会得到一个稀疏矩阵。问题是,当您尝试使用 OneVsRest 分类器预测标签时,它会查找decision_function
或predict_proba
方法。 predict_proba
在svm.SVC
上不可用,除非您指定probability=True
。另一方面,正如我在代码中看到的那样,decision_function
不是为稀疏矩阵实现的。因此,我的代码失败,因为这两个必需的方法都不可用。但也许我做错了什么?是否有可能在不指定probability=True?
的情况下以某种方式使用 svm.SVC
实现多标签分类(这样做会增加分类器训练的大量开销),也许是通过以某种方式强制 TfidfTransformer 输出密集矩阵而不是稀疏矩阵?
这是一个众所周知的问题,到目前为止还没有简单的解决方案。
您可以使用管道"致密化"稀疏数据(通过调用.toarray
),但这会增加内存消耗。您可以执行 TruncatedSVD(AFAIK,这是唯一适用于稀疏数据的降维方法),但它可能会弄乱您的数据,从而使 SVM 的性能下降。