【问题标题】:NLTK: Tuning LinearSVC classifier accuracy? - Looking for better approaches/advicesNLTK:调整 LinearSVC 分类器的准确性? - 寻找更好的方法/建议
【发布时间】:2015-11-29 05:02:43
【问题描述】:

问题/主要目标/TLDR: 训练分类器,然后对其进行随机评论并获得相应的预测评论评级(星数从 1 到 5) - 只有 60% 的准确度! :(

我有一个包含大约 48000 条技术产品评论的大型数据集(来自许多不同的作者和不同的产品 - 这不是那么重要 (?))和相应的评分(1 到 5 星) 我在每个班级中随机选择了一些评论:

  • 1 星:173 条评论(无法选择 1000 条,因为有 173 条)
  • 2 星:1000 条评论
  • 3 星:1000 条评论
  • 4 星:1000 条评论
  • 5 星:1000 条评论

总计:4173 条评论 - 此数据以元组格式组织在一个文件 (all_reviews_labeled.txt) 中,一条评论和评分为:

  • (‘评论文本’, ‘x 星’)
  • (‘评论文本’, ‘x 星’)
  • (‘评论文本’, ‘x 星’)
  • (‘评论文本’, ‘x 星’)

我的第一个“傻瓜”方法是:

  1. 标记评论文本
  2. 词性标注
  3. 获取遵循某些 POS 标签规则的最常见的二元组 最常见的三元组(我见过这个规则 - 使用这个 POS “从文本评论中自动生成星级”中的模式 - 第 7 页 - Chong-U Lim、Pablo Ortiz 和 Sang-Woo Jun 的论文):

    for (w1,t1), (w2,t2), (w3,t3) in nltk.trigrams(text):
        if (t1 == 'JJ' or t1 == 'JJS' or t1 == 'JJR') and (t2 == 'NN' or t2 == 'NNS'):
            bi = unicode(w1 + ' ' + w2).encode('utf-8')
            bigrams.append(bi)
        elif (t1 == 'RB' or t1 == 'RBR' or t1 == 'RBS') and (t2 == 'JJ' or t2 == 'JJS' or t2 == 'JJR') and (t3 != 'NN' or t3 != 'NNS'):
            bi = unicode(w1 + ' ' + w2).encode('utf-8')
            bigrams.append(bi)
        elif (t1 == 'JJ' or t1 == 'JJS' or t1 == 'JJR') and (t2 == 'JJ' or t2 == 'JJS' or t2 == 'JJRS') and (t3 != 'NN' or t3 != 'NNS'):
            bi = unicode(w1 + ' ' + w2).encode('utf-8')
            bigrams.append(bi)
        elif (t1 == 'NN' or t1 == 'NNS') and (t2 == 'JJ' or t2 == 'JJS' or t2 == 'JJRS') and (t3 != 'NN' or t3 != 'NNS'):
            bi = unicode(w1 + ' ' + w2).encode('utf-8')
            bigrams.append(bi)
        elif (t1 == 'RB' or t1 == 'RBR' or t1 == 'RBS') and (t2 == 'VB' or t2 == 'VBD' or t2 == 'VBN' or t2 == 'VBG'):
            bi = unicode(w1 + ' ' + w2).encode('utf-8')
            bigrams.append(bi)
        elif (t1 == 'DT') and (t2 == 'JJ' or t2 == 'JJS' or t2 == 'JJRS'):
            bi = unicode(w1 + ' ' + w2).encode('utf-8')
            bigrams.append(bi)
        elif (t1 == 'VBZ') and (t2 == 'JJ' or t2 == 'JJS' or t2 == 'JJRS'):
            bi = unicode(w1 + ' ' + w2).encode('utf-8')
            bigrams.append(bi)
        else:
            continue
    
  4. 提取特征(这是我有更多疑问的地方 - 我应该 只找这两个功能?):

    features={}
    for bigram,freq in word_features:
        features['contains(%s)' % unicode(bigram).encode('utf-8')] = True
        features["count({})".format(unicode(bigram).encode('utf-8'))] = freq
    return features
    

    featuresets = [(review_features(review), rating) for (review, rating) in tuples_labeled_reviews]

  5. 将训练数据分为训练规模和测试规模 (90% 训练 - 10% 测试):

    numtrain = int(len(tuples_labeled_reviews) * 90 / 100)
    train_set, test_set = featuresets[:numtrain], featuresets[numtrain:]
    
  6. 训练 SVMc:

    classifier = nltk.classify.SklearnClassifier(LinearSVC())
    classifier.train(train_set)
    
  7. 评估分类器:

    errors = 0
    correct = 0
    for review, rating in test_set:
        tagged_rating = classifier.classify(review)
        if tagged_rating == rating:
            correct += 1
            print("Correct")
            print "Guess: ", tagged_rating
            print "Correct: ", rating
        else:
            errors += 1
    

到目前为止,我的准确率只有 60%…… 我可以做些什么来改善我的预测结果?之前是否有一些文本/评论预处理(例如删除停用词/标点符号?)丢失了?你能建议我一些其他的方法吗?如果真的是分类问题还是回归问题,我仍然有点困惑......:/

请简单解释,或者给我一个“机器学习傻瓜”的链接,或者做我的导师,我保证学得很快! 我在机器学习/语言处理/数据挖掘方面的背景很浅,我玩过几次weka(Java),但现在我需要坚持使用Python(nltk + scikit-learn)!

编辑:

  1. 现在我还提取一元词作为特征,一元词的 POS 标记为“JJ”、“NN”、“VB”和“RB”。将准确率稍微提高到 65%。
  2. 我还应用了在词性标记之前对文本进行词干提取和词形还原。它将准确率提高到 +70%。

编辑 2:

  1. 我已将我所有的评论(48000 条评论)提供给分类器,分为 90% 的训练和 10% 的测试,准确度为 91%。

  2. 1234563 /-1 星点,+2/-2,+3/-3 - 因为它只是一个插图):

怎么了?为什么在 3 星和 5 星时准确率会下降这么多?

【问题讨论】:

  • 这个问题有点开放,可能会得到更多好的答案@this site。无论如何,对我来说,你的方法看起来不错,而且你第一次试验的 60% 准确率还不错(虽然我不知道你花了多长时间)。 (你如何衡量准确度?因为比率是 1 到 5,所以准确度是指你完全正确的时候?但是,那些不正确的,至少是封闭的?)你应该明确做的一件事是看一些分类错误的例子,并试图找出原因。另一件事,你在训练中得到什么准确度?
  • 这是一个回归问题还是分类问题取决于你想用它做什么:如果分类器预测 1 星获得 5 星评价,或者预测 4 星获得这个5星评价?如果是这样,那么准确性可能不是一个好的指标(因为它不能区分这些情况)。这是在进行预处理或调整算法之前最重要的问题。
  • @Irnzcig 我花了多长时间?所有的构建策略+训练分类器?我在这大约只有一个星期 =x --- 训练分类器需要 3 个小时。我只验证了测试的准确性,我现在将验证用于训练。非常感谢您的帮助/意见
  • @Idirer 你说准确性不是一个好的指标,因为它只衡量正确评论的百分比,对吧?我需要一个专注于错误的人,看看它是否真的是错误的或近似的?就像给 4 星给 5 星评论,而不是极端,就像给 1 星给 5 星评论......我只是目视检查,只有 1 分的差异有更多错误
  • 对您的训练集进行交叉验证。不是在训练中测试。对训练进行测试只是一个健全性检查,因为在训练集上进行测试时应该始终获得优化的结果。

标签: python machine-learning nlp scikit-learn nltk


【解决方案1】:

考虑添加更多功能。对于我的任务,要在四位作者之间找到一篇文章的作者,我使用了以下功能:

  • 句子特征

    • 单词的平均句子长度
    • 以音节为单位的平均句子长度
    • 平均句子长度(以字符为单位)
    • 长句百分比
  • 词汇特征

    • 字数
    • Hapaxes(单词只出现一次)
    • Dislegomena(单词只出现两次)
    • Dislegomena 与 Hapaxes 的比率
    • 平均字长
    • 词汇多样性
    • 尤尔克
    • HeransC
    • GuiraudsR
    • 优步
    • 相对熵
    • 1lw .. 14lw(1个字符,2个字符,...14个字符的词出现的频率)
  • 字符特征
    • 字符 a 的百分比,
    • 字符 b 的百分比,
    • ...
  • 的话
    • 语料库中最常用的 50 个单词的百分比

对于每个文本,上面构建了它的特征向量。我在SPSS中使用了判别分析。当然你可以使用 SVM 或其他分类器。

【讨论】:

  • 我使用了所有的数据集,48000 条评论,90% 的训练 - 10% 的测试,使用 SVMc,只查看二元组和形容词,准确率达到 93%,这正常吗?跨度>
  • 尝试使用 5 到 10 折交叉验证以获得更准确的结果。在评论中,形容词,特别是二元组或三元组中的形容词包含很多信息。例如,我们认为“坏”:否定,“好”:肯定。但是,“不错”:积极,“不好”:消极。
  • 交叉验证 10 倍。平均准确率为 98%,感谢@Aris F. 的建议
猜你喜欢
  • 2018-07-06
  • 1970-01-01
  • 1970-01-01
  • 2023-04-04
  • 2012-02-14
  • 2016-10-09
  • 1970-01-01
  • 2018-12-15
  • 1970-01-01
相关资源
最近更新 更多