首页 文章

使用NLTK,scikit-learn和OneVsRestClassifier打开多标签分类

提问于
浏览
2

免责声明:我是AI,Python,NLTK和scikit-learn的新手 .

我正在尝试训练分类器,将一组文档分类为一组标签 .

我正在使用NLTK包装器与scikit-learn的OneVsRestClassifier交谈 .

training_set = [
    [{"car": True, ...}, "Label 1"],
    [{"car": False, ...}, "Label 2"],
    ...
    [{"car": False, ...}, "Label 1"],
]

ovr = SklearnClassifier(OneVsRestClassifier(MultinomialNB()))
ovr.train(training_set)

这适用于多类分类,其中分类器尝试仅将文档分类为标签 . 准确性很好,但我希望分类器为文档分配0,1个或更多标签 . 我怎样才能做到这一点?

遗憾的是,我不能只是初始化分类器,告诉它是一个多标签分类器,documentation说:

该策略也可用于多标记学习,其中分类器用于预测多个标签,例如,通过拟合2-d矩阵,其中如果样本i具有标记j则单元[i,j]为1,否则为0 .

这对我来说并不是很清楚,因为我不熟悉这种语言 . 我觉得我必须以这样的方式塑造我的训练集,以便分类器能够理解我希望它能够对我的数据进行多标签分类吗?如果有,怎么样?

我试图在数组中提供标签,如下所示:

training_set = [
    [{"car": True, ...}, ["Label 1"]],
    [{"car": False, ...}, ["Label 2"]],
    ...
    [{"car": False, ...}, ["Label 1"]],
]

这没有按预期工作并提出:

DataConversionWarning: A column-vector y was passed when a 1d array was expected. Please change the shape of y to (n_samples, ), for example using ravel().
  y = column_or_1d(y, warn=True)
One-vs-rest accuracy percent: 0.0

2 回答

  • 2

    试图说明的是,使用2-D矩阵作为目标 . 基本上,你的训练集可以是,

    training_set = [
        [{"car": True, ...}, [is_label_1, is_label_2, is_label_3]],
        [{"car": False, ...}, [is_label_1, is_label_2, is_label_3]],
        ...
        [{"car": False, ...}, [is_label_1, is_label_2, is_label_3]],
    ]
    

    对于特定样本,使用多个标签对其进行训练,例如:对于第一个样品,如果存在标签1和标签3,则将其作为[1,0,1]传递 .

    希望,答案很清楚 .

  • 2

    我通过将NLTK移除到scikit-learn适配器并导入NLTK模块以帮助我将我的数据结构转换为可供应给scikit-learn OneVsRestClassifier的东西来解决这个问题 .

    from nltk import compat
    from sklearn.feature_extraction import DictVectorizer
    from sklearn.naive_bayes import MultinomialNB
    from sklearn.multiclass import OneVsRestClassifier
    
    _vectorizer = DictVectorizer(dtype=float, sparse=True)
    
    def prepare_scikit_x_and_y(labeled_featuresets):
        X, y = list(compat.izip(*labeled_featuresets))
        X = _vectorizer.fit_transform(X)
    
        set_of_labels = []
        for label in y:
            set_of_labels.append(set(label))
    
        y = self.mlb.fit_transform(set_of_labels)
    
        return X, y
    
    def train_classifier(labeled_featuresets):
        X, y = prepare_scikit_x_and_y(labeled_featuresets)
        classifier.fit(X, y)
    
    training_set = [
        [{"car": True, ...}, ["Label 1"]],
        [{"car": False, ...}, ["Label 2"]],
        ...
        [{"car": False, ...}, ["Label 1"]],
    ]
    
    
    ovr = OneVsRestClassifier(MultinomialNB())
    ovr.train(training_set)
    

    快乐的 beans 子

相关问题