我正在尝试使用人们看到横幅广告后的点击和转化数据来训练我的SVM算法。主要问题是点击数据仅占所有数据的0.2%,因此存在很大的不平衡。在测试阶段使用简单的SVM时,它总是预测为“查看”类,而从不预测为“点击”或“转化”。平均来说,它给出的正确答案有99.8%(因为数据不平衡),但如果检查“点击”或“转化”类别,正确预测率为0%。如何调整SVM算法(或选择其他算法)来考虑这种不平衡情况?
回答:
最基本的方法是使用所谓的“类别加权方案” – 在经典的SVM公式中,有一个C
参数用于控制误分类数量。它可以被调整为C1
和C2
参数,分别用于类别1和类别2。对于给定的C
,C1
和C2
最常见的选择是设置为
C1 = C / n1C2 = C / n2
其中n1
和n2
分别是类别1和类别2的大小。因此,你对SVM误分类较少出现的类别进行更严厉的“惩罚”,而对最常见的类别误分类则较为宽松。
许多现有的库(如libSVM)通过class_weight
参数支持这种机制。
示例使用Python和sklearn
print __doc__import numpy as npimport pylab as plfrom sklearn import svm# we create 40 separable pointsrng = np.random.RandomState(0)n_samples_1 = 1000n_samples_2 = 100X = np.r_[1.5 * rng.randn(n_samples_1, 2), 0.5 * rng.randn(n_samples_2, 2) + [2, 2]]y = [0] * (n_samples_1) + [1] * (n_samples_2)# fit the model and get the separating hyperplaneclf = svm.SVC(kernel='linear', C=1.0)clf.fit(X, y)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 classeswclf = svm.SVC(kernel='linear', class_weight={1: 10})wclf.fit(X, y)ww = wclf.coef_[0]wa = -ww[0] / ww[1]wyy = wa * xx - wclf.intercept_[0] / ww[1]# plot separating hyperplanes and samplesh0 = pl.plot(xx, yy, 'k-', label='no weights')h1 = pl.plot(xx, wyy, 'k--', label='with weights')pl.scatter(X[:, 0], X[:, 1], c=y, cmap=pl.cm.Paired)pl.legend()pl.axis('tight')pl.show()
特别是在sklearn中,你可以通过设置class_weight='auto'
来简单地开启自动加权功能。