我正在尝试使用scikit learn中的"被动攻击分类器"与20个新闻格罗普数据集实现在线分类器。我对此很陌生,因此我不确定我是否正确实现了它。话虽如此,我开发了一个 samll 代码,但当我执行它时,我不断收到错误:
回溯(最近一次调用(:文件 "/home/suleka/Documents/RNN 模型/被动侵略.py",第 100 行,在 clf.fit(X, y( File "/home/suleka/anaconda3/lib/python3.6/site-packages/sklearn/linear_model/passive_aggressive.py", 225 行,适合 coef_init=coef_init, intercept_init=intercept_init( 文件 "/home/suleka/anaconda3/lib/python3.6/site-packages/sklearn/linear_model/stochastic_gradient.py", 444路,_fit 类, sample_weight, coef_init, intercept_init( 文件 "/home/suleka/anaconda3/lib/python3.6/site-packages/sklearn/linear_model/stochastic_gradient.py", 407路,_partial_fit 引发 ValueError("类标签的数量必须为 " 值错误:类标签的数量必须大于 1。
我检查了stackoverflow中的大多数帖子,他们建议必须只有一个唯一的类。所以我做了np.unique(labels)
,它显示了 20(20 个新闻组(:
[ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19]
任何人都可以帮助我解决此错误,如果我实施错误,请告诉我。
我的代码如下所示:
from sklearn.linear_model import PassiveAggressiveClassifier
from sklearn.datasets import make_classification
from string import punctuation
import numpy as np
from sklearn.datasets import fetch_20newsgroups
from collections import Counter
from sklearn.preprocessing import MinMaxScaler, LabelBinarizer
from sklearn.utils import shuffle
from nltk.corpus import stopwords
from sklearn.feature_extraction.text import TfidfVectorizer
import nltk
nltk.download('stopwords')
seed = 42
np.random.seed(seed)
def preProcess():
newsgroups_data = fetch_20newsgroups(subset='all', remove=('headers', 'footers', 'quotes'))
vectorizer = TfidfVectorizer(sublinear_tf=True, max_df=0.5,
stop_words='english')
features = vectorizer.fit_transform(newsgroups_data.data)
labels= newsgroups_data.target
return features, labels
if __name__ == '__main__':
features, labels = preProcess()
X_train, y_train = shuffle(features, labels, random_state=seed)
clf = PassiveAggressiveClassifier(random_state=seed)
n, d =X_train.shape
print(np.unique(labels))
error = 0
iteration = 0
for i in range(n):
print(iteration)
X, y = X_train[i:i + 1], y_train[i:i + 1]
clf.fit(X, y)
pred = clf.predict(X)
print(pred)
print(y)
if y - pred != 0:
error += 1
iteration += iteration
print(error)
print(np.divide(error, n, dtype=np.float))
提前谢谢你!
问题出在这一行:
X, y = X_train[i:i + 1], y_train[i:i + 1]
在您的for
循环中,即在您要求np.unique(labels)
并舒适地发现您确实拥有所有 20 个之后......
仔细观察,你会发现这条线的结果是每个元素只有一个元素(分别为X_train[i]
和y_train[i]
(的X
和y
- 事实上,由于错误可以说发生在i=0
的第一次迭代中,你最终只得到X_train[0]
和y_train[0]
(,这当然不应该是拟合模型时的情况; 因此, 错误消息正确地指出您的集合中只有一个标签(因为您只有一个样本,也就是说(...
要说服自己确实如此,只需在clf.fit()
之前插入一个print(np.unique(y))
- 它只会打印一个标签。
目前还不清楚你到底想用你的for
循环实现什么;如果你试图训练你的分类器到数据集的连续片段,你可以尝试将[i:i+1]
索引更改为[i:i+k]
一些足够大的k
,但对于 20 个标签的数据集来说,这不是那么简单, 因为您必须确保每次调用clf.fit()
时都会存在所有20 个标签,否则您最终会将苹果与橙子进行比较......
我强烈建议从简单开始:删除for
循环,将分类器适合整个训练集(clf.fit(X_train, y_train)
(,并查看scikit-learn的文档以获取您可以使用的可用性能指标...
编辑我刚刚注意到细节:
我正在尝试实现一个在线分类器
好吧,您尝试做的当然不是在线训练(这本身就是一个巨大的话题(,因为您的for
循环只是在每次迭代期间从头开始重新训练(它至少尝试(一个新的分类器。
正如我已经说过的,从简单开始;首先尝试牢牢掌握简单批量训练的原则,然后再转向更高级的在线培训主题,这绝对不是初学者的......