一种自动分类数据方法_初探索

知识分享文档, 已替换一些可能敏感的内容

1. 本文由来

当前的防御系统, 已经存储了一定量的基本数据(例如数据a,数据c, 数据c等), 如何利用这些数据,判断不同账户是否正常,是防御的一个重点工作。 本文记录雷健辉的一个探索过程。

2.  首次判断方法

先来看看我们手头上有什么数据(一下数据由等级xx工具统计并生成):

其中:

d – 数据a

s – 数据b

b – 数据c

bt – 数据d

abn – 数据e

spm – 数据f

times – 数据g

用人肉判断以上数据: 初步发现, 账号是否作弊与【数据b】【数据a】两个数据关系密切。先看组成的二维图:

横坐标是【数据a】 , 纵坐标是【数据b】。

从正常的用户来看, 【数据a】应该是大于【数据b】的。通讯一般是熟人之间发生嘛, 有来必有回。

从上图分析可以得出一些简单 结论:

  1. 【数据b】过大不正常
  2. 【数据b】远大于【数据a】大概率不正常
  3. 【数据a】远大于【数据b】是大概率正常用户

根据上面的结论形成规则: 以【数据b】/ 【数据a】 = 1为分割线

如上图

线1表示 斜率 = 1

线2表示 斜率= 0.5

线3表示 斜率= 2

线4表示 【数据b】大于600

线5表示 【数据a】大于320

得出上面的区域

【红色】【蓝色】区域账号拉黑

【绿色】区域账号为优质

剩下【白色】区域账号为普通

判断方法已确定, 函数已写好, 太好了! 应该可以一劳永逸的解决账号判断问题了吧, 可实际的效果如何呢?

3.  一刀切的效果

令人遗憾的是, 如上面一刀切法的效果并不好。 不同范围的斜率如何确定?【数据b】的阀值如何确定? 数值定大了, 拦截效果不好; 数值定小了, 产生大量的误判。此外, 人肉确定数值的另一个副作用是, 需要人肉观察拦截效果, 不断调整阀值, 人力成本骤增。

换个角度, 让我们从代码的层面看看, 实现上面判断逻辑的代码是什么样子的:

            // 1. xx用户:xxx调成3
            // 数据b 非0, 数据b小于350,
            // 比例大于 0.5 的, 

            // 2. 下调的: xxx调成1
            // 数据b 大于600
            // 数据a 大于550
            // 比例大于2 拉黑

            // 比例在2 - 0.5 之间的, 定为2

            if (b_trust >= 500)
            {
                temp_priority = low_priority;
            }
            else if (s_d_rate <= 0.5 && s_d_rate > 0 &&double_trust < 350)
            {
                temp_priority = high_priority;
            }
            else if (s_d_rate >= 2 )
            {
                // 补充规则:
                if (s_d_rate <= 5 && times  <= 10)
                {
                    temp_priority = middle_priority;
                }
                else
                {
                    temp_priority = low_priority;
                }
            }
            else
            {
                temp_priority = middle_priority;
            }

如上图, 针对两维的数据(【数据b】,【数据a】), 代码尚算可读, 可是由于防御效果不好, 不得不加入次数(times)协同判断的“补充规则”。 想象一下,如果针对3维, 4维, 或者更高N维的数据, 要写多少个if else嵌套才能判断得清楚? 要定多少个magic number来做边界值? 即使是能写出这样的判断函数, 假如攻击方的行为有变化, 规则需要随之修改,此代码维护的成本也必定是灾难性的(谁能看得懂)。

4.  机器代替人肉

重复的东西就应该交给机器去做。 换个角度思考, 能否让机器帮我们设计判断规则, 机器帮我们确定magic number, 而我们只做监工的角色?

带着这个想法, 我做了以下尝试:

5.  收集数据

原始数据我们已经拥有, 要想让机器训练数据, 首先得有训练用的数据集。 要得到一组带有标签(是否攻击账号), 我选取的Pycluster(python的一个聚类库)来帮我做聚类,因为我不想在数千条乃至数万条数据中,人肉判断然后打标签。 通过同样的原始数据(输入【数据b】【数据a】【数据c】【数据d】 4维数据),聚类出的效果如下图:

位于左中的【浅蓝】【蓝】点, 和右上的【红】点,是攻击账户的高危地带, 需要我重点筛查。而其余颜色的账户正常度就比较高了(也并非完全没有)。

聚类+手动筛查后,得到带有标签的训练数据集:

最后一位数字: 0表示攻击账户, 1表示正常账户。

倒数第二位数字: 0-9, 表示Pycluster聚类后的分类标签。

6.  开始训练

以上共1932条打好标签的账号数据。 我们希望验证一下训练预测模型的准确性。还需完成以下步骤:

随机乱序1932条数据; 抽取前200条作为测试数据(test_data); 剩余的数据(1732条)作为训练数据(train_data)。

为了生成可预测新数据的判断器, 我选用的是sklearn(python的一个机器学习库),并用其中自带的【朴素贝叶斯分类器naive_Bayes】进行分类(里面还有很多其他的分类器, 由于时间关系, 我只测试了naive_bayes)。

代码如下:

重点看两个箭头所指, 由train_clf函数训练1732条数据(train_data)后生成的 clf 就是一个判断器。 pred 就是 clf 针对测试数据(test_data)做出的预测。

运行后得出,预测准确率为:95.4%

7.  初次训练后的思考

针对95.4% 这个数字, 基本符合预期, 但是我个人认为, 这个准确率还达不到放心使用的标准的(至少需要99.9%? 几个9?)。

总结了以下几点, 有助于进一步提高准确率:

  1. 原始数据可进一步优化。

a)         例如数据由于某些因素, 可能不够准确。

  1. 拓展数据维度。

a)         现在的数据维度是不够的, 明显例子是, 部分攻击者, 和正常的某种行为的账号行为非常相似, 这样会让训练器难以判断。

  1. 训练模型的度量。

a)         现在只用了naive_bayes一种训练模型, 剩余的模型还有很多, 如何确定训练变量, 如何衡量不同模型的训练预测效果, 如何判断训练器是否【过拟合】或【欠拟合】, 都是进一步需要研究的领域。

8.  总结

对于机器训练数据, 好处是显而易见的。 我们要做的工作, 从人肉定规则变成为: begin ->收集数据-> 设置标签 ->训练数据(调优训练模型, 完善基础数据)-> 实际使用 -> end -> 定期重新训练新数据集, 防止模型过期 -> begin。 我们的角色也真正变成一个监工, 避免重复劳作, 从而提高生产力。

时间: 2024-10-08 10:14:32

一种自动分类数据方法_初探索的相关文章

shell脚本中8种字符串截取方法_转自脚本之家

转自:http://www.jb51.net/article/56563.htm Linux 的字符串截取很有用.有八种方法. 假设有变量 var=http://www.aaa.com/123.htm. 1. # 号截取,删除左边字符,保留右边字符. echo ${var#*//} 其中 var 是变量名,# 号是运算符,*// 表示从左边开始删除第一个 // 号及左边的所有字符即删除 http://结果是 :www.aaa.com/123.htm 2. ## 号截取,删除左边字符,保留右边字符

几种遍历数据方法及性能

forEach() 数组中的每个元素都会通过forEach进行一些改变,会改变原数组. peoples.forEach(function (people) {  people.doSomething();}); map() 数组中的元素通过map进行一些改变后返回一个新数组,新数组中的元素都是原数组中的元素doSomething()后的结果,元素顺序一一对应.(return是必须的) var newPeoples = peoples.map(function (people) {  return

ZZUOJ 1199 大小关系(拓扑排序,两种方法_判断入度和dfs回路判断)

1 /* 2 这道题如果按照度为0的节点来判断的时候,将度为0的节点和其相连的节点(度数并减去1) 3 从图中去掉,如果度为0的节点的个数为0个但是图中的节点没有都去掉的 时候那么说明 4 出现了回路!用这种方法必须将重边去除掉! 5 6 所以推荐用dfs方式进行判断!这种方式还是比较直观的! 7 */ 8 #include<iostream> 9 #include<cstring> 10 #include<cstdio> 11 #include<algorith

web三种跨域请求数据方法

web三种跨域请求数据方法 以下测试代码使用php,浏览器测试使用IE9,chrome,firefox,safari <!DOCTYPE HTML> <html> <head> <meta charset="UTF-8"> <script type="text/javascript" src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.7.2.min.

IOS数据解析_使用GDataXML解析,多层结构,相同目录的方法

项目例子(包含GDataXML框架) http://download.csdn.net/detail/u013686641/7672689 /*说明 将GDataXML引入你的项目 加入libxml2框架 导入#import "GDataXMLNode.h" 在TARGETS 接下来再进入Build Settings,在搜索框中搜索header search paths,添加/usr/include/libxml2 然后搜索Other linker flags,同样的方式添加-lxml

数据在线服务的一些探索经验

本文聊下提供数据在线的一些经验 典型场景:数据组的同学每天凌晨在Hive上基于历史数据计算用户行为数据,通过工具将该数据推送到HBase,业务方通过RPC Service获取用户行为数据 整体架构 调度:启动计算/传输任务 监控:监控任务运行(可视化界面),异常报警 质量:对核心数据质做质量检查 传输:将数据从HDFS/HIVE导入HBase/Redis/Memcache/Mysql RPC Service:通过Service获取数据 JDBC:获取Mysql中的数据 Memcache:作为HB

android数据存储_内部存储

源码下载(免下载积分):下载 你可以直接存储数据到内部存储中,默认情况下,文件存储到内部存储中是私有的,不能被 其他程序访问,当卸载应用程序,这些文件会被移除. 创建并写入数据可以有两种方法: 使用java中的相关的方法, 使用android.content中的相关方法,  调用 openFileOutput(),并返回FileOutputStream对象 调用FileOutputStream对象的write()方法 关闭流 读文件也是基本相同的方式. 在读文件有一点小技巧:如果想在编译时保存一

几种Android数据序列化方案

一.引言 数据的序列化在Android开发中占据着重要的地位,无论是在进程间通信.本地数据存储又或者是网络数据传输都离不开序列化的支持.而针对不同场景选择合适的序列化方案对于应用的性能有着极大的影响. 从广义上讲,数据序列化就是将数据结构或者是对象转换成我们可以存储或者传输的数据格式的一个过程,在序列化的过程中,数据结构或者对象将其状态信息写入到临时或者持久性的存储区中,而在对应的反序列化过程中,则可以说是生成的数据被还原成数据结构或对象的过程. 这样来说,数据序列化相当于是将我们原先的对象序列

如何增大二维码种的数据存储

最近在做项目,需求就是要传尽量多的数据,属于一个调研,估计后期会加入到项目里面,二维码其实不推荐放入大量数据,但是需求嘛,拿钱干活,可能后期还会优化,因为目前的画扫描的效率不高,主要直接用的原生的开源库zxing感觉效率不高. 一开始,从数据源下手,进行数据源压缩,首先尝试了hufman编码,huffman主要是一些开源的算法,但是实现从建树到压缩,其实有很大区别,文件我直接上传了,有兴趣的可以看一下: http://download.csdn.net/detail/shidongdong201