5

我有2599个文件,从1到5的文件五个标记文本分类任务是如何使用scikit-learn和matplotlib绘制不平衡数据集的SVC分类?

label | texts 
---------- 
5  |1190 
4  |839 
3  |239 
1  |204 
2  |127 

所有准备将此划文本具有非常低的性能数据,并同时获得约不明确的指标警告:

Accuracy: 0.461057692308 

score: 0.461057692308 

precision: 0.212574195636 

recall: 0.461057692308 

    'precision', 'predicted', average, warn_for) 
confussion matrix: 
[[ 0 0 0 0 153] 
    'precision', 'predicted', average, warn_for) 
[ 0 0 0 0 94] 
[ 0 0 0 0 194] 
[ 0 0 0 0 680] 
[ 0 0 0 0 959]] 

clasification report: 
      precision recall f1-score support 

      1  0.00  0.00  0.00  153 
      2  0.00  0.00  0.00  94 
      3  0.00  0.00  0.00  194 
      4  0.00  0.00  0.00  680 
      5  0.46  1.00  0.63  959 

avg/total  0.21  0.46  0.29  2080 

显然,这是事实,我有一个不平衡的数据集发生的事情,所以我发现这个paper这里作者提出了几个aproaches来解决这个问题:

The problem is that with imbalanced datasets, the learned boundary is too close to the positive instances. We need to bias SVM in a way that will push the boundary away from the positive instances. Veropoulos et al [14] suggest using different error costs for the positive (C +) and negative (C -) classes

我知道,这可能是非常复杂的,但SVC提供了几个超参数,所以我的问题是:有没有什么办法偏见SVC在与超参数,提供SVC分类推边界远离独到之处实例的方式?。我知道这可能是一个困难的问题,但任何帮助是值得欢迎的,这要归功于前辈们。

from sklearn.feature_extraction.text import TfidfVectorizer 
import numpy as np 
tfidf_vect= TfidfVectorizer(use_idf=True, smooth_idf=True, sublinear_tf=False, ngram_range=(2,2)) 
from sklearn.cross_validation import train_test_split, cross_val_score 

import pandas as pd 
df = pd.read_csv('/path/of/the/file.csv', 
        header=0, sep=',', names=['id', 'text', 'label']) 



reduced_data = tfidf_vect.fit_transform(df['text'].values) 
y = df['label'].values 



from sklearn.decomposition.truncated_svd import TruncatedSVD 
svd = TruncatedSVD(n_components=5) 
reduced_data = svd.fit_transform(reduced_data) 

from sklearn import cross_validation 
X_train, X_test, y_train, y_test = cross_validation.train_test_split(reduced_data, 
                y, test_size=0.33) 

#with no weights: 

from sklearn.svm import SVC 
clf = SVC(kernel='linear', class_weight={1: 10}) 
clf.fit(reduced_data, y) 
prediction = clf.predict(X_test) 

w = clf.coef_[0] 
a = -w[0]/w[1] 
xx = np.linspace(-5, 5) 
yy = a * xx - clf.intercept_[0]/w[1] 


# get the separating hyperplane using weighted classes 
wclf = SVC(kernel='linear', class_weight={1: 10}) 
wclf.fit(reduced_data, y) 

ww = wclf.coef_[0] 
wa = -ww[0]/ww[1] 
wyy = wa * xx - wclf.intercept_[0]/ww[1] 

# plot separating hyperplanes and samples 
import matplotlib.pyplot as plt 
h0 = plt.plot(xx, yy, 'k-', label='no weights') 
h1 = plt.plot(xx, wyy, 'k--', label='with weights') 
plt.scatter(reduced_data[:, 0], reduced_data[:, 1], c=y, cmap=plt.cm.Paired) 
plt.legend() 

plt.axis('tight') 
plt.show() 

但我什么也没有,我不能明白发生了什么,这是剧情:

weighted vs normal

则:

#Let's show some metrics[unweighted]: 
from sklearn.metrics.metrics import precision_score, \ 
    recall_score, confusion_matrix, classification_report, accuracy_score 
print '\nAccuracy:', accuracy_score(y_test, prediction) 
print '\nscore:', clf.score(X_train, y_train) 
print '\nrecall:', recall_score(y_test, prediction) 
print '\nprecision:', 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) 

#Let's show some metrics[weighted]: 
print 'weighted:\n' 

from sklearn.metrics.metrics import precision_score, \ 
    recall_score, confusion_matrix, classification_report, accuracy_score 
print '\nAccuracy:', accuracy_score(y_test, prediction) 
print '\nscore:', wclf.score(X_train, y_train) 
print '\nrecall:', recall_score(y_test, prediction) 
print '\nprecision:', 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) 

这是即时通讯使用的data。我该如何解决这个问题,并以正确的方式策划这个问题?在此先感谢家伙!

从这个问题的答案我删除此行:

# 
# from sklearn.decomposition.truncated_svd import TruncatedSVD 
# svd = TruncatedSVD(n_components=5) 
# reduced_data = svd.fit_transform(reduced_data) 


# 
# w = clf.coef_[0] 
# a = -w[0]/w[1] 
# xx = np.linspace(-10, 10) 
# yy = a * xx - clf.intercept_[0]/w[1] 

# ww = wclf.coef_[0] 
# wa = -ww[0]/ww[1] 
# wyy = wa * xx - wclf.intercept_[0]/ww[1] 
# 
# # plot separating hyperplanes and samples 
# import matplotlib.pyplot as plt 
# h0 = plt.plot(xx, yy, 'k-', label='no weights') 
# h1 = plt.plot(xx, wyy, 'k--', label='with weights') 
# plt.scatter(reduced_data[:, 0], reduced_data[:, 1], c=y, cmap=plt.cm.Paired) 
# plt.legend() 
# 
# plt.axis('tight') 
# plt.show() 

This where the results: 

Accuracy: 0.787878787879 

score: 0.779437105112 

recall: 0.787878787879 

precision: 0.827705441238 

这个指标的改善。 如何绘制这个结果以获得像文档一样的好例子。我想看看两架超飞机的行为?。多谢你们!

+1

'显然这是由于我有一个不平衡的数据集的事实发生的 - 根据你所说的,我根本没有发现这一点。你能告诉我们你的代码甚至数据吗? – IVlad 2015-02-12 11:05:14

+1

没有SVD和没有触及class_weight参数,你会得到什么?尝试首先关注性能,然后再进行绘图。 – IVlad 2015-02-15 09:17:10

+0

@Ivlad不使用从不平衡数据集这个文档的例子是我得到的性能:'精度:0.461057692308 评分:0.461057692308 精度:0.212574195636 召回:0.461057692308'这是我可以用网格搜索做到最好。 – tumbleweed 2015-02-15 18:10:20

回答

2

如果我理解你正确输入您有:

1190 5个标记文本 1409的1-4标记文本

的您可以尝试做一个sequental分类。首先威胁的所有5个标签为1,所有其他为0火车这个任务

二分类,从数据集中退出所有5个例。训练分类器对1-4个标签进行分类。

在分类运行第一分类器,如果它返回0 - 运行第二分类器,以获得最终的标签。

虽然我不认为这种分布是真的偏斜和不平衡的(它应该像5%的90%,10% - 所有的休息,真的是倾斜的,所以引入偏见可能是有趣的SVC)。因此,我认为你可能想尝试一些其他的分类算法,因为看起来像你的选择不适合这个任务。或者也许你需要在SVC中使用不同的内核(我假设你使用线性内核,尝试一些不同的东西 - 也许是RBF或多项式)。

+0

我正在使用rbf,我尝试了多项,RF,LR和svc,它具有最佳性能。 – tumbleweed 2015-02-13 00:07:49

+0

感谢您的反馈意见。任何想法如何偏向SVC分类器? – tumbleweed 2015-02-13 20:44:31

+1

我相信klubow提供了一些有用的信息。在scikit-learn中,您可以阅读有关正确使用unballanced类别的方法:http://scikit-learn.org/stable/auto_examples/svm/plot_separating_hyperplane_unbalanced.html请记住,您需要手动调整课程权重最佳性能,或尝试使用GridSearchCV自动调整它们(尽管您需要使用一些特定的评分指标,否则您将得不到好的结果)。 – 2015-02-14 21:20:42

1

您可能要检查SVM分类 或 平衡你的数据(https://github.com/fmfn/UnbalancedDataset/blob/master/UnbalancedDataset.py

+0

对于这个问题,我需要设置什么样的class_weight来偏向SVM?谢谢您的帮助! – tumbleweed 2015-02-13 20:43:38

+0

我编辑过,感谢您的帮助! – tumbleweed 2015-02-15 04:59:51

+0

这帮了我很多,想知道如何绘制这个?我只想公平对待赏金的东西。 – tumbleweed 2015-02-25 19:35:30

2

作为一个简单的解决方案class_weight参数(http://scikit-learn.org/stable/modules/generated/sklearn.svm.SVC.html),只需乘实例在小班和平衡实例的数量。即使这看起来很愚蠢,它在钻机配置中也不需要。

使用这种方法的想法是模仿每个班级的缩放学习率对其班级规模的行为。也就是说,在基于梯度的优化方法中,您应该按照每个类的类大小成反比地调整学习速率,以防止模型忽略其他类的类。

如果你的问题很大,而且你正在使用批量更新,那么不要预订所有的数据集和计数类,而应该考虑微型批处理和动态调整学习率,批量。

这意味着如果您的母校学习率为0.01,并且在一批实例中您有0.4个A级和0.6个B级,那么您需要将每个班级的最终学习率调整为班级的master_learning率A(表示保持不变),2/3 * B级的master_learning率。因此,您可以为A级提供更宽的级别,反之可提高B级级别。

我选择走,特别是对于大型问题和扩充数据更小的类通过复制实例或作为更强大的选择,向复制的实例添加一些噪声和差异。以这种方式,(取决于你的问题),你也可以训练一个对小变化更强健的模型(这对于特别是图像分类问题是非常常见的)。

+1

您是否有任何关于此功能的声明参考?我没有看到它与SVM一起工作。 – IVlad 2015-02-13 18:05:05

+0

事实上,我正在考虑做这个事情.... gust复制和粘贴,以平衡这一点。这个问题的理论解释是什么?感谢您的反馈 – tumbleweed 2015-02-13 20:42:04

+1

您只需平衡每个班级的模型更新次数。从理论上讲,设定学习率与每个班的实例数成反比是更有意义的。通过设置实例的数量,您可以以天真的方式模仿相同的行为。 – erogol 2015-02-13 20:48:57

4

通过减少数据5SVD特点:

svd = TruncatedSVD(n_components=5) 
reduced_data = svd.fit_transform(reduced_data) 

你失去了很多的信息。只是通过删除这些行我得到78%准确性。

离开参数设置class_weight它似乎比删除它好。我没有尝试给它其他的价值。

研究使用k-fold cross validationgrid search来调整模型的参数。如果您想减少数据的维度,则还可以使用pipeline,以便确定要在不影响性能的情况下减少多少。 Here是一个示例,显示如何使用网格搜索来调整整个管道。

至于绘图,你只能绘制2D或3D数据。在使用更多维度训练之后,您可以将数据减少到2或3维并绘制该维度。绘图示例见here。代码看起来与你正在绘制的内容相似,并且我得到了与你相似的结果。问题在于你的数据有许多特征,你只能将事物绘制成2D或3D曲面。这通常会让它看起来很奇怪,很难说出发生了什么。

我建议你不要打算绘图,因为它不会告诉你很多数据的高维度。使用网格搜索进行k-fold交叉验证,以获得最佳参数,如果您想查看过度拟合,请改为绘制learning curves

所有这些结合起来会告诉你更多关于你的模型的行为,而不是绘制超平面。

+0

事实上,我使用网格搜索,但它需要很长的搜索...一长... – tumbleweed 2015-02-15 17:43:26

+0

感谢您的帮助。我删除了这些行,并得到以下异常:'Traceback(最近一次调用最后一次): 文件“/Users/user/test.py”,第35行,在中 a = -w [0]/w [1] 文件“/usr/local/lib/python2.7/site-packages/scipy/sparse/csr.py”,第253行,在__getitem__中 return self._get_row_slice(row,col) 文件“/ usr/local/lib/python2.7/site-packages/scipy/sparse/csr.py“,第320行,在_get_row_slice中 raise IndexError('index(%d)out of range'%i) IndexError:index(1)out范围 '。任何想法如何解决这个问题? – tumbleweed 2015-02-15 17:51:23

+1

@ml_guy - 我也评论了'w = clf.coef_ [0] a = -w [0]/w [1] xx = np.linspace(-5,5) yy = a * xx - clf。 intercept_ [0]/w [1]'为了解决这个问题。我也评论了绘图代码。 – IVlad 2015-02-15 18:06:19

2

您可能已经尝试将class-weight设置为auto,但我想检查一下。

也许平衡实验(oversampling or undersampling)可以帮助,它的一些lib已经被klubow建议。

+0

随着班级重量自动这是结果:'准确性:0.453846153846 得分:0.458315519453 回忆:0.453846153846 精度:0.205976331361'指标下降.. – tumbleweed 2015-02-21 19:54:52

相关问题