Problem/Main objective/TLDR: 训练一个分类器,然后给它一个随机的评论并获得相应的预测评论评级(星数从1到5) - 只有60%的准确率! :(
我有一个大型数据集,有大约48000个技术产品评论(来自许多不同的作者和来自不同的产品 - 这里不是那么重要(?))和相应的评级(1到5星)我在每个 class 中随机选择了一些评论:
-
1星级:173条评论(因为有173条评论不提供1000条评论)
-
2星级:1000条评论
-
3星级:1000条评论
-
4星级:1000条评论
-
5星级:1000条评论
总共:4173条评论 - 此数据以元组格式组织在一个文件(all_reviews_labeled.txt)中,一条评论和评级为:
-
('评论文字','x star')
-
('评论文字','x star')
-
('评论文字','x star')
-
('评论文字','x star')
-
......
我的第一个“dummie”方法是:
-
Tokenize评论文本
-
POS标记
-
获取最常见的双字符串,其中包含一些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
- 提取功能(这里是我有更多疑问的地方 - 我应该只查找这两个功能吗?):
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]
- 将训练数据分成训练大小和测试大小(90%训练--10%测试):
numtrain = int(len(tuples_labeled_reviews) * 90 / 100)
train_set, test_set = featuresets[:numtrain], featuresets[numtrain:]
- 火车SVMc:
classifier = nltk.classify.SklearnClassifier(LinearSVC())
classifier.train(train_set)
- 评估分类器:
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)!
EDIT:
-
现在我也提取unigrams作为功能,unigrams POS标记为'JJ','NN','VB'和'RB' . 它将精度提高到65% .
-
我在POS标记之前也应用了文本中的词干和词形还原 . 它将准确度提高到70% .
EDIT 2:
-
我已经为分类器提供了所有评论,48000,分为90%的培训和10%的测试,准确率为91% .
-
现在我有32000个新的评论(也标记了)并将它们全部用于测试,平均准确度为62%...我的混淆矩阵如下图所示(除以1 / -1星点的相等误差, 2 / -2,3 / -3 - 因为它只是一个例子):
发生了什么事?为什么准确度在3星和5星下降得那么多?
1 回答
考虑添加更多功能 . 对于我的任务,为了找到四位作者之间的文本作者,我使用了以下功能:
句子功能
平均句子长度
音节中的平均句子长度
平均句子长度(以字符为单位)
长句百分比
词汇特征
单词数量
Hapaxes(单词仅见过一次)
Dislegomena(单词只见过两次)
Dislegomena与Hapaxes的比率
平均字长
词汇多样性
YuleK
HeransC
GuiraudsR
优步
熵
相对熵
1lw .. 14lw(包含一个字符的单词的频率,包含两个字符,...包含14个字符)
角色特征
字符a的百分比,
字符b的百分比,
......
单词
语料库中50个最常用词的每一个的百分比
对于每个文本,上面构建它的特征向量 . 我在SPSS中使用了判别分析 . 当然,您可以使用SVM或其他分类器 .