K-临近算法介绍和实践
来源:互联网 发布:小幽灵网络技术论坛 编辑:程序博客网 时间:2024/06/08 18:53
K-临近算法概述
KNN算法(K-Nearest Neighbors)算法是机器学习领域广泛使用的分类算法之一,所谓KNN,说的就是每个样本的分类都可以用它最接近的K个邻居来代表。
KNN算法的基本思路是:
1、给定一个训练集数据,每个训练集数据都是已经分好类的。
2、设定一个初始的测试数据a,计算a到训练集所有数据的欧几里得距离,并排序。
3、选出训练集中离a距离最近的K个训练集数据。
4、比较k个训练集数据,选出里面出现最多的分类类型,此分类类型即为最终测试数据a的分类。
Python中的KNN相关API
在python中,我们可以很容易使用sklearn中的neighbors module来创建我们的KNN模型。
在API文档中,neighbors模块中的方法如下:
接下来我们用一个简单的例子只管阐述一下KNN算法的实现。
K临近算法的hello world
首先我们要创建二维空间上的一些点用于我们测试:
from sklearn.neighbors import NearestNeighborsimport numpy as npX = np.array([[-1, -1], [-2, -1], [-3, -2], [1, 1], [2, 1], [3, 2]])
由以上代码可以看到,我们在二维空间中创建了6个测试点用于我们的实验,接下来我们便是要使用KNN算法,训练出一个合适我们这六个点的一个分类模型。
#NearestNeighbors用到的参数解释 #n_neighbors=5,默认值为5,表示查询k个最近邻的数目 #algorithm='auto',指定用于计算最近邻的算法,auto表示试图采用最适合的算法计算最近邻 #fit(X)表示用X来训练算法 nbrs = NearestNeighbors(n_neighbors=2, algorithm="ball_tree").fit(X)
这样,我们最简单的一个KNN的分类器就完成了,接下来看看效果。
#返回的indices是距离该点较近的k个点的下标,distance则是距离distances, indices = nbrs.kneighbors(X)
结果如下图所示:
第一个矩阵是distances矩阵,第二个则表示k个距离该点较近的点的坐标。
还可以输入以下代码可视化结果:
#输出的是求解n个最近邻点后的矩阵图,1表示是最近点,0表示不是最近点 print nbrs.kneighbors_graph(X).toarray()
使用KNN算法用于监督学习的时候也是非常简单的:
如下图所示:
使用K近邻算法检测异常操作
在黑客入侵Web服务器之后,通常会使用一些系统漏洞进行提权,获得服务器的root权限,在接下来的工作中,我们通过搜集Linux服务器的bash操作日志,通过训练识别出特定用户的使用习惯,然后进一步识别出异常操作。
数据情况大概如下:
训练数据中包含50个用户的操作日志,每个日志包含了15000条操作命令,其中前5000条为正常操作,后面10000条随机包含有异常操作。为了方便训练,我们将100个命令视为一个操作序列,在label.txt中是对应每个用户的后100个操作序列中是否异常的标签。正常为0,异常为1。
源码如下:
# -*- coding:utf-8 -*-import sysimport urllibimport refrom hmmlearn import hmmimport numpy as npfrom sklearn.externals import joblibimport nltkimport matplotlib.pyplot as pltfrom nltk.probability import FreqDistfrom sklearn.feature_extraction.text import CountVectorizerfrom sklearn.neighbors import KNeighborsClassifierfrom sklearn.metrics import classification_reportfrom sklearn import metrics#测试样本数N=90def load_user_cmd(filename): cmd_list=[] dist_max=[] dist_min=[] dist=[] with open(filename) as f: i=0 x=[] for line in f: line=line.strip('\n') x.append(line) dist.append(line) i+=1 #每100条命令组成一个操作序列 if i == 100: cmd_list.append(x) x=[] i=0 #统计最频繁使用的前50个命令和最少使用的50个命令 fdist =list(FreqDist(dist).keys()) dist_max=set(fdist[0:50]) dist_min = set(fdist[-50:]) return cmd_list,dist_max,dist_min#特征化用户使用习惯def get_user_cmd_feature(user_cmd_list,dist_max,dist_min): user_cmd_feature=[] for cmd_block in user_cmd_list: #以100个命令为统计单元,作为一个操作序列,去重后的操作命令个数作为特征 #将list转为set去重 f1=len(set(cmd_block)) #FreqDist转为统计字典转化为命令:出现次数的形式 fdist = list(FreqDist(cmd_block).keys()) #最频繁使用的10个命令 f2=fdist[0:10] #最少使用的10个命令 f3 = fdist[-10:] f2 = len(set(f2) & set(dist_max)) f3 = len(set(f3) & set(dist_min)) #返回该统计单元中和总的统计的最频繁使用的前50个命令和最不常使用的50个命令的重合程度 #f1:统计单元中出现的命令类型数量 #f2:统计单元中最常使用的10个命令和总的最常使用的命令的重合程度 #f3:统计单元中最不常使用的10个命令和总的最不常使用的命令的重合程度 x=[f1,f2,f3] user_cmd_feature.append(x) return user_cmd_featuredef get_label(filename,index=0): x=[] with open(filename) as f: for line in f: line=line.strip('\n') x.append( int(line.split()[index])) return xif __name__ == '__main__': user_cmd_list,user_cmd_dist_max,user_cmd_dist_min=load_user_cmd("../data/MasqueradeDat/User3") user_cmd_feature=get_user_cmd_feature(user_cmd_list,user_cmd_dist_max,user_cmd_dist_min) #index=2 即为User3对应的label labels=get_label("../data/MasqueradeDat/label.txt",2) #前5000个记录为正常操作 即前50个序列为正常操作 y=[0]*50+labels x_train=user_cmd_feature[0:N] y_train=y[0:N] x_test=user_cmd_feature[N:150] y_test=y[N:150] neigh = KNeighborsClassifier(n_neighbors=3) neigh.fit(x_train, y_train) y_predict=neigh.predict(x_test) score=np.mean(y_test==y_predict)*100 print(y_test) print(y_predict) print(score) print(classification_report(y_test, y_predict)) print(metrics.confusion_matrix(y_test, y_predict))
运行一下,可以看到准确率约为83.3%,结果不是很理想。
如果我们想提高我们的验证效果,我们需要更加全盘考虑异常操作的出现。因此接下来,我们使用全量比较,来重新对用户的是否异常进行训练。
在数据搜集和清洗的时候,我们使用dict数据结构,将全部命令去重之后形成一个大型的向量空间,每个命令代表一个特征,首先通过遍历全部命令生成对应的词集。因此我们重写load_user_cmd方法,如下:
def load_user_cmd_new(filename): cmd_list=[] dist=[] with open(filename) as f: i=0 x=[] for line in f: line=line.strip('\n') x.append(line) dist.append(line) i+=1 if i == 100: cmd_list.append(x) x=[] i=0 fdist = list(FreqDist(dist).keys()) return cmd_list,fdist
得到词集之后,将命令向量化,方便模型的训练。因此再重写get_user_feature方法,重新获取用户特征。
def get_user_cmd_feature_new(user_cmd_list,dist): user_cmd_feature=[] for cmd_list in user_cmd_list: v=[0]*len(dist) for i in range(0,len(dist)): if dist[i] in cmd_list: v[i]+=1 user_cmd_feature.append(v) return user_cmd_feature
训练新模型和之前的方法一样。
效果验证的时候,使用交叉验证,通过十次随机取样和验证,提高验证的可信度:
score=cross_val_score(neigh,user_cmd_feature,y,n_jobs = -1,cv=10)
最后可以得到一个准确率约在93%左右的较好的模型。
除了以上的几个例子,使用KNN来进行webshell检测和rootkit检测的例子可以参考https://github.com/traviszeng/MLWithWebSecurity/tree/master/code/KNNsample
- K-临近算法介绍和实践
- K-means算法和K临近算法
- K临近算法
- k-临近算法
- k-临近算法
- opencv K临近算法(knearest)
- k临近算法(k nearest neighbors)
- K临近算法k-Nearest Neighbor algorithm
- python机器学习k临近算法
- k-means算法简介和基础实践
- 聚类算法——K临近(KNN)
- 机器学习实战(python)一 k临近算法。
- 机器学习实战:k-临近算法(一)
- 机器学习实战:k-临近算法(二)
- KNN(K最临近算法)的python实现
- K-近邻算法实践
- 机器学习与python实践(一)k临近(knn)
- KNN-临近算法
- mongodb及可视化工具
- java线程基础知识
- Laravel入门教程(二)A
- STM32 USB Audio 音量调节修改
- Spring框架由ConditionalOnMissingBean注解引发的问题
- K-临近算法介绍和实践
- duilib在点击关闭按钮调用CoUninitialize在WIN10下出现异常
- 面试中的那些 Git 问题
- Android 蓝牙扫描枪连接状态变化(连接、断开)界面实屏幕会实时刷新重构一次
- centos07 关闭防火墙指令
- div显示关闭图标
- Kubernetes(K8S)集群管理Docker容器(部署篇)
- Servlet的doGet 和doPost方法的区别
- jbpm基础知识