支持向量机异常检测

机器学习领域,异常检测是一种重要的任务,它可以帮助识别出不符合预期模式的数据点。支持向量机(SVM)是一种常用的分类算法,它也可以被用来进行异常检测。在某些情况下,可能需要处理非线性可分的数据,这时候可以使用核技巧来扩展SVM的能力。

在这篇文章中,将探讨如何使用基于径向基函数(RBF)核的OneClassSVM和基于随机梯度下降(SGD)的SGDOneClassSVM来进行异常检测。首先,使用核近似方法来应用SGDOneClassSVM,这是一种在线性SVM上使用SGD的版本。值得注意的是,SGDOneClassSVM的计算复杂度与样本数量线性相关,而核化的OneClassSVM的复杂度至多为样本数量的二次方。本例的目的不是为了展示这种近似在计算时间上的好处,而是为了展示在一个小规模数据集上可以得到相似的结果。

首先需要生成一些训练数据和测试数据,包括一些正常的新观测值和一些异常的新观测值。然后,使用OneClassSVM的超参数来拟合模型,并预测训练数据、测试数据和异常数据的标签。通过比较预测结果,可以评估模型在训练集和新观测值上的表现。

在下面的代码示例中,首先设置了一些基本的参数,包括随机状态和字体大小。然后,生成了训练数据和测试数据,并使用OneClassSVM和SGDOneClassSVM分别进行训练和预测。还使用了决策边界显示工具来可视化模型的决策边界。最后,展示了模型在训练集和新观测值上的错误率。

import matplotlib.pyplot as plt import numpy as np from sklearn.kernel_approximation import Nystroem from sklearn.linear_model import SGDOneClassSVM from sklearn.pipeline import make_pipeline from sklearn.svm import OneClassSVM # 设置字体大小 font = {"weight": "normal", "size": 15} matplotlib.rc("font", **font) # 设置随机状态 random_state = 42 rng = np.random.RandomState(random_state) # 生成训练数据 X = 0.3 * rng.randn(500, 2) X_train = np.r_[X + 2, X - 2] # 生成一些正常的新观测值 X = 0.3 * rng.randn(20, 2) X_test = np.r_[X + 2, X - 2] # 生成一些异常的新观测值 X_outliers = rng.uniform(low=-4, high=4, size=(20, 2)) # OneClass SVM超参数 nu = 0.05 gamma = 2.0 # 拟合One-Class SVM clf = OneClassSVM(gamma=gamma, kernel="rbf", nu=nu) clf.fit(X_train) y_pred_train = clf.predict(X_train) y_pred_test = clf.predict(X_test) y_pred_outliers = clf.predict(X_outliers) # 使用核近似和SGD拟合One-Class SVM transform = Nystroem(gamma=gamma, random_state=random_state) clf_sgd = SGDOneClassSVM(nu=nu, shuffle=True, fit_intercept=True, random_state=random_state, tol=1e-4) pipe_sgd = make_pipeline(transform, clf_sgd) pipe_sgd.fit(X_train) y_pred_train_sgd = pipe_sgd.predict(X_train) y_pred_test_sgd = pipe_sgd.predict(X_test) y_pred_outliers_sgd = pipe_sgd.predict(X_outliers) # 可视化决策边界 from sklearn.inspection import DecisionBoundaryDisplay fig, ax = plt.subplots(figsize=(9, 6)) xx, yy = np.meshgrid(np.linspace(-4.5, 4.5, 50), np.linspace(-4.5, 4.5, 50)) X = np.concatenate([xx.ravel().reshape(-1, 1), yy.ravel().reshape(-1, 1)], axis=1) DecisionBoundaryDisplay.from_estimator(clf, X, response_method="decision_function", plot_method="contourf", ax=ax, cmap="PuBu") DecisionBoundaryDisplay.from_estimator(clf, X, response_method="decision_function", plot_method="contour", ax=ax, linewidths=2, colors="darkred", levels=[0]) DecisionBoundaryDisplay.from_estimator(clf, X, response_method="decision_function", plot_method="contourf", ax=ax, colors="palevioletred", levels=[0, clf.decision_function(X).max()]) # 绘制数据点 s = 20 b1 = plt.scatter(X_train[:, 0], X_train[:, 1], c="white", s=s, edgecolors="k") b2 = plt.scatter(X_test[:, 0], X_test[:, 1], c="blueviolet", s=s, edgecolors="k") c = plt.scatter(X_outliers[:, 0], X_outliers[:, 1], c="gold", s=s, edgecolors="k") # 设置图表标题和标签 ax.set(title="One-Class SVM", xlim=(-4.5, 4.5), ylim=(-4.5, 4.5), xlabel=(f"error train: {y_pred_train[y_pred_train==-1].size} / {X_train.shape[0]}; " f"errors novel regular: {y_pred_test[y_pred_test==-1].size} / {X_test.shape[0]}; " f"errors novel abnormal: {y_pred_outliers[y_pred_outliers==1].size} / {X_outliers.shape[0]}"),) # 显示图例 fig.legend([mlines.Line2D([], [], color="darkred", label="learned frontier"), b1, b2, c], ["learned frontier", "training observations", "new regular observations", "new abnormal observations"], loc="upper left") plt.show()

通过上述代码,可以看到OneClassSVM和SGDOneClassSVM在异常检测任务上的表现。首先生成了训练数据和测试数据,然后使用OneClassSVM和SGDOneClassSVM进行训练和预测。还可视化了模型的决策边界,以便更好地理解模型是如何区分正常数据和异常数据的。最后,展示了模型在训练集和新观测值上的错误率,以评估模型的性能。

总的来说,使用支持向量机进行异常检测是一种有效的方法。通过选择合适的核函数和超参数,可以在各种数据集上获得良好的性能。此外,使用核近似和随机梯度下降的方法可以进一步提高模型的计算效率,使其适用于大规模数据集。

在实际应用中,可以根据具体问题选择合适的异常检测算法。对于线性可分的数据,可以使用线性SVM进行异常检测;对于非线性可分的数据,可以使用基于核技巧的SVM进行异常检测。此外,还可以尝试使用其他异常检测算法,如局部异常因子(LOF)和隔离森林等,以获得更好的性能。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485