使用Sklearn进行多标签文本分类

3
我已经尝试了所有我能想到的方法来解决我的Python多标签文本分类问题,真的很感激任何帮助。我已经基于这里使用multilabelbinarizer的结果,并参考了此网页
我正在尝试预测一组用西班牙语书写的数据集中的特定类别,其中有7个不同的标签,我的数据集在这里展示。我有一条书面信息和每行的不同标签。每个文本消息都有一个或两个标签,具体取决于消息。
df2=df.copy()
df2.drop(["mensaje", "pregunta_parseada", "tags_totales"], axis=1, inplace=True)

# Divide into train and test
X_train, X_test, y_train, y_test = train_test_split(df['pregunta_parseada'], 
                                                df2,
                                                test_size=0.15, 
                                                random_state=42)

from sklearn.feature_extraction.text import TfidfVectorizer, CountVectorizer

features_train = tfidf.fit_transform(X_train).toarray()
labels_train = y_train

features_test = tfidf.transform(X_test).toarray()
labels_test = y_test


from sklearn.linear_model import LogisticRegression
from sklearn.pipeline import Pipeline
from sklearn.metrics import accuracy_score
from sklearn.multiclass import OneVsRestClassifier


lr = LogisticRegression(solver='sag', n_jobs=1)
clf = OneVsRestClassifier(lr)

# fit model on train data
clf.fit(features_train, labels_train)

# make predictions for validation set
y_pred = clf.predict(features_test)

到目前为止,一切顺利,但是当我试图验证问题时,似乎几乎每个类别都被归类为 "无" 。
y_pred[2]
accuracy_score(y_test,y_pred)

输出

array([0, 0, 0, 0, 0, 0, 0])
0.2574626865671642

我也尝试了使用MultiLabelBinarizer,但遇到了同样的问题,我哪里出错了?尝试使用MultiLabelBinarizer会得到以下结果:

z=[["Generico"],["Mantenimiento"],["Motor"],["Generico"],["Motor"], 
["Generico"],["Motor"],["Generico","Configuracion"],["Generico"], 
["Motor"],["Consumo"],...,["Consumo"]]

from sklearn.preprocessing import MultiLabelBinarizer
mlb = MultiLabelBinarizer()
y=mlb.fit_transform(z)

message = df["pregunta_parseada"].to_numpy()
X_train, X_test, y_train, y_test = train_test_split(message, 
                                                y, 
                                                test_size=0.15, 
                                                random_state=42)
classifier = Pipeline([
('vectorizer', CountVectorizer()),
('tfidf', TfidfTransformer()),
('clf', OneVsRestClassifier(LinearSVC()))])

 classifier.fit(X_train, y_train)
 predicted = classifier.predict(X_test)
 accuracy_score(y_test, predicted)
 #predicted[150]
 all_labels = mlb.inverse_transform(predicted)
 all_labels

以下是输出结果

 (),
 (),
 (),
 (),
 ('Generico',),
 (),
 (),
 (),
 (),
 ('Compra',),
 ('Motor', 'extras'),

非常感谢您的帮助。

2
你确定你处于多标签设置中(一个样本可以同时属于多个类别),而不是单标签多类别设置中(一个样本只能属于一个类别)吗? - desertnaut
1
我刚刚编辑了我的消息,以展示我的问题是多标签分类。我将非常感激任何帮助。谢谢! - Isabel Kofoed Alonso
1个回答

1
我认为问题出在数据上,可能过于稀疏。
我看到你正在使用OneVsRestClassifier,所以它会构建多个二进制分类器来决定标签。
我认为,你的代码没有明显的错误,但是选择的模型对于这个任务来说不太合适。
这些二进制分类器的问题在于数据不平衡。即使每个类别中有相同数量的样本(n),二进制分类器也会将数据分成n vs (n-1) x c个正类和负类样本。
因此,所有分类器的负类数据都比正类数据更多。它们偏向于负类,结果每个二进制分类器倾向于预测(在oneVsall场景中全部预测)大多数情况。
如果你不想改变你的设置,那么你可以做的一件事是:
  1. 使用predict_proba而不是predict,以获取每个类别的概率,并设置一个较低的阈值(<0.5)来决定选择哪组类别。

你的测试准确率相当低,也许重新调整阈值可以获得更好的准确性。

  1. 如果可能的话,请使用基于深度学习的方法,如Bert,这将提供更好的性能。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接