通过 libsvm 对 n-gram 进行线性 One Class SVM 训练的参数估计
Parameter estimation for linear One Class SVM training via libsvm for n-grams
我知道,对此有多个问题,但没有一个是针对我的特定问题的。
我将简化我的问题以使其更清楚。
假设我有一个英文文档中的多个句子,我想 class 使用一个 class 支持向量机(在 libsvm 中)对它们进行 class 验证,以便之后能够看到异常情况(例如德语句子)。
对于训练:我只有一个 class 的样本(假设其他 class 事先不存在)。我提取所有 3-grams(因此特征 space 最多包含 16777216 个不同的特征)并将它们保存为 libsvm 格式(标签=1,以防万一)
现在我想估计我的参数。我尝试使用附加参数来使用 grid.py
,但是,运行时对于 rbf 内核来说太大了。所以我尝试使用线性内核(因此,grid.py
可能会更改以便仅使用一个伽玛值,因为它对线性内核无关紧要)。
无论如何,最小的 c
grid.py 测试将显示为最佳解决方案(-c 对线性内核重要吗?)。
此外,无论我如何改变 -n
(nu) 值,每次得分之间的关系都会相同(即使支持向量的数量发生变化)。使用 python 实现收集分数。 (分数之间的关系意味着,例如,起初它们是 -1 和 -2,我更改 nu
然后它们是 -0.5 和 -1,所以如果我对它们进行排序,总是出现相同的顺序,如这个例子):
# python2
from sklearn.metrics import roc_curve, auc
import matplotlib.pyplot as plt
from svmutil import *
y,x = svm_read_problem("/tmp/english-3-grams.libsvm") # 5000 sentence samples
ym,xm = svm_read_problem("/tmp/german-3-grams.libsvm") # 50 sentence samples
m = svm_train(y,x,"-s 2 -t 2 -n 0.5");
# do the prediction in one or two steps, here is one step:
p_l, p_a, p_v = svm_predict(y[:100]+ym[:100],x[:100]+xm[:100],m)
# p_v are our scores.
# let's plot a roc curve
roc_ret = roc_curve([1]*100+[-1]*100,p_v)
plt.plot(roc_ret[0],roc_ret[1])
plt.show()
在这里,每次都获得完全相同的 roc 曲线(即使 -n
有所不同)。即使只有 1 个支持向量,也会显示相同的曲线。
因此,我的问题(假设每次训练最多 50000 个样本):
- 为什么 -n
没有为一个 class 训练过程做任何改变?
- 我需要为 class 支持向量机更改哪些参数?
- 线性内核是最好的方法吗? (+ 关于运行时)和 rbf 内核参数网格搜索需要很长时间才能处理如此大的数据集
- 没有使用 liblinear,因为我想进行异常检测 = one class svm
此致,
多重
性能影响是您的巨大特征 space 的 16777216 个元素的结果。这会导致德语句子等元素的向量非常稀疏。
Yang & Petersen 的一项研究 A Comparative Study on Feature Selection in Text Categorization 表明,激进 feature-selection 不一定会降低分类准确性。我在对(医学)德语文本文档进行文本分类时取得了类似的结果。
如评论中所述,LIBLINEAR
很快,因为它是为此类稀疏数据构建的。然而,您最终得到的是一个线性分类器,它有所有的缺陷和好处。
我建议采用以下策略:
使用 N
的剩余 feature-space 执行积极的特征选择(例如使用 InformationGain)
结合 cross-validation 逐步增加 N
并为您的数据找到 最佳 加工 N
。
使用 2.
中的 N
寻找 grid-search
使用 3. 中找到的最佳匹配参数和 2.
中找到的 N
训练您的分类器
我知道,对此有多个问题,但没有一个是针对我的特定问题的。
我将简化我的问题以使其更清楚。 假设我有一个英文文档中的多个句子,我想 class 使用一个 class 支持向量机(在 libsvm 中)对它们进行 class 验证,以便之后能够看到异常情况(例如德语句子)。
对于训练:我只有一个 class 的样本(假设其他 class 事先不存在)。我提取所有 3-grams(因此特征 space 最多包含 16777216 个不同的特征)并将它们保存为 libsvm 格式(标签=1,以防万一)
现在我想估计我的参数。我尝试使用附加参数来使用 grid.py
,但是,运行时对于 rbf 内核来说太大了。所以我尝试使用线性内核(因此,grid.py
可能会更改以便仅使用一个伽玛值,因为它对线性内核无关紧要)。
无论如何,最小的 c
grid.py 测试将显示为最佳解决方案(-c 对线性内核重要吗?)。
此外,无论我如何改变 -n
(nu) 值,每次得分之间的关系都会相同(即使支持向量的数量发生变化)。使用 python 实现收集分数。 (分数之间的关系意味着,例如,起初它们是 -1 和 -2,我更改 nu
然后它们是 -0.5 和 -1,所以如果我对它们进行排序,总是出现相同的顺序,如这个例子):
# python2
from sklearn.metrics import roc_curve, auc
import matplotlib.pyplot as plt
from svmutil import *
y,x = svm_read_problem("/tmp/english-3-grams.libsvm") # 5000 sentence samples
ym,xm = svm_read_problem("/tmp/german-3-grams.libsvm") # 50 sentence samples
m = svm_train(y,x,"-s 2 -t 2 -n 0.5");
# do the prediction in one or two steps, here is one step:
p_l, p_a, p_v = svm_predict(y[:100]+ym[:100],x[:100]+xm[:100],m)
# p_v are our scores.
# let's plot a roc curve
roc_ret = roc_curve([1]*100+[-1]*100,p_v)
plt.plot(roc_ret[0],roc_ret[1])
plt.show()
在这里,每次都获得完全相同的 roc 曲线(即使 -n
有所不同)。即使只有 1 个支持向量,也会显示相同的曲线。
因此,我的问题(假设每次训练最多 50000 个样本):
- 为什么 -n
没有为一个 class 训练过程做任何改变?
- 我需要为 class 支持向量机更改哪些参数?
- 线性内核是最好的方法吗? (+ 关于运行时)和 rbf 内核参数网格搜索需要很长时间才能处理如此大的数据集
- 没有使用 liblinear,因为我想进行异常检测 = one class svm
此致, 多重
性能影响是您的巨大特征 space 的 16777216 个元素的结果。这会导致德语句子等元素的向量非常稀疏。
Yang & Petersen 的一项研究 A Comparative Study on Feature Selection in Text Categorization 表明,激进 feature-selection 不一定会降低分类准确性。我在对(医学)德语文本文档进行文本分类时取得了类似的结果。
如评论中所述,LIBLINEAR
很快,因为它是为此类稀疏数据构建的。然而,您最终得到的是一个线性分类器,它有所有的缺陷和好处。
我建议采用以下策略:
使用
N
的剩余 feature-space 执行积极的特征选择(例如使用 InformationGain)
结合 cross-validation 逐步增加
N
并为您的数据找到 最佳 加工N
。使用 2.
中的 使用 3. 中找到的最佳匹配参数和 2.
中找到的
N
寻找 grid-search
N
训练您的分类器