数据不平衡导致多类数据集分类错误


9

我正在研究文本分类,这里有39个类别/类和850万条记录。(未来的数据和类别将会增加)。

我的数据的结构或格式如下。

----------------------------------------------------------------------------------------
| product_title          | Key_value_pairs                               | taxonomy_id |
----------------------------------------------------------------------------------------
  Samsung S7 Edge        | Color:black,Display Size:5.5 inch,Internal    | 211 
                          Storage:128 GB, RAM:4 GB,Primary Camera:12 MP  

  Case cover Honor 8     | Color:transparent,Height:15 mm,width:22 mm    | 212 

  Ruggers Men's T-Shirt  | Size:L,ideal for:men,fit:regular,             | 111
                          sleeve:half sleeve

  Optimum Nutrition Gold | Flavor:chocolate,form:powder,size:34 gm       | 311
  Standard Whey Protein  

数据分发不正常;它是高度不平衡的:

-------------------------
| taxonomy_id |   count |
-------------------------
          111 |  851750 
          112 |  355592
          113 |  379433
          114 |   23138
          115 |  117735
          116 |  145757
          117 | 1339471
          121 |  394026
          122 |  193433
          123 |   78299
          124 |  111962
          131 |    1776
          132 |    4425
          133 |     908
          134 |   23062
          141 |   22713
          142 |   42073
          211 |    7892
          212 | 1574744
          221 |    1047
          222 |  397515
          223 |   53009
          231 |    1227
          232 |    7683
          251 |     739
          252 |     327
          253 |   38974
          254 |      25
          311 |    2901
          321 |    7126
          412 |     856
          421 |  697802
          422 |  414855
          423 |   17750
          425 |    1240
          427 |     658
          429 |    1058
          431 |   20760
          441 |     257       

如您所见,它们高度不平衡,导致分类错误。

到现在为止我执行的步骤

1)合并product_title和key_value_pairs列,并删除停用词和特殊字符并执行词干。

2)我已经将管道用于TFIDFvectorizer(),LinearSVC()

vectorizerPipe = Pipeline([
                 ('tfidf', TfidfVectorizer(lowercase=True, stop_words='english')),
                 ('classification', OneVsRestClassifier(LinearSVC(penalty='l2', loss='hinge'))),
                 ])

在此之后,我已经适应管道并将分类器存储在pickle中

prd = vectorizerPipe.fit(df.loc[:, 'description'], df.loc[:, 'taxonomy_id'])

在测试方面,我如上所述重复了步骤1,然后加载了泡菜并使用了预测功能

pd = cl.predict([testData])

我面临的问题

  1. 许多产品被误分类为其他类别

    示例:Ultimate Nutrition Prostar 100%乳清蛋白应分类为311类,但我的分类器将其分类为222,这是完全错误的。

  2. 我不确定是否要使用TFidfVectorizer()或Hashingvectorizer(),你们可以帮助我选择其中之一及其参数吗?

  3. 我使用的算法是LinearSVC,它是处理海量数据的多类分类问题的理想选择吗?还是应该使用其他算法?

  4. 由于数据高度不平衡,因此我尝试了随机欠采样。结果有所改善,但仍达不到要求。我也不确定这是否是执行随机欠采样的正确方法:

    pipe = make_pipeline_imb(
        HashingVectorizer(lowercase=True),
        RandomUnderSampler(ratio={111: 405805, 112: 170431, 113: 241709, 114: 8341, 115: 50328, 116: 89445, 117: 650020, 121: 320803, 122: 162557, 123: 66156, 124: 36276, 131: 1196, 132: 3365, 133: 818, 134: 15001, 141: 6145, 142: 31783, 211: 24728, 212: 100000, 221: 791, 222: 8000, 223: 35406, 231: 785, 232: 3000, 251: 477, 252: 127, 253: 29563, 254: 33, 311: 2072, 321: 5370, 412: 652, 421: 520973, 422: 99171, 423: 16786, 425: 730, 427: 198, 429: 1249, 431: 13793, 441: 160},random_state=1), 
        OneVsRestClassifier(LinearSVC(penalty='l2', loss='hinge')))
  5. 我是机器学习的新手,因此我已使用这种方法进行文本分类。如果我的方法不对,请以正确的一种纠正我。

(如果您通过示例提出建议或解决方案,那将是很棒的,因为它可以帮助我更好地理解)。

***编辑-1 ****

RndmFrst = RandomForestClassifier(n_estimators=100, max_depth=20, max_features=5000,n_jobs=-1)
LogReg = LogisticRegression()
voting = VotingClassifier(estimators=[('LogReg ', LogReg), ('RndmFrst', RndmFrst)], voting='soft', n_jobs=-1)

pipe = Pipeline([('tfidf', TfidfVectorizer(ngram_range=(1,4), max_features=50000)), ('clf', voting)])

pipe = pipe.fit(df.loc[:,'description'], df.loc[:,'taxonomy_id'])
Preds = pipe.predict(test_data)

我只是看到您尝试了欠采样。只是,Sci-Kit Learn中的Startized K-fold交叉验证也考虑了类分配。
Kasra Manshaei

Answers:


6

好问题!

一些备注

对于不平衡的数据,您可以使用不同的方法。最完善的方法是重新采样(对小类进行过度采样/对大类进行欠采样)。另一个是使您的分类成为分层,即将大型类别与所有其他类别进行分类,然后在第二步中对小型类别进行分类(分类器不应该是相同的。尝试使用模型选择策略来找到最佳分类)。

实用答案

我获得了可接受的结果,而无需重新采样数据!因此,请尝试一下,但以后使用重采样方法对其进行改进(统计上,它们是必须的)。

TFIDF可以解决此类问题。应该通过模型选择来选择分类器,但我的经验表明,逻辑回归和随机森林在此特定问题上效果很好(但是,这只是实践经验)。

您可以遵循下面的代码,因为它工作得很好,然后您可以尝试对其进行修改以改善结果:

train = pd.read_csv(...)
test = pd.read_csv(...)    

# TFIDF Bag Of Words Model For Text Curpos. Up to 4-grams and 50k Features
vec = TfidfVectorizer(ngram_range=(1,4), max_features=50000)
TrainX = vec.fit_transform(train)
TestX = vec.transform(test)


# Initializing Base Estimators
clf1 = LogisticRegression()
clf2 = RandomForestClassifier(n_estimators=100, max_depth=20, max_features=5000,n_jobs=-1)

# Soft Voting Classifier For Each Column
clf = VotingClassifier(estimators=[('lr', clf1), ('rf', clf2)], voting='soft', n_jobs=-1)
clf = clf.fit(TrainX, TrainY)
preds = clf.predict_proba(TestX)[:,1]

请注意,代码是抽象的,因此您应该正确定义TianX,TrainY,TestX等。

提示

请注意什么是StopWord。实际上,很多人(包括我自己!)都犯了此错误,以便根据预定义的列表删除停用词。那是不对的!

停用词对语料库敏感,因此您需要根据信息理论概念删除停用词(为简单起见,您需要了解TFIDF会忽略您的特定于语料库的停用词。如果您需要更多说明,请让我知道以更新我的答案) 。

VotingClassifier是Ensemble Methods系列中的一种元学习策略。他们从不同的分类器中受益。尝试一下,因为它们在实践中效果很好。

投票模式仅采用不同分类器的结果,然后返回概率最高的分类器的输出。这种反对独裁统治的民主方法;)

希望能帮助到你!


欢迎!对于直观的重新采样,您可以参考我放置的用于重新采样的链接。有分步说明。
Kasra Manshaei

我正在尝试您的解决方案,如果我在任何地方卡住或有任何疑问,我将在评论部分中发布。希望对你没问题!
离群值

确定我的朋友...祝你好运!
Kasra Manshaei

1
如果有效,那么您可以接受答案:)
Kasra Manshaei

@outlier,因为答案已经解决了您的问题,请接受(并可能投票);答案占用了(志愿者)应答者的宝贵时间
desertnaut
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.