如何让OneClassSVM生成的Contour Plot为单条连续轮廓线?
异常值检测中OneClassSVM轮廓线不连续问题
我使用OneClassSVM进行异常值检测,期望绘制出覆盖非异常值区域的连续轮廓线,但当前得到的是两条孤立的轮廓线,需要实现无论形状如何都能生成单条连续轮廓线的效果。
代码实现
import numpy as np from sklearn.svm import OneClassSVM import matplotlib.pyplot as plt ss = [[9.0, 1.0],[1.78, 2.14],[7.36, 2.67],[5.95, 2.5 ],[2.59, 2.87],[1.76, 2.45],[1.87, 2.45],[2.15, 2.61],[1.64, 2.17],[1.35, 2.27], [2.16, 2.3 ],[1.48, 2.32],[1.73, 2.41],[1.73, 2.39],[3.87, 1.38],[1.81, 2.7 ],[1.92, 2.72],[1.57, 2.62],[1.59, 2.48],[3.1 , 2.56]] ssa = np.asarray(ss) X1 = ssa # 学习异常值检测的决策边界 xx1, yy1 = np.meshgrid(np.linspace(0, 10, 500), np.linspace(0, 6, 500)) model_1 = OneClassSVM(nu=0.25, gamma=0.35) model_1.fit(X1) Z1 = model_1.decision_function(np.c_[xx1.ravel(), yy1.ravel()]) Z1 = Z1.reshape(xx1.shape) plt.figure(1) plt.contour(xx1, yy1, Z1, levels=[0], linewidths=2, colors='r') plt.scatter(X1[:, 0], X1[:, 1], color="black") plt.show()
当前效果

期望效果

解决方案
原因分析
出现两条孤立轮廓线,是因为gamma=0.35和nu=0.25的参数组合让OneClassSVM学习到了两个分离的非异常值区域。可以通过调整模型参数或后处理决策结果来解决。
方法1:调整模型参数
降低gamma值(让模型决策边界更平滑),同时调整nu(控制模型允许的异常值比例),让模型学习到连续的决策区域。
修改模型初始化代码:
model_1 = OneClassSVM(nu=0.1, gamma=0.1)
调整后模型的决策边界会更平滑,大概率生成连续的轮廓线。
方法2:后处理决策结果(强制合并区域)
如果不想调整模型参数,可以先填充所有非异常值区域(Z1 > 0的区域),再提取该区域的外轮廓,这样无论内部区域是否分离,最终只会显示一条连续的外轮廓线。
修改绘制部分的代码:
plt.figure(1) # 填充非异常值区域(透明填充,仅用于提取轮廓) plt.contourf(xx1, yy1, Z1 > 0, levels=[0, 1], colors='none') # 提取填充区域的外轮廓线 contours = plt.contour(xx1, yy1, Z1 > 0, levels=[1], linewidths=2, colors='r') plt.scatter(X1[:, 0], X1[:, 1], color="black") plt.show()
内容的提问来源于stack exchange,提问作者Efrain
相关产品推荐
相关产品推荐

