2018-02-11 21:27:05 rosetta 阅读数 1919
  • 机器学习案例实战第二课-欺诈检测

    购买课程后,可扫码进入学习群,获取唐宇迪老师答疑 使用Python数据分析流行的库Numpy,Pandas,Matplotlib, Scikit-learn结合真实数据集展开可视化特征分析与机器学习建模和评估。每次课程涉及一个完整的案例,基于案例讲解python库的使用以及如何建立机器学习模型,对涉及到的机器学习算法给出通俗易懂的解释,帮助大家掌握经典机器学习算法,并应用在实际的案例中。

    6915 人正在学习 去看看 唐宇迪

前言

接着前面三篇学习笔记《约会对象魅力程度分类》、《使用sklearn中的KNN算法》和《KNN手写识别系统》,本节记录使用K近邻算法检测异常操作,主要参考《Web安全之机器学习》 。
转载请注明出处:http://blog.csdn.net/rosetta

使用K近邻算法检测异常操作之一

实验数据及情况

实验数据在Schonlau个人网站中:http://www.schonlau.net/
Schonlau实验数据

训练数据包含50个用户的操作日志(网站上对应红框处“Masquerade Data(zip File)”)和一个标签文件label.txt(网站上对应的红框处“WIndows ascii file”)

在本机解压后是这样子的:
Schonlau数据解压后
实验数据一共收集了50个用户的操作命令(在理解代码时,只先考虑1个用户的即可),每个用户命令为15000条,前5000条是正常数据(这里隐含的一层意思是,我不需要特意指定标签了,你在代码中把我们全设置成0就可以了(本次实验就0表示正常操作;1表示异常操作)),后10000条随机包含了异常操作。

为了方便操作,会把数据集的每100个命令作为一个操作序列,所以15000条数据实际上看作150条,而前50条都是正常的,那么只有后面的100条需要标记,所以lable.txt中只有100条,而不是150条。在代码中使用KNN算法时,会把训练数据的label的前50条自动补上0,后100条从lable.txt中读取,这样就组合出了代码中实际的lable是150条的,和数据的条目能对应上了。

注意下本次实验样本数据的标签放在label.txt中,要以列方向去看,比如User1样本的标签对应第0列(因为加载到python list中是以0开始算的),User3就是第2列了。

另外在训练数据的时候,怎么把每组的100条数据清洗成易理解的数据?本实验是这么做的(针对1个用户来说):先统计15000条数据中最频繁使用的50个命令(后续称全局TOP50)和最不频繁使用的50个命令(后续称LOW50),然后统计每个100条数据中不重复命令的个数,及最频繁使用的前10个命令和是不频繁使用的10个命令,拿前10和后10分别和TOP50 LOW50取交集,生成一条数据的特征list:[无重复命令个数,和TOP50交集个数,和LOW50交集个数],生成这样的特征一共150条。

代码中的特征变量由user_cmd_feature list表示。
特征变量

并生成150条对应的lables,从下图代码可知,前50条因为都是正常数据,所以赋值为0,后100条从lable.txt中读取
代码中的标签用y表示。
前50条正常数据的标签都赋值为0

这些数据出来以后就好办了,取150条数据的前N条数据用来做训练数据,后150-N条数据做测试数据,然后和之前的学习内容都是类似的了。本实例的KNN核心代码就是如下4句。
代码中的训练数据用:x_train和y_train表示,一个是特征,另一个是特征对应的标签
测试数据用x_test和y_test表示,算法预测的结果用y_predict表示。
K近邻算法检测异常操作核心代码

注意

这个实验的结果是很坑爹的,因为通过预测的结果都是0,而用于测试的数据其标签0多,1少,所以导致后续的结果看起来正确率很高。我试了其它的几个User样本,也是类似的,没见过预测的结果中有1的情况。
即使如此,从本实验中还是学到了很多东西,比如如何从原始数据转换成KNN能理解的标量数据等。

实验代码

本代码原始文件是《Web安全之机器学习》书中的,本人加了些注释而已。

# -*- coding:utf-8 -*-

import numpy as np
from nltk.probability import FreqDist
from sklearn.neighbors import KNeighborsClassifier

from sklearn.metrics import classification_report
from sklearn import metrics

#N姑且叫做训练数据,实际上就是已知的带标签的数据条目数。
N=100

def 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
            if i == 100:
                cmd_list.append(x)
                x=[]
                i=0

    fdist = list(FreqDist(dist).keys())
    dist_max=set(fdist[0:50])
    dist_min = set(fdist[-50:])
    return cmd_list,dist_max,dist_min
#cmd_list包含150组数据,每组100个命令,所以一共是15000个命令。
#dist_max 最常用的50个命令
#dist_min 最不常用的50个命令

def get_user_cmd_feature(user_cmd_list,dist_max,dist_min):
    user_cmd_feature=[]
    for cmd_block in user_cmd_list:
        f1=len(set(cmd_block))#当前分块(100个数据中),不重要的数据个数
        fdist = list(FreqDist(cmd_block).keys())#这100个数据中频繁程度排序。FreqDist为nltk中的库,nltk是NLP(自然语言处理)工具包。
        f2=fdist[0:10]#最频繁的10个命令
        f3=fdist[-10:]#最不频繁的10个命令
        f2 = len(set(f2) & set(dist_max))#这100个命令中最频繁的10个命令和15000个命令中最频繁的前50个的交集的长。。
        f3=len(set(f3)&set(dist_min)) #这100个命令中最不频繁的10个命令和15000个命令中最不频繁的前50个的交集的长度
        x=[f1,f2,f3]
        user_cmd_feature.append(x)
    return user_cmd_feature

def 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 x

if __name__ == '__main__':
    user_cmd_list,user_cmd_dist_max,user_cmd_dist_min=load_user_cmd("./data/MasqueradeDat/User3")
    #user_cmd_list 150个大小的list,list中的每个成员又是一个存放100个字符串(linux操作命令)的list.
    #user_cmd_dist_max 15000个命令中最频繁使用的50个命令
    #user_cmd_dist_min 15000个命令中最不频繁使用的50个命令
    user_cmd_feature=get_user_cmd_feature(user_cmd_list,user_cmd_dist_max,user_cmd_dist_min)
    #user_cmd_feature存放的是150个大小的List,list中的每个成员也是list,里面的list长度为3,记录100个记录分组中的不重复命令个数,和50个最频繁命令交集的个数,和50个最不频繁命令交集的个数
    labels=get_label("./data/MasqueradeDat/label.txt",2) #取标签的第2列,因为从0开始,所以实际上是label.txt的第3列。一共100行,为什么是100行而不是150行?因为前面5000条(50行)都是正常数据,默认为0就是,就不用类型了,
    # 后面10000(100行)条是随机包含有异常操作。
    y=[0]*50+labels
    #y为150个大小的list,前50个为正常数据,值为0, 后100个就是从label.txt中读出来的某一列,哪一列由get_label第2个参数决定。

    #KNN中其实没什么训练集概念,用这个概念反而不容易理解,其它就是一个已知带标签的样本数据,当有新数据到来的时候和这些有标签的数据的属性做一个最近邻计算。
    #算出距离最近的前k项,并统计这k项中最多的项属于哪类,那么新数据就属于这一类。
    x_train=user_cmd_feature[0:N] #取前N项数据的特征用作样本
    y_train=y[0:N] #取前N项数据对应的标签。这个主要是用于当新数据和已知样本匹配上后,返回这些已知样本的标签。

    x_test=user_cmd_feature[N:150] #后50项用来测试
    y_test=y[N:150] #测试数据实际上是知道真实的标签结果的,这个y_test就是真实结果,它用来和通过分类器预测的结果做对比。

    neigh = KNeighborsClassifier(n_neighbors=3)
    neigh.fit(x_train, y_train)#就是输入已知的条目属性,和该条目录对应的标签。
    y_predict=neigh.predict(x_test)#然后输入测试数据,和已知条目属性做距离运算,返回预测结果。
    #这个预测结果都是0,没法玩。。

    score=np.mean(y_test==y_predict)*100#然后把测试结果和真实结果对比,算出错误率。

    #print y
    #print y_train
    print(y_test)#打印测试集已经知标签
    print(y_predict)#打印使用KNN算法预测后的标签。
    print(score)

#     print(classification_report(y_test, y_predict)) #这两句是sklearn中的东西,不知道啥意思,不影响KNN算法的学习,后续再看吧。
# print(metrics.confusion_matrix(y_test, y_predict))

K近邻算法检测异常操作运行结果

如有疑问之处欢迎加我微信交流,请备注“CSDN博客”
这里写图片描述

如有疑问之处欢迎加我微信交流,共同进步!请备注“CSDN博客”
这里写图片描述

2018-02-11 21:38:34 rosetta 阅读数 247
  • 机器学习案例实战第二课-欺诈检测

    购买课程后,可扫码进入学习群,获取唐宇迪老师答疑 使用Python数据分析流行的库Numpy,Pandas,Matplotlib, Scikit-learn结合真实数据集展开可视化特征分析与机器学习建模和评估。每次课程涉及一个完整的案例,基于案例讲解python库的使用以及如何建立机器学习模型,对涉及到的机器学习算法给出通俗易懂的解释,帮助大家掌握经典机器学习算法,并应用在实际的案例中。

    6915 人正在学习 去看看 唐宇迪

前言

上一节给出了使用K近邻算法检测异常操作的一种方法,现给出另外一种方法。
转载请注明出处:http://blog.csdn.net/rosetta

使用K近邻算法检测异常操作之二

这节的内容和上节总体上类型,区别在于,上一节比较的是最频繁使用的命令和最不频繁使用的命令,而这次使用全量比较。
全量比较的思路仅仅特征选择上不太一样,它先统计所有15000条样本中不重复的命令条数(假设是x条),然后创建150条*x大小的list,即list大小为150条,每条的大小是x。
而这x个大小的值是这样算的,遍历这x条不重复的命令,看其是否是在每个100条分组中,如果在就置1,如果不在就置0。这个操作需要理解的是,x命令不一定都在每个100条分组中,但每个100条分组中的命令肯定在x中。
所以这样的操作结果有是一个150*x的list。如下图,这里的x=107,即此样本只有107条不重复的命令。
帮助理解1

整理完样本的特征后,和上一节的操作都是一样的了,再搞个变量用于存放样本的属性,这样样本数据就有了。然后取样本数据的前N条用于训练数据,150-N条用于测试数据。

不过本算法也是很坑,其预测结果也是没有一个是1,全是0。根本就没什么实际意义。

如有疑问之处欢迎加我微信交流,共同进步!请备注“CSDN博客”
这里写图片描述

2017-07-25 10:43:06 u013709270 阅读数 10036
  • 机器学习案例实战第二课-欺诈检测

    购买课程后,可扫码进入学习群,获取唐宇迪老师答疑 使用Python数据分析流行的库Numpy,Pandas,Matplotlib, Scikit-learn结合真实数据集展开可视化特征分析与机器学习建模和评估。每次课程涉及一个完整的案例,基于案例讲解python库的使用以及如何建立机器学习模型,对涉及到的机器学习算法给出通俗易懂的解释,帮助大家掌握经典机器学习算法,并应用在实际的案例中。

    6915 人正在学习 去看看 唐宇迪

引言

  可能你对这个名字叫“机器学习”的家伙不是特别的了解,但是相信用过iPhone的同学都知道iPhone的语音助手Siri,它能帮你打电话,查看天气等等;相信大家尤其是美女童鞋都用过美颜相机,它能自动化的给我们拍出更漂亮的照片;逛京东淘宝的时候,细心的童鞋应该也会发现它们会有一个栏目“猜你喜欢”;最近异军突起的新闻客户端软件今日头条,它们就是会根据分析你的日常喜好给每个人推荐不同的新闻……没错,这些功能背后的核心就是今天要介绍的主题:机器学习。

什么是机器学习

  对于这个问题的解释,说实话我很有压力,因为在分享篇文章之前就有朋友告诉我,这个百度上一搜一大片,还需要你讲吗?但是,我觉得并非如此。正如同一千个读者眼里有一千个林黛玉一样,我解释的当然是我个人自从读研到工作这么多年对机器学习的学习到应用过程的独特见解。

  首先我们看下图了解一下机器学习在AI(Artificial Intelligence 人工智能)领域的地位。在图中,我们可以看到,机器学习是人工智能的一个子领域。而现在火的不要不要的 深度学习 其实是机器学习的一个子分支。

这里写图片描述

机器学习在人工智能中的地位

那么到底什么才是真正的机器学习呢?在这里我将对比我和学术界大神的解释:

  • 大神的解释

      机器学习研究的是计算机怎样模拟人类的学习行为,以获取新的知识或技能,并重新组织已有的知识结构使之不断改善自身。简单一点说,就是计算机从数据中学习出规律和模式,以应用在新数据上做预测的任务。

  • 我的解释

      传统的机器学习主要做的事情就是利用统计学的基本观点,利用要学习的问题的历史样本数据的分布对总体样本分布进行估计。分析数据大致特性建立数学分布模型,并利用最优化的知识对模型的参数进行调优学习,使得最终的学习模型能够对已知样本进行很好的模拟与估计。最终利用学习好的模型对未知标签的样本进行预测和估计的过程。

      但是越说越觉得机器学习有距离感,云里雾里高深莫测,我们不是专家,但说起算有一些从业经验,做过一些项目在实际数据上应用机器学习。这一篇就我们的经验和各位同仁的分享,总结一些对于初学者入门有帮助的方法和对进阶有用的资料。

机器学习的基本问题

  对于机器学习中的基本问题,我们将从以下几个角度进行讲解:机器学习的特点;机器学习的对象;机器学习的分类;机器学习的要素;模型的评估与选择。

机器学习的特点

机器学习主要特点如下:

  1. 机器学习以数据为研究对象,是数据驱动的科学;

  2. 机器学习的目的是对数据进行预测与分析;

  3. 机器学习以模型方法为中心,利用统计学习的方法构建模型并且利用模型对未知数据进行预测和分析;

  4. 统计学习是概率论、统计学、信息论、计算理论、最优化理论以及计算机科学等多领域的交叉学科,并且逐渐形成自己独自的理论体系和方法论。

这里写图片描述

机器学习的一般训练过程

机器学习的对象

  机器学习研究的对象是多维向量空间的数据。它从各种不同类型的数据(数字,文本,图像,音频,视频)出发,提取数据的特征,抽象出数据的模型,发现数据中的知识,又回到数据的分析与预测中去。

机器学习的分类

  对于机器学习的分类,绝大多数人只简单的分为有监督学习和无监督学习这两类。严格意义上来讲应该分为四大类:有监督学习、无监督学习、半监督学习、强化学习。下面对这四种学习做一下简要的介绍:

  • 有监督学习

      有监督学习是指进行训练的数据包含两部分信息:特征向量 + 类别标签。也就是说,他们在训练的时候每一个数据向量所属的类别是事先知道的。在设计学习算法的时候,学习调整参数的过程会根据类标进行调整,类似于学习的过程中被监督了一样,而不是漫无目标地去学习,故此得名。

  • 无监督学习

      相对于有监督而言,无监督方法的训练数据没有类标,只有特征向量。甚至很多时候我们都不知道总共的类别有多少个。因此,无监督学习就不叫做分类,而往往叫做聚类。就是采用一定的算法,把特征性质相近的样本聚在一起成为一类。

  • 半监督学习

      半监督学习是一种结合有监督学习和无监督学习的一种学习方式。它是近年来研究的热点,原因是在真正的模型建立的过程中,往往有类标的数据很少,而绝大多数的数据样本是没有确定类标的。这时候,我们无法直接应用有监督的学习方法进行模型的训练,因为有监督学习算法在有类标数据很少的情况下学习的效果往往很差。但是,我们也不能直接利用无监督学习的方式进行学习,因为这样,我们就没有充分的利用那些已给出的类标的有用信息。

这里写图片描述

典型半监督训练过程

  • 强化学习

      所谓强化学习就是智能系统从环境到行为映射的学习,以使奖励信号(强化信号)函数值最大,强化学习不同于连接主义学习中的监督学习,主要表现在教师信号上,强化学习中由环境提供的强化信号是对产生动作的好坏作一种评价(通常为标量信号),而不是告诉强化学习系统RLS(reinforcement learning system)如何去产生正确的动作。由于外部环境提供的信息很少,RLS必须靠自身的经历进行学习。通过这种方式,RLS在行动-评价的环境中获得知识,改进行动方案以适应环境。

机器学习的要素

简单地说,机器学习的三要素就是:模型、策略和算法。

  • 模型 其实就是机器学习训练的过程中所要学习的条件概率分布或者决策函数。

  • 策略 就是使用一种什么样的评价度量模型训练过程中的学习好坏的方法,同时根据这个方法去实施的调整模型的参数,以期望训练的模型将来对未知的数据具有最好的预测准确度。

  • 算法 算法是指模型的具体计算方法。它基于训练数据集,根据学习策略,从假设空间中选择最优模型,最后考虑用什么样的计算方法去求解这个最优模型。

入门方法与学习路径

  总的来说,机器学习的学习门槛还是蛮高的。当然,也得看你的目标是什么了。如果你的目标只是为了用机器学习的一些算法解决一些简单的分类回归问题,那么其实也不难。但是,如果你的目标是成为机器学习科学家,提出并改进一些算法的新的应用场景或者是算法的执行性能的话,那么你的学习难度和学习周期必定是很艰辛和漫长的。

  本文对所有的读者的假设是前者,因此我们也制定了与机器学习科学家不一致的学习道路。大致的学习过程如下图所示:
  

这里写图片描述

机器学习的入门过程

  对于上图,之所以最左边写了『数学基础』 『经典算法学习』 『编程技术』 三个并行的部分,是因为机器学习是一个将数学、算法理论和工程实践紧密结合的领域,需要扎实的理论基础帮助引导数据分析与模型调优,同时也需要精湛的工程开发能力去高效化地训练和部署模型和服务。

  在互联网领域从事机器学习的人基本上属于以下两种背景:其中绝大部分是程序员出身,这类童鞋工程经验相对会多一些;另一部分是学数学统计领域的,这部分童鞋理论基础相对扎实一些。因此对比上图,这二类童鞋入门机器学习,所欠缺和需要加强的部分是不一样的。

下面就从三个基本技能讲起。

  • 数学基础

      曾经有无数的满怀激情,誓要在机器学习领域有一番作为的同学,在看到公式的一刻突然就觉得自己狗带了。是的,机器学习之所以门槛高并且显得高大上的主要原因就是数学。每一个算法,要在训练集上最大程度拟合同时又保证泛化能力,需要不断分析结果和数据,调优参数,这需要我们对数据分布和模型底层的数学原理有一定的理解。所幸的是如果只是想合理应用机器学习,而不是做相关方向高精尖的研究,所需要的数学知识读完本科的理工科童鞋还是能很容易的把这些数学知识学明白的。

      基本所有常见机器学习算法需要的数学基础,都集中在微积分、线性代数和概率与统计当中。下面我们先过一过知识重点,文章的后部分会介绍一些帮助学习和巩固这些知识的资料。

  • 微积分

      微分的计算及其几何、物理含义,是机器学习中大多数算法的求解过程的核心。比如算法中运用到梯度下降法、牛顿法等。如果对其几何意义有充分的理解,就能理解“梯度下降是用平面来逼近局部,牛顿法是用曲面逼近局部”,能够更好地理解运用这样的方法。

      凸优化和条件最优化的相关知识在算法中的应用随处可见,如果能有系统的学习将使得你对算法的认识达到一个新高度。

enter image description here

梯度下降法示意图

  • 线性代数

      大多数机器学习的算法要应用起来,依赖于高效的计算,这种场景下,程序员童鞋们习惯的多层for循环通常就行不通了,而大多数的循环操作可转化成矩阵之间的乘法运算,这就和线性代数有莫大的关系了。向量的内积运算更是随处可见。矩阵乘法与分解在机器学习的主成分分析(PCA)和奇异值分解(SVD) 等部分呈现刷屏状地出现。

enter image description here

奇异值分解过程示意图

  从广义来说,机器学习在做的很多事情,和统计层面数据分析和发掘隐藏的模式,是非常类似的。

  极大似然思想、贝叶斯模型 是理论基础,朴素贝叶斯(NaiveBayes)、语言模型(Ngram)、隐马尔科夫(HMM)、隐变量混合概率模型是他们的高级形态。常见分布如高斯分布是混合高斯模型(GMM)等的基础。

这里写图片描述

朴素贝叶斯算法的基本原理

经典算法学习

  绝大多数平常的应用中,经典的机器学习算法就能够解决其中绝大多数的问题。因此,对机器学习经典算法的学习和掌握是相当有必要的。

接下来我们会分门别类的介绍一下:

  • 分类算法: 逻辑回归(LR),朴素贝叶斯(Naive Bayes),支持向量机(SVM),随机森林(Random Forest),AdaBoost,GDBT,KNN,决策树……

  • 回归算法: 线性回归(Linear Regression),多项式回归(Polynomial Regression),逐步回归(Stepwise Regression),岭回归(Ridge Regression),套索回归(Lasso Regression)

  • 聚类算法: K均值(K-Means),谱聚类、DBSCAN聚类、模糊聚类、GMM聚类、层次聚

  • 降维算法: PCA(主成分分析)、SVD(奇异值分解)

  • 推荐算法: 协同过滤算法

      在这里,我还是希望解释一下 算法 这个概念在不同的地方出现的意义给广大的读者带来的疑惑。本文介绍的机器学习算法和我们程序员所说的“数据结构与算法分析”里的算法略有不同。前者更关注结果数据的召回率、精确度、准确性等方面,后者更关注执行过程的时间复杂度、空间复杂度等方面。 当然,实际机器学习问题中,对效率和资源占用的考量是不可或缺的。

编程技术

技术选择

  编程技术无非是语言和开发环境了。在此,对初入门学习机器学习的小白童鞋来说,我的个人建议是:Python + PyCharm。如下图所示是他们的Logo。

这里写图片描述

Python 与 PyCharm 软件示意图

  语言和工具选择好了,对于小白来说,我们当然使用成熟的机器学习库。那么对于python机器学习来说,毫无疑问我们选择的是scikit-learn。

软件安装

  关于在Windows下安装python和scikit-learn的方法步骤,请参阅我的CSDN博客Windows下安装Scikit-Learn。对于PyChram的下载,请点击PyCharm官网去下载,当然windows下软件的安装不用解释,傻瓜式的点击 下一步 就行了。

实战操作

  • 创建项目

  • 打开 PyCharm,点击 Create New Project

这里写图片描述

  • 接下来选择 Pure Python,并选择程序目录同时设置项目名称为 MLDemo,点击右下角的 Create

这里写图片描述

  • 在生成的项目MLDemo 上右击,依次选择 New —> Python,命名 MLDemo

这里写图片描述

  • 编写如下代码,然后右击代码区,点击 Run MLDemo
from sklearn import svm

X = [[0, 0], [1, 1]]
y = [0, 1]
clf = svm.SVC()
clf.fit(X, y)

ans = clf.predict([[2., 2.]])
print(ans)

这里写图片描述

  • 对运行结果进行解释

这里写图片描述



源程序调用了sklearn包的svm类,用于后续程序的分类器是训练:

这里写图片描述


对机器学习,人工智能感兴趣的小伙伴可以加我微信:JeemyJohn,我拉你进我的机器学习群(群里很多高手哦!),或者扫描二维码!当然你也可以关注我的公众号,点击链接:燕哥带你学算法公众号团队简介

这里写图片描述


参考文献:

2017-09-07 15:16:45 Iris0104 阅读数 181
  • 机器学习案例实战第二课-欺诈检测

    购买课程后,可扫码进入学习群,获取唐宇迪老师答疑 使用Python数据分析流行的库Numpy,Pandas,Matplotlib, Scikit-learn结合真实数据集展开可视化特征分析与机器学习建模和评估。每次课程涉及一个完整的案例,基于案例讲解python库的使用以及如何建立机器学习模型,对涉及到的机器学习算法给出通俗易懂的解释,帮助大家掌握经典机器学习算法,并应用在实际的案例中。

    6915 人正在学习 去看看 唐宇迪

算法介绍

聚类分析是一个无监督学习 (Unsupervised Learning) 过程, 一般是用来对数据对象按照其特征属性进行分组,经常被应用在客户分群,欺诈检测,图像分析等领域。K-means 应该是最有名并且最经常使用的聚类算法了,其原理比较容易理解,并且聚类效果良好,有着广泛的使用。
K-means是聚类算法重较为简单的一种,其属于无监督学习,所以训练样本中没有没有类别标签,只有特征。

算法流程

  1. 第一步,选择 K 个点作为初始聚类中心。
  2. 第二步,计算其余所有点到聚类中心的距离,并把每个点划分到离它最近的聚类中心所在的聚类中去。在这里,衡量距离一般有多个函数可以选择,最常用的是欧几里得距离 (Euclidean Distance), 也叫欧式距离。公式如下:
    这里写图片描述
    其中 C 代表中心点,X 代表任意一个非中心点。
  3. 第三步,重新计算每个聚类中所有点的平均值,并将其作为新的聚类中心点。
  4. 最后,重复 (二),(三) 步的过程,直至聚类中心不再发生改变,或者算法达到预定的迭代次数,又或聚类中心的改变小于预先设定的阀值。

参数含义

  1. k 表示期望的聚类的个数。
  2. maxInterations 表示方法单次运行最大的迭代次数。
  3. runs 表示算法被运行的次数。K-means 算法不保证能返回全局最优的聚类结果,所以在目标数据集上多次跑 K-means 算法,有助于返回最佳聚类结果。(1.6版本后,该参数废弃)
    1. initializationMode 表示初始聚类中心点的选择方式, 目前支持随机选择或者 K-means||方式。默认是 K-means||。
  4. initializationSteps表示 K-means||方法中的部数。
  5. epsilon 表示 K-means 算法迭代收敛的阀值。
  6. seed 表示集群初始化时的随机种子。

通常应用时,我们都会先调用 KMeans.train 方法对数据集进行聚类训练,这个方法会返回 KMeansModel 类实例,然后我们也可以使用 KMeansModel.predict 方法对新的数据点进行所属聚类的预测,这是非常实用的功能

k-means小知识

距离计算方法

1.欧几里得距离

欧氏距离是最易于理解的一种距离计算方法,源自欧氏空间中两点间的距离公式。
(1)二维平面上两点a(x1,y1)与b(x2,y2)间的欧氏距离:
这里写图片描述
(2)三维空间两点a(x1,y1,z1)与b(x2,y2,z2)间的欧氏距离:
这里写图片描述
(3)两个n维向量a(x11,x12,…,x1n)与 b(x21,x22,…,x2n)间的欧氏距离:
这里写图片描述

2.曼哈顿距离

从名字就可以猜出这种距离的计算方法了。想象你在曼哈顿要从一个十字路口开车到另外一个十字路口,驾驶距离是两点间的直线距离吗?显然不是,除非你能穿越大楼。实际驾驶距离就是这个“曼哈顿距离”。而这也是曼哈顿距离名称的来源, 曼哈顿距离也称为城市街区距离(CityBlock distance)。
(1)二维平面两点a(x1,y1)与b(x2,y2)间的曼哈顿距离

这里写图片描述
(2)两个n维向量a(x11,x12,…,x1n)与b(x21,x22,…,x2n)间的曼哈顿距离
这里写图片描述

3.余弦相似度

余弦相似度,又称为余弦相似性。通过计算两个向量的夹角余弦值来评估他们的相似度。
(1)在二维空间中向量A(x1,y1)与向量B(x2,y2)的夹角余弦公式:
这里写图片描述
(2)两个n维样本点a(x11,x12,…,x1n)和b(x21,x22,…,x2n)的夹角余弦
类似的,对于两个n维样本点a(x11,x12,…,x1n)和b(x21,x22,…,x2n),可以使用类似于夹角余弦的概念来衡量它们间的相似程度。
这里写图片描述

案例

K-Means算法的结果好坏依赖于对初始聚类中心的选择,容易陷入局部最优解,对K值的选择没有准则可依循,对异常数据较为敏感,只能处理数值属性的数据,聚类结构可能不平衡。

本实例中进行如下步骤:

1.装载数据,数据以文本文件方式进行存放;

2.将数据集聚类,设置2个类和20次迭代,进行模型训练形成数据模型;

3.打印数据模型的中心点;

4.使用误差平方之和来评估数据模型;

5.使用模型测试单点数据;

6.交叉评估1,返回结果;交叉评估2,返回数据集和结果。

数据格式

使用的kmeans_data.txt的数据如下所示:

0.0 0.0 0.0  
0.1 0.1 0.1  
0.2 0.2 0.2  
9.0 9.0 9.0  
9.1 9.1 9.1  
9.2 9.2 9.2  

运行参数

  • 输入数据所在目录:输入数据文件目录,本例中在代码中在代码中可设置,这里设置为/Users/Iris/Documents/idea/spark-master/data/mllib/kmeans_data.txt
  • 用户的评分文件路径:前一步骤中用户对十部电影评分结果文件路径,在这里设置为 /home/Iris/Documents/result_kmeans2

输出内容

1.两个簇中心点

17/06/19 16:48:23 INFO KMeans: KMeans converged in 1 iterations.
17/06/19 16:48:23 INFO KMeans: The cost is 0.11999999999994547.
17/06/19 16:48:23 INFO MapPartitionsRDD: Removing RDD 3 from persistence list
17/06/19 16:48:23 INFO BlockManager: Removing RDD 3
Cluster centers:
 [9.099999999999998,9.099999999999998,9.099999999999998]
 [0.1,0.1,0.1]
 ```
2.结果
模型确定后,可通过预测来几个数值来测试模型,
,注意数据要转换成向量  

方法为:

model.predict(Vectors.dense(“0.25 0.25 0.25”.split(’ ‘).map(_.toDouble))

结果为:

0.25 0.25 0.25 1
“`
它属于cluster1

2019-10-05 13:03:03 day_day_uo 阅读数 6
  • 机器学习案例实战第二课-欺诈检测

    购买课程后,可扫码进入学习群,获取唐宇迪老师答疑 使用Python数据分析流行的库Numpy,Pandas,Matplotlib, Scikit-learn结合真实数据集展开可视化特征分析与机器学习建模和评估。每次课程涉及一个完整的案例,基于案例讲解python库的使用以及如何建立机器学习模型,对涉及到的机器学习算法给出通俗易懂的解释,帮助大家掌握经典机器学习算法,并应用在实际的案例中。

    6915 人正在学习 去看看 唐宇迪

机器学习小白,各位多多交流

def classify0(inX, dataSet, labels, k):  #这个函数就是分类器的函数,要输入4个参数,第一个为测试元素,第二个为数据集,第三个对
    #对应的标签,第四个为K-邻值检测的 K值
    dataSetSize = dataSet.shape[0]  #先求出测试机的行数
    diffMat = tile(inX, (dataSetSize,1)) - dataSet #将测试对象(为一个列表),扩展成一个数组。并和数据集里面的每一个对象进行相减
    sqDiffMat = diffMat**2  # 将相减之后得到的数组进行平方,及数组对应位置的平方,返回的还是一个数组
    sqDistances = sqDiffMat.sum(axis=1) # 按列方向,将平方之后的数字进行相加,得到一个行一样,列为一列的数组
    distances = sqDistances**0.5  #在对求出的数组,每个元素进行开方,来求测试对象和每一个样本集之间的距离
    sortedDistIndicies = distances.argsort()     #然后对求出后的distance 进行排序,并且放回的是这个数在distantces 里面的引索值
    classCount={}          #建立一个空的字典
    for i in range(k):
        voteIlabel = labels[sortedDistIndicies[i]] #取出排前K个数 在原来的位置的引索值,并取得对应引索值下的label值
        classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1  #dict.get()方法, 如果该label值原来没有的
        # 则新建这个key=lable 的键 并且赋值为0  原来这个dict里面本来就有这个key 的话 那就对应增加这个value的值加1
    sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
    #对classCount这个字典先进性items , 通过对items里面的第二个内容的数字大小进行排序,这里即数字,然后为倒叙先大后小,得到一个以元组为元素的列表
    #这里值得注意的是,没办法对字典本身进行排序的,必须先用items方法之后,再进行排序
    return sortedClassCount[0][0] #返回排序中最大元组里面的 标签值

def createDataSet():
    group = array([[1.0,1.1],[1.0,1.0],[0,0],[0,0.1]])
    labels = ['A','A','B','B']
    return group, labels

def file2matrix(filename):
    fr = open(filename)      #打开名字为filename 的文件名,如果是绝对路径则输入据对路径,如r'D:/xxx.txt',因为本文采用的是相对路径
    numberOfLines = len(fr.readlines())         # 计算改文件的行数,并赋值给 number0fLines
    returnMat = zeros((numberOfLines,3))        # 通过zeros 创建一个行数为 number0flines,列数位3 的初始 0 矩阵 名字为returnMat
    classLabelVector = []                       # 定义了一个classLabelVector 的空列表 用于下面的搜集标签
    index = 0                                    #设置一个值为0 的index 变量
    for line in fr.readlines():            #对文本中的每一个值进行预处理
        line = line.strip()   #先去掉每一行里面首尾的空格及换行符
        listFromLine = line.split('\t')    #然后根据key= '\t'空格符  进行切片   得到的是 每一行的 分开的列表
        returnMat[index,:] = listFromLine[0:3]  # 对相应位置的行进行赋值,赋值的内容为listFromLine 列表的前3个元素,有点像Dict 的赋值
        # 这里需要主要的 因为数组或者矩阵是先行后列的描述,因此如果数字在冒号前面,及对行进行操作,数字在冒号后面即对列进行操作
        classLabelVector.append(int(listFromLine[-1]))  #将listFromLine列表的最后一项及标签,按书序添加到classLabelVector
        #这里对标签项用Int()函数 是为了让标签是一个整体字符串的形式
        index += 1   #然后index 逐步加1  这样就可以 把 txt 里面的所有数据 按照顺序安排带returnMat 中
    return returnMat,classLabelVector   #结果返回 一个数组(前)  一个列表(后)
    
def autoNorm(dataSet):  #因为每个指标的取指范围是不一样的,那么在进行计算的时候,就会造成取值大的指标对结果的影响更大
    #因此需要对原来的数据进行  归一化的处理,类似百分比,这里的dataset 及上一个函数返回的 returnMat
    minVals = dataSet.min(0)  #取出每一列的最小值,axis=0 表示竖的方向,axis=1表示横着的方向,返回的是一个列表
    maxVals = dataSet.max(0)   #取出每一行的最大值
    ranges = maxVals - minVals   #计算出最大值和最小值之间的差值
    normDataSet = zeros(shape(dataSet))  #这一步要不要其实都没关系,只是构建了一个和dataset 一样行列的数组而已
    m = dataSet.shape[0]  #计算出 dataset 的行数,这里是用中括号
    normDataSet = dataSet - tile(minVals, (m,1))   # 先看tile()这个函数,因为minVal 只是一个列表, tile将该列表在行方向重复m次,列方向不动
    #这样出来的就是和dataset 一样 行列的数组,然后通过数组之间的相减实现批量操作
    normDataSet = normDataSet/tile(ranges, (m,1))   #这里的原理和上面一样,只不过是数组之间的相除,只要对应的位置进行相除就可以。
    return normDataSet, ranges, minVals    #最后返回3个只,最后的normDateSet 为归一化之后的数组,ranges是最大最小值相减之后的数组

   
def datingClassTest():  #在进行归一化之后,我们得到了最后可用的数据,也就是我们手头上所有的样本,那么我们需要将样本分成训练样本和验证样本,其实还有一个是测试样本
    hoRatio = 0.10      #这里的hoRation 从后面可知就是需要进行测试的样本百分比
    datingDataMat, datingLabels = file2matrix('datingTestSet2.txt')  #将函数file2matrix函数返回的数据值和标签列表返回给datingDataMat 和datingLabels
    normMat, ranges, minVals = autoNorm(datingDataMat) #上面得到的数据datingDataMat  被函数autoNorm进行处理,然后换回3个值
    m = normMat.shape[0] #得知normMat 的行数,给m
    numTestVecs = int(m*hoRatio)  #行数的百分之10 整体的数  给numTestVecs
    errorCount = 0.0 #这里设置了一个 错误的基数器
    for i in range(numTestVecs):   #假如全部的样本有1000条,这里的numTestVecs 就是100条,对这100条的数据进行测试
        classifierResult = classify0(normMat[i,:],normMat[numTestVecs:m,:],datingLabels[numTestVecs:m],3)
        #其中classify0 是分类器算法,normMat[i, :]表示normMat中第i行 成为测试数据,normMat的100行下所有数据作为训练数据
        # datingLabels(它是一个列表)是对应100到最后的标签数据, k-近邻算法里面的K值  取前3个结果对象的标签来确定测试样本的特征值
        print "the classifier came back with: %d, the real answer is: %d" % (classifierResult, datingLabels[i])
        #打印出 测试结果和 测试数据本身的标签值
        if (classifierResult != datingLabels[i]): errorCount += 1.0
        #如果测试结果和测试数据本身标签纸不一样,则错误数加1
    print "the total error rate is: %f" % (errorCount/float(numTestVecs))
    #打印错误路,因为errorCount是小数浮点数,因此分母也需要改成浮点数格式
    print errorCount

机器学习基本问题

阅读数 758

没有更多推荐了,返回首页