我正在处理情绪分析问题,数据看起来像这样:
label instances
5 1190
4 838
3 239
1 204
2 127
因此,我的数据不平衡,因为1190 instances
标有5
。对于分类我使用scikit的SVC。问题是我不知道如何以正确的方式平衡我的数据,以便准确计算多类案例的精确度,召回率,准确度和f1分数。所以我尝试了以下方法:
首先:
wclf = SVC(kernel='linear', C= 1, class_weight={1: 10})
wclf.fit(X, y)
weighted_prediction = wclf.predict(X_test)
print 'Accuracy:', accuracy_score(y_test, weighted_prediction)
print 'F1 score:', f1_score(y_test, weighted_prediction,average='weighted')
print 'Recall:', recall_score(y_test, weighted_prediction,
average='weighted')
print 'Precision:', precision_score(y_test, weighted_prediction,
average='weighted')
print '\n clasification report:\n', classification_report(y_test, weighted_prediction)
print '\n confussion matrix:\n',confusion_matrix(y_test, weighted_prediction)
第二
auto_wclf = SVC(kernel='linear', C= 1, class_weight='auto')
auto_wclf.fit(X, y)
auto_weighted_prediction = auto_wclf.predict(X_test)
print 'Accuracy:', accuracy_score(y_test, auto_weighted_prediction)
print 'F1 score:', f1_score(y_test, auto_weighted_prediction,
average='weighted')
print 'Recall:', recall_score(y_test, auto_weighted_prediction,
average='weighted')
print 'Precision:', precision_score(y_test, auto_weighted_prediction,
average='weighted')
print '\n clasification report:\n', classification_report(y_test,auto_weighted_prediction)
print '\n confussion matrix:\n',confusion_matrix(y_test, auto_weighted_prediction)
第三
clf = SVC(kernel='linear', C= 1)
clf.fit(X, y)
prediction = clf.predict(X_test)
from sklearn.metrics import precision_score, \
recall_score, confusion_matrix, classification_report, \
accuracy_score, f1_score
print 'Accuracy:', accuracy_score(y_test, prediction)
print 'F1 score:', f1_score(y_test, prediction)
print 'Recall:', recall_score(y_test, prediction)
print 'Precision:', precision_score(y_test, prediction)
print '\n clasification report:\n', classification_report(y_test,prediction)
print '\n confussion matrix:\n',confusion_matrix(y_test, prediction)
F1 score:/usr/local/lib/python2.7/site-packages/sklearn/metrics/classification.py:676: DeprecationWarning: The default `weighted` averaging is deprecated, and from version 0.18, use of precision, recall or F-score with multiclass or multilabel data or pos_label=None will result in an exception. Please set an explicit value for `average`, one of (None, 'micro', 'macro', 'weighted', 'samples'). In cross validation use, for instance, scoring="f1_weighted" instead of scoring="f1".
sample_weight=sample_weight)
/usr/local/lib/python2.7/site-packages/sklearn/metrics/classification.py:1172: DeprecationWarning: The default `weighted` averaging is deprecated, and from version 0.18, use of precision, recall or F-score with multiclass or multilabel data or pos_label=None will result in an exception. Please set an explicit value for `average`, one of (None, 'micro', 'macro', 'weighted', 'samples'). In cross validation use, for instance, scoring="f1_weighted" instead of scoring="f1".
sample_weight=sample_weight)
/usr/local/lib/python2.7/site-packages/sklearn/metrics/classification.py:1082: DeprecationWarning: The default `weighted` averaging is deprecated, and from version 0.18, use of precision, recall or F-score with multiclass or multilabel data or pos_label=None will result in an exception. Please set an explicit value for `average`, one of (None, 'micro', 'macro', 'weighted', 'samples'). In cross validation use, for instance, scoring="f1_weighted" instead of scoring="f1".
sample_weight=sample_weight)
0.930416613529
然而,我得到这样的警告:
/usr/local/lib/python2.7/site-packages/sklearn/metrics/classification.py:1172:
DeprecationWarning: The default `weighted` averaging is deprecated,
and from version 0.18, use of precision, recall or F-score with
multiclass or multilabel data or pos_label=None will result in an
exception. Please set an explicit value for `average`, one of (None,
'micro', 'macro', 'weighted', 'samples'). In cross validation use, for
instance, scoring="f1_weighted" instead of scoring="f1"
如何才能正确处理不平衡数据,以便以正确的方式计算分类器的指标?
答案 0 :(得分:128)
我认为关于哪些权重用于什么存在很多混淆。我不确定我究竟是什么困扰你,所以我将涵盖不同的主题,忍受我;)。
class_weight
参数的权重用于训练分类器。
它们不用于计算您正在使用的任何指标:使用不同的类权重,数字会因为分类器不同而不同。
基本上在每个scikit-learn分类器中,类权重用于告诉您的模型一个类的重要性。这意味着在训练期间,分类器将做出额外的努力来正确地对高权重的类进行分类 他们如何做到这一点是特定于算法的。如果您想了解SVC的工作原理以及文档对您没有意义,请随时提及。
一旦你有了分类器,你想知道它的表现如何。
在这里,您可以使用您提到的指标:accuracy
,recall_score
,f1_score
......
通常当班级分布不平衡时,准确性被认为是一个不好的选择,因为它给刚刚预测最频繁班级的模型提供了高分。
我不会详细说明所有这些指标,但请注意,除了accuracy
之外,它们自然会在类级别应用:正如您在分类报告print
中所看到的那样,它们是为每个班级定义。他们依赖true positives
或false negative
等概念来定义哪个类是正面。
precision recall f1-score support
0 0.65 1.00 0.79 17
1 0.57 0.75 0.65 16
2 0.33 0.06 0.10 17
avg / total 0.52 0.60 0.51 50
F1 score:/usr/local/lib/python2.7/site-packages/sklearn/metrics/classification.py:676: DeprecationWarning: The
default `weighted` averaging is deprecated, and from version 0.18,
use of precision, recall or F-score with multiclass or multilabel data
or pos_label=None will result in an exception. Please set an explicit
value for `average`, one of (None, 'micro', 'macro', 'weighted',
'samples'). In cross validation use, for instance,
scoring="f1_weighted" instead of scoring="f1".
你得到这个警告,因为你正在使用f1-score,召回和精确度,而没有定义它们应该如何计算! 问题可以改写一下:从上面的分类报告中,你如何为f1分数输出一个全局数字? 你可以:
avg / total
结果。它也被称为宏平均值。'weighted'
将通过类的支持来衡量f1分数:一个类具有的元素越多,该类在计算中的f1分数就越重要。这些是scikit-learn中的3个选项,警告可以说你必须选择一个。因此,您必须为score方法指定average
参数。
您选择哪一个取决于您希望如何衡量分类器的性能:例如宏观平均不考虑类不平衡,而第1类的f1分数与f1-一样重要第5级的分数。如果你使用加权平均,你将会更加重视第5课。
这些指标中的整个论证规范现在在scikit-learn中并不是非常明确,根据文档,它在0.18版本中会变得更好。他们正在删除一些非显而易见的标准行为,他们正在发出警告,以便开发人员注意到它。
我想提及的最后一件事(如果你意识到的话,可以随意跳过它),只有在分类器从未见过的数据计算得分时,分数才有意义。 这非常重要,因为您在拟合分类器时使用的数据得分与完全无关。
这是使用StratifiedShuffleSplit
执行此操作的方法,它可以随机分割您的数据(在随机播放后),以保留标签分布。
from sklearn.datasets import make_classification
from sklearn.cross_validation import StratifiedShuffleSplit
from sklearn.metrics import accuracy_score, f1_score, precision_score, recall_score, classification_report, confusion_matrix
# We use a utility to generate artificial classification data.
X, y = make_classification(n_samples=100, n_informative=10, n_classes=3)
sss = StratifiedShuffleSplit(y, n_iter=1, test_size=0.5, random_state=0)
for train_idx, test_idx in sss:
X_train, X_test, y_train, y_test = X[train_idx], X[test_idx], y[train_idx], y[test_idx]
svc.fit(X_train, y_train)
y_pred = svc.predict(X_test)
print(f1_score(y_test, y_pred, average="macro"))
print(precision_score(y_test, y_pred, average="macro"))
print(recall_score(y_test, y_pred, average="macro"))
希望这有帮助。
答案 1 :(得分:58)
这里有很多非常详细的答案,但我不认为你正在回答正确的问题。据我了解这个问题,有两个问题:
你可以使用scikit-learn中的大多数评分函数来解决多类问题和单类问题。例:
from sklearn.metrics import precision_recall_fscore_support as score
predicted = [1,2,3,4,5,1,2,1,1,4,5]
y_test = [1,2,3,4,5,1,2,1,1,4,1]
precision, recall, fscore, support = score(y_test, predicted)
print('precision: {}'.format(precision))
print('recall: {}'.format(recall))
print('fscore: {}'.format(fscore))
print('support: {}'.format(support))
这样,您最终会得到每个班级的有形和可解释的数字。
| Label | Precision | Recall | FScore | Support |
|-------|-----------|--------|--------|---------|
| 1 | 94% | 83% | 0.88 | 204 |
| 2 | 71% | 50% | 0.54 | 127 |
| ... | ... | ... | ... | ... |
| 4 | 80% | 98% | 0.89 | 838 |
| 5 | 93% | 81% | 0.91 | 1190 |
则...
...你可以判断不平衡数据是否是一个问题。如果较少代表的类(1级和2级)的得分低于具有更多训练样本(4级和5级)的类,则您知道不平衡数据实际上是一个问题,并且您可以相应地采取行动,如在这个帖子中的一些其他答案中描述。 但是,如果您想要预测的数据中存在相同的类别分布,那么您的不平衡训练数据就是数据的良好代表,因此,不平衡是一件好事。
答案 2 :(得分:15)
提出问题
回答“使用不平衡数据进行多级分类应采用什么指标”的问题:Macro-F1-measure。 宏精度和宏调用也可以使用,但它们不像二进制分类那么容易解释,它们已经被合并到F-measure中,而且过多的度量使方法比较,参数调整等变得复杂。
微观平均对类不平衡很敏感:例如,如果您的方法适用于最常见的标签并且完全混淆其他标签,则微观平均指标会显示出良好的结果。
加权平均不太适合不平衡数据,因为它按标签计数加权。此外,它太难以解释和不受欢迎:例如,在以下非常详细的survey中没有提及这种平均值我强烈建议您仔细阅读:
Sokolova,Marina和Guy Lapalme。 “系统分析 分类任务的绩效衡量标准。“信息处理 &安培;管理45.4(2009):427-437。
特定于应用的问题
然而,回到你的任务,我将研究2个主题:
常用指标。 通过阅读文献后我可以推断,有两个主要的评估指标:
Yu,April,和Daryl Chang。 “多类情绪预测使用 Yelp Business。“
(link) - 请注意作者使用几乎相同的评级分布,见图5.
Pang,Bo和Lillian Lee。 “看到明星:剥削阶级 关于评级的情绪分类关系 “第四十三届年会的会议记录 计算语言学。计算语言学协会, 2005。
(link)
李,Moontae和R. Grafe。 “多类情绪分析与 餐厅评论。“CS N 224(2010)的最终项目。
(link) - 他们探索准确性和MSE,考虑到后者更好
Pappas,Nikolaos,Rue Marconi和Andrei Popescu-Belis。 “解释 星系:基于方面的加权多实例学习 “情绪分析”,“2014年经验会议论文集” 自然语言处理方法。 No. EPFL-CONF-200899。 2014。
(link) - 他们利用scikit-learn进行评估和基线方法,并说明他们的代码是可用的;但是,我找不到它,所以如果你需要它,写信给作者,这项工作很新,似乎是用Python编写的。
不同错误的成本。 如果你更关心避免重大错误,例如对一星级到五星级的评论或类似的东西,看看MSE; 如果差异很重要,但不是那么多,试试MAE,因为它不是方差; 否则保持准确性。
关于方法,而非指标
尝试回归方法,例如SVR,因为它们通常优于SVC或OVA SVM等多类分类器。
答案 3 :(得分:12)
首先,使用计数分析判断您的数据是否不平衡有点困难。例如:千分之一的正面观察只是一个噪音,错误或科学上的突破?你永远不会知道。
因此,最好使用所有可用的知识,并明智地选择其状态。
好的,如果它真的不平衡怎么办?
再一次 - 查看您的数据。有时您可以找到一两次观察乘以百次。有时创建这种假的一类观察是有用的
如果所有数据都是干净的,那么下一步就是在预测模型中使用类权重。
那么多类指标呢?
根据我的经验,通常不使用任何指标。主要有两个原因
第一:使用概率而不是实体预测总是更好(因为如果他们都给你相同的类,你怎么能用0.9和0.6预测分离模型?)
第二:根据一个好的指标,比较预测模型和建立新模型要容易得多
根据我的经验,我可以推荐logloss或MSE(或只是意味着平方误差)。
如何修复sklearn警告?
只是简单地(正如杨杰注意到的那样)用其中一个覆盖average
参数
值:'micro'
(全局计算指标),'macro'
(计算每个标签的指标)或'weighted'
(与宏相同但具有自动权重)。
f1_score(y_test, prediction, average='weighted')
调用具有默认average
值'binary'
的指标函数后,所有警告都出现了,这不适用于多类预测。
祝你好运,享受机器学习的乐趣!
修改强>
我发现另一个回答者建议切换到我不能同意的回归方法(例如SVR)。据我记得,甚至没有多类回归这样的东西。是的,有多标签回归,这是非常不同的,是的,在某些情况下,有可能在回归和分类之间切换(如果类按某种方式排序),但这种情况非常罕见。
我建议(在scikit-learn的范围内)是尝试另一种非常强大的分类工具:gradient boosting,random forest(我最喜欢的),KNeighbors等等。< / p>
之后,您可以计算预测之间的算术或几何平均值,并且大部分时间您将获得更好的结果。
final_prediction = (KNNprediction * RFprediction) ** 0.5