在令牌级别使用sklearn的多类分类[关闭]

问题描述 投票:0回答:1

我正在尝试使用scikit-learn在令牌级别对数据进行分类。我已经有一个traintest拆分。数据采用以下\t分隔格式:

-----------------
token       label
-----------------
way          6
to           6
reduce       6
the          6
amount       6
of           6
traffic      6
   ....
public       2
transport    5
is           5
a            5
key          5
factor       5
to           5 
minimize     5
   ....

数据分布如下:

                              Training Data                    Test Data
# Total:                        119490                          29699
# Class 0:                      52631                           13490
# Class 1:                      35116                           8625
# Class 2:                      17968                           4161
# Class 3:                      8658                            2088
# Class 4:                      3002                            800
# Class 5:                      1201                            302
# Class 6:                      592                             153

我正在尝试SVM,但F1-score相当糟糕。

代码是:

import pandas as pd
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.pipeline import Pipeline
from sklearn.feature_extraction.text import TfidfTransformer
from sklearn.linear_model import SGDClassifier
from sklearn.metrics import accuracy_score, f1_score
from sklearn.model_selection import KFold

if __name__ == '__main__':
    # reading Files
    train_df = pd.read_csv(TRAINING_DATA_PATH, names=['token', 'label'], sep='\t')
    test_df = pd.read_csv(TEST_DATA_PATH, names=['token', 'label'], sep='\t')

    # getting training and testing data
    train_X = train_df['token'].astype('U')
    test_X = test_df['token'].astype('U')
    train_y = train_df['label']
    test_y = test_df['label']

    # Linear SVM
    sgd = Pipeline([('vect', CountVectorizer()),        
                    ('tfidf', TfidfTransformer()),      
                    ('clf',   SGDClassifier(loss='hinge', penalty='l2', alpha=1e-3, max_iter=100, tol=None)
                   ])
    f1_list = []
    acc_list = []
    cv = KFold(n_splits=5)
    for train_index, test_index in cv.split(train_X):
        X_train, X_val = train_X[train_index], train_X[test_index]
        y_train, y_val = train_y[train_index], train_y[test_index]
        sgd.fit(X_train, y_train)
        predicted = sgd.predict(X_val)
        f1 = f1_score(y_val, predicted, average='macro')
        acc = accuracy_score(y_val, predicted)
        f1_list.append(f1)
        acc_list.append(acc)
    print(f1_list)
    print(acc_list)
    sgd_pred = sgd.predict(test_X)
    print('SVM accuracy: %s' % accuracy_score(sgd_pred, test_y))
    print('SVM F1-macro: %s' % f1_score(sgd_pred, test_y, average='macro'))
    print('SVM F1-weighted: %s' % f1_score(sgd_pred, test_y, average='weighted'))

线性SVM的结果如下:

SVM accuracy: 0.49493248930940437
SVM F1-macro: 0.2677988484198396

如何提高性能?

python machine-learning scikit-learn svm cross-validation
1个回答
0
投票

主要原因是,您的数据集似乎非常不平衡,并且您可能会注意到,准确性分数f1分数(宏观)之间的差异非常高,这是一个指标对于某些类的missclassifcation。另外,我猜您的数据可能是[[nonlinearly可分离的,linear-SVM找不到合适的分隔线。

只需注意这一点,但您的问题仍然存在

不平衡

数据集。
您可以尝试以下方法。

  1. 使用

    班级体重

  • 如果您的特征遵循

    多项式

  • 分布,则可以尝试补数朴素贝叶斯带有或不带有班级重量。
  • 您可以在sklearn中尝试

    nonlinear-SVM

  • ,通常可以使用SVC,但是您可能需要一段时间才能使模型适合您的训练集,在这种情况下,您可以尝试使用GPU进行优化的ThunderSVM
  • 尝试一些

    无监督

  • 学习算法
  • 重复一些不平衡的类,

    随机地

  • 选择样本(较差]方法,但有时效果很好)针对您的问题,我建议仅使用

    f1分数

    (宏)作为评估指标,因为在数据集不平衡的情况下,使用准确度分数可以非常好地评估模型的[差]执行并使用both可能会引起一些混乱。
    © www.soinside.com 2019 - 2024. All rights reserved.