我知道这个问题有很多讨论,但没有一个是针对我的具体问题。
为了让问题更清晰,我将简化我的问题。假设我有来自一个英文文档的多个句子,我想使用单类SVM(在libsvm中)对它们进行分类,以便之后能够识别异常(例如,一个德语句子)。
在训练过程中:我只有一个类的样本(假设其他类事先不存在)。我提取所有3-gram(因此特征空间最多包括16777216个不同的特征)并以libsvm格式保存它们(标签=1,以防万一这很重要)。
现在我想估计我的参数。我尝试使用grid.py
并添加了额外的参数,但是使用rbf核的时间消耗太大。因此,我尝试使用线性核(因此,grid.py
可能需要修改以只使用一个gamma值,因为对于线性核这并不重要)。
无论如何,grid.py
测试的最小c
值显示为最佳解决方案(对于线性核,-c
是否重要?)。
此外,无论我如何更改-n
(nu)值,每次都会得到相同的分数关系(尽管支持向量的数量会发生变化)。分数是通过python实现收集的。(分数关系的意思是,例如,起初它们是-1和-2,我更改nu
后,它们变成例如-0.5和-1,因此如果我对它们进行排序,总是会出现相同的顺序,如本例所示):
# python2from sklearn.metrics import roc_curve, aucimport matplotlib.pyplot as pltfrom svmutil import *y,x = svm_read_problem("/tmp/english-3-grams.libsvm") # 5000句子样本ym,xm = svm_read_problem("/tmp/german-3-grams.libsvm") # 50句子样本m = svm_train(y,x,"-s 2 -t 2 -n 0.5");# 预测可以在一步或两步中完成,这里是一步:p_l, p_a, p_v = svm_predict(y[:100]+ym[:100],x[:100]+xm[:100],m)# p_v是我们的分数。# 让我们绘制ROC曲线roc_ret = roc_curve([1]*100+[-1]*100,p_v)plt.plot(roc_ret[0],roc_ret[1])plt.show()
在这里,每次都得到完全相同的ROC曲线(即使-n
值有所变化)。即使只有一个支持向量,也会显示相同的曲线。
因此,我的疑问是(假设每次训练的最大样本数为50000):- 为什么-n
对单类训练过程没有任何影响?- 我需要更改哪些参数来进行单类SVM?- 线性核是最好的方法吗?(+考虑到运行时间)而rbf核的参数网格搜索在如此大的数据集上需要花费很长时间- 没有使用liblinear,因为我想进行异常检测=单类SVM
此致,mutilis
回答:
性能影响是由于你的巨大特征空间(16777216个元素)造成的。这导致像德语句子这样的元素具有非常稀疏的向量。
杨和彼得森的研究,文本分类中特征选择的比较研究显示,激进的特征选择不一定降低分类准确性。我在进行(医学)德文文本文档的文本分类时也得到了类似的结果。
正如评论中所述,LIBLINEAR
速度很快,因为它是为这种稀疏数据构建的。然而,你最终得到的是一个线性分类器,具有它的所有缺点和优点。
我建议采取以下策略:
-
进行激进的特征选择(例如使用信息增益),保留特征空间为
N
-
逐步增加
N
,结合交叉验证,找到适合你数据的最佳N
值。 -
使用步骤2中找到的
N
值进行网格搜索。 -
使用步骤3中找到的最佳参数和步骤2中找到的
N
值训练你的分类器。