【问题标题】:ValueError: The number of class labels must be greater than one in Passive Aggressive ClassifierValueError: Passive Aggressive Classifier 中类标签的数量必须大于 1
【发布时间】:2019-02-18 15:37:11
【问题描述】:

我正在尝试使用 scikit learn 中的“被动攻击分类器”和 20 个新闻组数据集来实现一个在线分类器。我对此很陌生,因此我不确定我是否正确实施了这一点。话虽如此,我开发了一个小代码,但是当我执行它时,我不断收到错误:

Traceback(最近一次调用最后一次):文件“/home/suleka/Documents/RNN models/passiveagressive.py”,第 100 行,在 clf.fit(X, y) 文件“/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 raise ValueError("类标签的数量必须是" ValueError: 类标签的数量必须大于一。

我检查了 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))

提前谢谢你!

【问题讨论】:

    标签: python-3.x machine-learning scikit-learn multiclass-classification tfidfvectorizer


    【解决方案1】:

    问题出在这一行:

    X, y = X_train[i:i + 1], y_train[i:i + 1]
    

    在您的 for 循环中,即 您要求 np.unique(labels) 并轻松地发现您确实拥有全部 20 个...

    仔细观察,您会发现这一行导致Xy只有一个元素(分别为X_train[i]y_train[i] - 事实上,因为错误可能发生在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 循环只是重新培训(至少它尝试)在每次迭代期间从头开始新的分类器。

    正如我已经说过的,从简单开始;尝试先牢牢掌握简单批量训练的原则,然后再转向更高级的在线训练主题,这绝对是不是初学者的......

    【讨论】:

    • 谢谢,我猜这可能是问题所在。但我试图将其与 RNN 在线训练模型进行比较,因此我想将其性能与机器学习算法进行比较。这就是我采用这种方法的原因。如果我一次输入整个数据集,它不会破坏它的整个目的吗?我在网上找不到任何合适的材料。
    • @Suleka_28 不客气;并且由于答案解决了问题所涉及的特定错误,请接受它 - 谢谢
    猜你喜欢
    • 2017-04-10
    • 2017-08-17
    • 2017-04-08
    • 2021-12-10
    • 2021-07-22
    • 2020-08-08
    • 2021-12-07
    • 2017-10-29
    • 1970-01-01
    相关资源
    最近更新 更多