利用one-class SVM进行异常值检测

时间:2024-04-05 07:18:11

python数据分析与数据化运营      宋天龙  

 sklearn中提供了one-class SVM和EllipticEnvelope两种方法用于异常检测,前者基于libsvm实现的非监督式异常检测方法,可用于做高维度分布的评估;后者只能做基于高斯分布数据集的异常检测。

本节示例模拟的是针对一批没有任何标签的原始数据做异常检测模型训练,然后通过新的测试集来发现新数据集中的异常数据。

 图形中的红色点代表异常点,绿色点代表正常点。该图形在python中可直接通过鼠标拖拽以显示不同3D视角下的数据分布,这在某些区域的点比较集中时非常有用。

 

 

利用one-class SVM进行异常值检测

     

 

# 通过Numpy的loadtxt读取数据文件;
# ·对矩阵做切片操作;
# ·使用sklearn.svm中的OneClassSVM方法实现异常检测分析,并使用
# fit方法针对训练集,使用predict方法针对测试集应用;
# ·使用Numpy的hstack方法将矩阵按列合并,得到新的矩阵;
# ·通过对矩阵中特定列的值进行判断,直接选择或切分数据集;
# ·通过shape方法获得矩阵的形状;
# ·通过print方法结合str.format做格式化的输出;
# ·通过plt.style.use方法使用Matplotlib的预定义库样式;
# ·通过mpl_toolkits.mplot3d的Axes3D方法做3D类型图像转换;
# ·通过matplotlib.pyplot的scatter方法画散点图,并通过展示图形,设
# 置不同的展示样式,包括颜色、样式、图例等,针对并隐藏坐标轴标 签、设置图例和标签、设置标题等。
import matplotlib
matplotlib.use('TkAgg')
# 导入库
from sklearn.svm import OneClassSVM # 导入OneClassSVM
import numpy as np # 导入numpy库
import matplotlib.pyplot as plt # 导入Matplotlib
from mpl_toolkits.mplot3d import Axes3D # 导入3D样式库
# 数据准备
raw_data = np.loadtxt('outlier.txt', delimiter=' ') # 读取数据
train_set = raw_data[:900, :] # 训练集
test_set = raw_data[:100, :] # 测试集
# 异常数据检测
model_onecalsssvm = OneClassSVM(nu=0.1, kernel="rbf", random_state=0) # 创建异常检测算法模型对象
model_onecalsssvm.fit(train_set) # 训练模型
pre_test_outliers = model_onecalsssvm.predict(test_set) # 异常检测
# 异常结果统计
toal_test_data = np.hstack((test_set, pre_test_outliers.reshape(test_set.shape[0], 1))) # 将测试集和检测结果合并
normal_test_data = toal_test_data[toal_test_data[:, -1] == 1] # 获得异常检测结果中集
outlier_test_data = toal_test_data[toal_test_data[:, -1] == -1] # 获得异常检测结果异常数据
n_test_outliers = outlier_test_data.shape[1] # 获得异常的结果数量
total_count_test = toal_test_data.shape[0] # 获得测试集样本量
print ('outliers: {0}/{1}'.format(n_test_outliers, total_count_test)) # 输出异常的结果数量
print ('{:*^60}'.format(' all result data (limit 5) ')) # 打印标题
print (toal_test_data[:5]) # 打印输出前5条合并后的数据集
# 异常检测结果展示
plt.style.use('ggplot') # 使用ggplot样式库
fig = plt.figure() # 创建画布对象
ax = Axes3D(fig) # 将画布转换为3D类型
s1 = ax.scatter(normal_test_data[:, 0], normal_test_data[:, 1], normal_test_data[:, 2], s=100, edgecolors='k', c='g',
marker='o') # 画出正常样本点
s2 = ax.scatter(outlier_test_data[:, 0], outlier_test_data[:, 1], outlier_test_data[:, 2], s=100, edgecolors='k', c='r',
marker='o') # 画出异常样本点
ax.w_xaxis.set_ticklabels([]) # 隐藏x轴标签,只保留刻度线
ax.w_yaxis.set_ticklabels([]) # 隐藏y轴标签,只保留刻度线
ax.w_zaxis.set_ticklabels([]) # 隐藏z轴标签,只保留刻度线
ax.legend([s1, s2], ['normal points', 'outliers'], loc=0) # 设置两类样本点的图例
plt.title('novelty detection') # 设置图像标题
plt.show