大家好,我是菜菜卷。
在上篇中,我们简要介绍了使用孤立森林(isolate forest
)来进行无监督异常检测,在今天的内容中,我们将使用ocsvm(One Class SVM)
来进行半监督异常检测,我们一起开始吧!~
关于数据集的介绍和数据读入方向可以参考第一篇的详细介绍:异常检测之孤立森林(isolate forest)
什么是SVM(支持向量机)
熟悉机器学习的同学肯定对svm
已经了如指掌了,下面我们就简要的说一下,SVM
的目的就是使用一条“线”将两类或者多类的数据分隔开来,使其每一侧的数据都是同一类别的,在简单的线性可分的二维平面中(如下图所示),我们可以很容易的找到一条线将两个类别的点区分开,
但是现实生活中的数据往往是多维和复杂的(线性不可分的),所以我们要找的往往是一个多维向量空间中的一个超平面,使得两类点尽可能的被划分在超平面的两侧。感兴趣的同学可以更详细的去了解一下SVM
。
而我们今天使用的ocsvm
也是svm
最基础的一个应用,其基本原理如下:其输入的数据只需要有正常数据及其标签即可,在训练过程中,ocsvm
会学习正常观测值的决策边界(svm
中划分正负样本的超平面),同时考虑一些离群值,如果奇异值(模型未见过的新数据点)落在决策边界内,则模型将其认为是正常的,反之认为其是异常的。
ocsvm
要实现的目标是:使用正常数据对模型进行训练,然后尝试在新数据中找出异常,因此ocsvm
是一种半监督的异常检测方法。
所用数据集
数据集获取地址:KDDcup99
前往以上的地址,下载kddcup.data.gz
即可。
该数据集是由若干正常和异常的数据分类,有41和特征和1个标签构成,因为后面我们只想对网页攻击方向的数据进行分析,所以要强调一下,第三个特征是表示异常的方向(即是哪种方面的异常,比如http还是其他)
项目所用环境
numpy 1.15.3
pandas 0.23.4
scikit-learn 0.19.1
matplotlib 2.2.2
大家可以使用pip或者conda自行安装项目环境,为保证顺利无bug复现结果,建议使用所示版本的包。
项目实战
1、包的导入
首先我们先导入实验所需的第三方包:
import time
import numpy as np
import pandas as pd
from sklearn.svm import OneClassSVM
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import LabelEncoder
from sklearn.metrics import roc_auc_score
其中time
可以用来记录时间和程序运行时间;numpy
可以高效做矩阵运算,在数据处理中有广泛的运用;pandas
可以快速方便的读入和处理数据的格式;sklearn
是一个非常丰富的机器学习库,内部集成了基本的机器学习方法、数据集处理方法、模型衡量指标等功能。
2、使用pandas读入和处理数据
像上篇孤立森林中的处理一样,我们使用如下代码读入数据并过滤出只和http
相关的数据(具体解读见第一篇博客的内容):
data_path = r'dataset/kddcup.data.corrected'
columns = [str(i) for i in range(1, 42)]
columns.append('label')
df = pd.read_csv(data_path, sep=',', names=columns, index_col=None)
df = df[df['3'] == 'http']
df = df.drop('3', axis=1)
columns.remove('3')
3、划分数据集
首先我们要获得用来训练模型的训练集x_train
(只包含正常数据):
normal = df[df['label'] == 'normal.']
因为我们是半监督的任务,所以也需要正常数据和异常数据混合组成的数据集(如下所示):
novelties = df[df['label'] != 'normal.']
novelties_normal = normal[: 4045]
novelties = pd.concat([novelties, novelties_normal])
我们首先通过df[df['label'] != 'normal.'