python - 从 SVM 获得的平均线性分离器
问题描述
出于研究目的,我发现自己需要在大型 DS(即大量示例)上通过 SGD 训练 SVM。这使得使用 scikit-learn 的实现 ( SGDClassifier
) 存在问题,因为它需要一次加载整个 DS。
我熟悉的算法使用 SGD 的 n 步来获得 n 个不同的分离器w_i
,然后对它们进行平均(具体可以在https://www.cse.huji.ac.il/~shais/Lectures2014/lecture8的幻灯片 12 中看到.pdf)。
这让我觉得也许我可以使用 scikit-learn 来训练多个这样的分类器,然后取得到的线性分离器的平均值(假设没有偏差)。
这是一个合理的思路,还是 scikit-learn 的实现不属于我的逻辑?
编辑:我很清楚以不同方式训练 SVM 的替代方法,但这是出于特定的研究目的。我只想知道这种思路是否可以通过 scikit-learn 的实现实现,或者您是否知道另一种方法可以让我使用 SGD 训练 SVM,而无需将整个 DS 加载到内存中。
解决方案
SGDClassifier
有一种partial_fit
方法,方法的主要目标之一partial_fit
是将 sklearn 模型扩展到大规模数据集。使用它,您可以将数据集的一部分加载到 RAM 中,将其提供给 SGD,并不断重复此操作,除非使用完整的数据集。
在下面的代码中,我KFold
主要用于模拟加载数据集块。
class GD_SVM(BaseEstimator, ClassifierMixin):
def __init__(self):
self.sgd = SGDClassifier(loss='hinge',random_state=42,fit_intercept=True,l1_ratio=0,tol=.001)
def fit(self,X,y):
cv = KFold(n_splits=10,random_state=42,shuffle=True)
for _,test_id in cv.split(X,y):
xt,yt = X[test_id],y[test_id]
self.sgd = self.sgd.partial_fit(xt,yt,classes=np.unique(y))
def predict(self,X):
return self.sgd.predict(X)
要针对常规(线性)SVM 进行测试:
X,y = load_breast_cancer(return_X_y=True)
X = StandardScaler().fit_transform(X) #For simplicity, Pipeline is better choice
cv = RepeatedStratifiedKFold(n_splits=5,n_repeats=5,random_state=43)
sgd = GD_SVM()
svm = LinearSVC(loss='hinge',max_iter=1,random_state=42,
C=1.0,fit_intercept=True,tol=.001)
r = cross_val_score(sgd,X,y,cv=cv) #cross_val_score(svm,X,y,cv=cv)
print(r.mean())
这返回了 95% 以上的准确率GD_SVM
和 96% 的SVM
. 在 Digits 数据集中SVM
有 93% 的准确率,而GD_SVM
有 91%。虽然这些性能大致相似,但正如这些测量结果所示,请注意它们并不相同。这是意料之中的,因为这些算法使用完全不同的优化算法,但我认为仔细调整超参数会缩小差距。
推荐阅读
- javascript - Sequelise:多对多表(CROSS TABLE)关联到其他表
- javascript - Express:来自 vue.js 的图像未重定向到后端
- c - 是否有可能像我们在 printf() 中一样在字符串中写入单词并同时使用 ate %s?
- gnuplot - Gnuplot:将 ytics 缩放到一定范围
- laravel - 如何使用惯性 js 和 spatie 媒体库获取图像
- python - 你能在解决问题或绕过这个问题之前对纸浆变量进行四舍五入吗?
- apache-flink - Apache Flink 水印策略
- pyqt - 全局和本地 PyQt5 样式表
- python - Blender 2.92 Python 使用 IntProperties 崩溃插件
- java - synchronizedList.toCollections 是否需要同步?