数据挖掘入门

  • 这篇博客是我刚开始接触数据挖掘的总结,虽然有些地方不是很详细,但框架还是很清晰,适合于小白入门,至于后面说的比较概括性的知识点,大家可以多Google搞清楚。如果您能坚持着阅读完这篇博客,恭喜你算是入门数据挖掘,接下来您就需要在主流会议和期刊找论文去提升自己了。

  • 虽然python的Sklearn包中都有,但对于简单的算法建议自己动手实现一下,或者涉及到数学推导的也去自己推导一下。

  • 另外,大家也可以自己去研究下weka这个软件,做数据挖掘还是很有意思的。

  • 本博客的代码以及数据可以去github查看。

Chapter 1 引论

1.1 什么是大数据及其特点

Big data is a buzzword, or catch-phrase, used to describe a massive volume of both structured and unstructured data that is so large that it’s difficult to process using traditional database and software techniques. (IDC white paper, 2011)

大数据是一种流行词或流行语,用于描述大量的结构化和非结构化数据,这些数据非常庞大,难以使用传统的数据库和软件技术进行处理。

1.1.1 特点

  • Volume of the data 数据量大 (规模性)
  • Variety different forms of data 多种不同形式的数据(多样性)
  • Velocity analysis of streaming data 数据产生分析快(高速性)
  • Veracity uncertainty of data 数据价值密度低,不确定(不确定性)

1.2 知识发现的流程以及核心

1.2.1 数据中的知识发现(KDD)

  1. 数据清理(消除噪声,删除不一致数据)
  2. 数据集成(多种数据源可以组合在一起)
  3. 数据选择(从数据库中提取与分析任务相关的数据)
  4. 数据变换(通过汇总或聚集操作,把数据变换和统一成适合挖掘的形式)
  5. 数据挖掘(基本步骤,使用智能方法提取数据模式)
  6. 模式评估(根据某种兴趣度度量,识别代表知识的真正有趣的模式)
  7. 知识表示 (使用可视化和知识表示技术,向用户提供挖掘的知识)

image

核心 : 数据挖掘

1.3 什么是数据挖掘,有哪些任务

数据挖掘是从海量数据中挖掘有趣的、有用的、先前未知的模式和知识的过程

1.3.1 主要任务

  • 关联规则挖掘
  • 分类/回归
  • 聚类
  • 离群点分析

1.4 主流会议与期刊

1.4.1 会议

  • ACM SIGKDD (A+), Feb.
  • IEEE ICDM (A), Jun.
  • SIAM SDM (A), Oct.
  • ECML/PKDD (A-), Apr.
  • PAKDD (B+), Oct.

1.4.2 期刊

  • IEEE Transactions on Knowledge and Data
  • Engineering (TKDE)
  • SIGKDD Explorations
  • ACM Transactions on Knowledge Discovery From Data (TKDD)
  • Data Mining and Knowledge Discovery
  • Knowledge and Information Systems (KAIS)

Chapter 2 认识数据与预处理

2.1 认识数据

2.1.1.基本概念

  • 数据是描述对象的抽象
  • 数据集 :数据对象的集合
  • 数据对象 :记录、点、向量、模式、事件、样本、案例、观测或实体
  • 属性 :用作刻画对象的基本性质或特性,也称变量、特性、字段、特征或维
  • 属性值:是赋予属性的数或符号

2.1.2 属性类型

分类型(Categorical)
  • 标称(Nominal)-特殊有:二元(仅仅是不同的名字,即标称值只提供足够的信息以区分对象)
    • 例:ID号、眼球颜色、邮政编码
    • 操作:众数、熵、列联相关、卡方检验
  • 序数(Ordinal)(提供足够的信息确定对象的序)
    • 例:军阶、GPA、用{tall,medium,short}表示的高
    • 操作:中值、百分位、秩相关、游程检验、符号检验
数值型(Numerical)
  • 区间(Interval)(值之间的差是有意义的,即存在测量单位)
    • 例:日历、摄氏或华氏温度
    • 操作:均值、标准差、皮尔逊相关、t和f检验
  • 比率(Ratio)(差与比率都有意义)
    • 开氏温度、长度、计数
    • 操作:几何平均、调和平均、百分比差

通常,标称、序数属性为离散的,区间和比率属性是连续的。

二元属性
  • 离散属性特例
  • 仅仅取两个不同的值,0/1、真/假、是/否、男/女
  • 对称的二元属性:两个值一样重要 男/女
  • 非对称的二元属性:一个值比另一个值更重要。化验结果中(阴性、阳性)阳性较少,值得关注。

2.1.3 数据类型

  • 记录数据
    • 数据矩阵
    • 文档数据
    • 购物篮数据(事务数据)
  • 图数据
    • 万维网
    • 分子结构
  • 有序数据
    • 时许数据
    • 序列数据
    • 基因序列数据
    • 空间数据

2.1.4 数据的描述

中心性描述
  • 均值
  • 众数
  • 中位数
  • 中列数(最大最小平均值)
散度描述
  • 极差
  • 四分位数(二分位数实际上是中位数)
  • 方差、标准差
  • 四分位数极差(横坐标25%分位数点与75%分位数点的距离)

2.1.5 数据的相似性度量

相似性与相异型都称邻近性,如果两个对象i和j不相似,则它们的相似性度量为0,相异型度量为1

标称属性数据

相异性度量的方法:

d(i,j)=pmp d ( i , j ) = p − m p

m:状态取值匹配的变量数目,

p:变量总数

二元属性数据
属性值10sum
1qrq+r
0sts+t
sumq+sr+tp

- 对称的二元变量的相异度计算

d(i,j)=r+sq+r+s+t d ( i , j ) = r + s q + r + s + t

  • 非对称的二元变量相异度计算

d(i,j)=r+sq+r+s d ( i , j ) = r + s q + r + s

对与非对称的相异度,负匹配数目t被认为不重要而忽略

例题
NameGenderFeverCoughTest1Test2Test3Test4
JackMYNPNNN
MaryFYNPNPN
JimMYPNNNN

Gender是对称的,其余都不是对称的

Y和P的值设置为1,而N的值设置为0

d(Jack,Mary)=0+12+0+1=0.33 d ( J a c k , M a r y ) = 0 + 1 2 + 0 + 1 = 0.33

d(Jack,Jim)=1+11+1+1=0.67 d ( J a c k , J i m ) = 1 + 1 1 + 1 + 1 = 0.67

d(Jim,Mary)=1+21+1+2=0.75 d ( J i m , M a r y ) = 1 + 2 1 + 1 + 2 = 0.75

数值型数据的相异性
闵科夫斯基距离

d(i,j)=|xi1xj1|h+|xi2xj2|h++|xipxjp|hh d ( i , j ) = | x i 1 − x j 1 | h + | x i 2 − x j 2 | h + … … + | x i p − x j p | h h

- h=1为曼哈顿距离
- h=2为欧几里得距离

序数属性的邻近性度量

例如一个序数属性{fair、good、excellent}可以映射为{0,0.5,1}利用数值型方法去度量

混合类型属性的相异性

分别计算相异性矩阵求和求平均

需要注意: 需要把相异型矩阵的数值压缩到区间[0,1]利用最大最小归一化

余弦相似性

sim(x,y)=xy||x||||y|| s i m ( x , y ) = x ⋅ y | | x | | | | y | |

2.2 数据预处理

2.2.1 主要任务

  • 数据清理:空缺值,噪声数据,删除孤立点,解决不一致性
  • 数据集成:集成多个数据库、数据立方体或文件
  • 数据归约:得到数据的压缩表示
  • 数据变换:规范化和聚集
  • 数据离散化:将连续数据进行离散处理
数据清理
缺失值处理
  • 属性缺少值百分比很大时,可以忽略此属性
  • 人工填写:工作量大,可行性低
  • 使用一个全局变量填充空缺值,比如Unknown
  • 使用属性的平均值填充空缺值
  • 使用与给定元祖属同一类的所有样本的平均值
  • 使用最可能的值填充:例如,其余属性值与之特别相近前k个平均
噪声处理
  • 分箱:首先排序数据,并将他们分到等深的箱中,然后可以按箱的平均值、按箱的中值,按箱的边界平滑
  • 聚类方法找出孤立点
数据集成

将多个数据源中的数据整合到一个一致的存储中

集成多个数据时,经常会出现冗余数据

  • 同一个属性在不同的数据库中有不同的字段
  • 一个属性可以由另一个表导出,如年薪
冗余数据处理
  • 数值型

相关分析——皮尔逊系数

rA,B=ni=1(aiA)(biB)(n1)σAσB r A , B = ∑ i = 1 n ( a i − A ) ( b i − B ) ( n − 1 ) σ A σ B

- n:样本个数
- A、B两个属性的平均值
- σA σ A σB σ B 各自标准差

  • 标称数据
    相关分析——卡方检验

χ2=i=1cj=1r(oijeij)2eij χ 2 = ∑ i = 1 c ∑ j = 1 r ( o i j − e i j ) 2 e i j

- oij o i j 是事件 (Ai,Bi) ( A i , B i ) 的观测频度,而 eij e i j 是事件 (Ai,Bi) ( A i , B i ) 的期望频度。

eij=count(A=ai)×count(B=bj)n e i j = c o u n t ( A = a i ) × c o u n t ( B = b j ) n

自由度为 (r1)×(c1) ( r − 1 ) × ( c − 1 )

例题
属性合计
小说250(90)200(360)450
非小说50(210)1000(840)1050
合计30012001500

e11=count()×count()n=300×4501500=90 e 11 = c o u n t ( 男 ) × c o u n t ( 小 说 ) n = 300 × 450 1500 = 90

… …

χ2=(25090)290+(50210)2210+(200360)2360+(10008400)2840=507.93 χ 2 = ( 250 − 90 ) 2 90 + ( 50 − 210 ) 2 210 + ( 200 − 360 ) 2 360 + ( 1000 − 8400 ) 2 840 = 507.93

对于 2×2 2 × 2 的表自由度为 (21)(21)=1 ( 2 − 1 ) ( 2 − 1 ) = 1 。对于自由度1,在0.001的置信水平下,拒绝假设的值是10.82,则这两个属性强相关。

数据归约

用来得到数据集的归约表示,它小的多,但可以产生相同的分析结果
- 维归约:小波分析、PCA、特征筛选
- 数量归约:回归、聚类、采样、数据立方题聚集
- 数据压缩:使用变换

- 最大最小规范化(压缩到0-1) 
- z-score规范化

z-score规范化 v=vμσ v ′ = v − μ σ

Chapter 3 关联规则挖掘

3.1 什么是关联规则挖掘

给定事务的集合T,关联规则发现是找出支持度大于等于min_sup并且置信度大于等于min_conf的所有规则,min_sup和min_conf是对应的支持度和置信度阈值

3.1.1 一般来说该过程包含两步

1.找出所有频繁项集

2.依据频繁项集找到强关联规则

3.1.2 基本概念

  • 项集:包含0个或多个项的集合
  • k-项集:包含k个项的项集
  • 支持度计数:包含特定项集的事务个数
  • 支持度:包含项集的事务数与总事务数的比值
  • 频繁项集:满足最小支持度阈值的所有项集
  • 置信度:确定Y在包含X的食物中出现的频繁程度 con(X,Y)=P(Y|X)=sup(XY)sup(X) c o n ( X , Y ) = P ( Y | X ) = s u p ( X ⋃ Y ) s u p ( X )

例子 (min_sup:50% min_con:50%)

Tid商品列表频繁项集支持度
10A,B,C{A}75%
20A,C{B}50%
30A,D{C}50%
40B,E,F{A,C}50%

可以发现规则:A===>C

最小支持度{A,C}:50%

最小置信度: sup(A,C)sup(A)=50%75%=66.6% s u p ( A , C ) s u p ( A ) = 50 % 75 % = 66.6 %

3.2 Apriori算法

Apriori算法是经典的挖掘频繁项集和关联规则的数据挖掘算法。

Apriori在拉丁语中指”来自以前”。当定义问题时,通常会使用先验知识或者假设,这被称作”一个先验”(apriori)。

Apriori算法的名字正是基于这样的事实:算法使用频繁项集性质的先验性质,即频繁项集的所有非空子集也一定是频繁的。

Apriori算法使用一种称为逐层搜索的迭代方法,其中k项集用于探索(k+1)项集。首先,通过扫描数据库,累计每个项的计数,并收集满足最小支持度的项,找出频繁1项集的集合。该集合记为L1。然后,使用L1找出频繁2项集的集合L2,使用L2找出L3,如此下去,直到不能再找到频繁k项集。每找出一个Lk需要一次数据库的完整扫描。

Apriori算法使用频繁项集的先验性质来压缩搜索空间。

3.2.1 相关定义

  • 连接步骤:频繁(k-1)项集 Lk1 L k − 1 的自身连接产生候选k项集 Ck C k

Apriori算法假定项集中的项按照字典序排序。如果 Lk1 L k − 1 中某两个的元素(项集)ItemSet_1和ItemSet_2的前(k-2)个项是相同的,则称ItemSet_1和ItemSet_2是可连接的。

  • 剪枝策略

由于存在先验性质:任何非频繁的(k-1)项集都不是频繁k项集的子集。因此,如果一个候选k项集 Ck C k 的(k-1)项子集不在 Lk1 L k − 1 中,则该候选也不可能是频繁的,从而可以从 Ck C k 中删除,获得压缩后的 Ck C k

  • 删除策略

基于压缩后的 Ck C k ,扫描所有事务,对 Ck C k 中的每个项进行计数,然后删除不满足最小支持度的项,从而获得频繁k项集,即 Lk L k

3.2.2 步骤

  1. 每个项都是候选1项集的集合 C1 C 1 的成员。算法扫描所有的事务,获得每个项,生成 C1 C 1 。然后对每个项进行计数。然后根据最小支持度从 C1 C 1 中删除不满足的项,从而获得频繁1项集 L1 L 1
  2. L1 L 1 的自身连接生成的集合执行剪枝策略产生候选2项集的集合 C2 C 2 ,然后,扫描所有事务,对 C2 C 2 中每个项进行计数。同样的,根据最小支持度从 C2 C 2 中删除不满足的项,从而获得频繁2项集 L2 L 2
  3. L2 L 2 的自身连接生成的集合执行剪枝策略产生候选3项集的集合 C3 C 3 ,然后,扫描所有事务,对 C3 C 3 每个项进行计数。同样的,根据最小支持度从 C3 C 3 中删除不满足的项,从而获得频繁3项集 L3 L 3
  4. 以此类推,对 Lk1 L k − 1 的自身连接生成的集合执行剪枝策略产生候选k项集 Ck C k ,然后,扫描所有事务,对 CK C K 中的每个项进行计数。然后根据最小支持度从 Ck C k 中删除不满足的项,从而获得频繁k项集。
由频繁项集产生关联规则

一旦找出了频繁项集,就可以直接由它们产生强关联规则。产生步骤如下:
- 对于每个频繁项集ItemSet,产生ItemSet的所有非空子集(这些非空子集一定是频繁项集)
- 对于itemset的每个非空子集s,如果 sup(l)sup(s)>=min_conf s u p ( l ) s u p ( s ) >= m i n _ c o n f ,则输出s==>(l-s),其中min_conf是最小置信度阈值。
image

python代码如下:
import numpy as np

class Apriori:
    dataSet = []
    minSopport = 0.2
    minConf = 0.7
    def __init__(self,dataSet,minSopport,minConf):
        self.dataSet = dataSet
        self.minConf = minConf
        self.minSopport = minSopport

    def creatC1(self):
        """
        找出频繁一项集
        """
        C1=[]
        for transaction in self.dataSet:
            for item in transaction:
                if not[item] in C1:
                    C1.append([item])
        C1.sort();
        return map(frozenset,C1)

    def ScanD(self,Data,Ck):
        """
        找出候选频繁项集,扫描数据集计算候选频繁项集的支持度
        """
        ssCnt={}
        for tid in Data:
            for can in Ck:
                if can.issubset(tid):#tid的事务数据集包含can
                    if can in ssCnt:
                        ssCnt[can]+=1
                    else:
                        ssCnt[can]=1
        numItems = float(len(Data))
        retlist = [];
        supportData = {}
        #计算所有项集的支持度
        for key in ssCnt:
            support = ssCnt[key]/numItems
            if support>=self.minSopport:
                retlist.insert(0,key)
            supportData[key] = support
        return retlist,supportData

    def has_infrequen_subset(self,Ck_item,Lk):
        """
        剪枝判断操作
        """
        for item in Ck_item:
            sub_Ck = Ck_item - frozenset([item])
            if sub_Ck not in Lk:
                return False
        return True

    def aprioriGen(self,Lk,k):
        """
        自连接和剪枝
        """
        retlist = []
        lenLk = len(Lk)
        for i in range (lenLk):
            for j in range(i+1,lenLk):  
                L1=list(Lk[i])[:k-2]
                L2=list(Lk[j])[:k-2]
                L1.sort()
                L2.sort()
                if L1==L2:  
                    Ck_item=Lk[i]|Lk[j]
                    if self.has_infrequen_subset(Ck_item, Lk):
                        retlist.append(Ck_item)
        return retlist

    def print_fre_set(self,L,supportData):
        """
        打印频繁项集
        """
        for i in range(len(L)):
            print("频繁{0}项集为:".format(i+1))
            for j in range(len(L[i])):
                n=supportData[L[i][j]]
                l=[k for k in L[i][j]]
                print(l,' : ',n)

    def apriori(self):
        C1 = list(self.creatC1())
        D = list(map(set,self.dataSet))
        L1,supportData = self.ScanD(D,C1)
        L=[L1]
        k=2
        while(len(L[k-2])>0):
            Ck = self.aprioriGen(L[k-2],k)
            Lk,supK=self.ScanD(D,Ck)
            supportData.update(supK)
            L.append(Lk)
            k+=1
        L.pop()
        self.print_fre_set(L,supportData)
        print("关联规则为:")
        Rules = self.GetRules(L,supportData)
        return L,supportData,Rules
    def GetRules(self,L,supportData):
        """
        获取关联规则
        """
        BigRuleList = []
        sub_set_list = []
        for i in range(0, len(L)):
            for freq_set in L[i]:
                for sub_set in sub_set_list:
                    if sub_set.issubset(freq_set):
                        conf = supportData[freq_set] / supportData[freq_set - sub_set]
                        big_rule = (freq_set - sub_set, sub_set, conf)
                        if conf >= self.minConf and big_rule not in BigRuleList:
                            L1 = [i for i in (freq_set-sub_set)]
                            L2 = [i for i in sub_set]
                            print (L1, " ===> ", L2, "confidence: ", conf)
                            BigRuleList.append(big_rule)
                sub_set_list.append(freq_set)
        return BigRuleList

3.2.3 提高Apriori算法的方法

  • Hash-based itemset counting(散列项集计数)
  • Transaction reduction(事务压缩)
  • Partitioning (划分)
  • Sampling(采样)
Hash-based itemset counting

基本思想:压缩候选k项集

散列项集到对应的桶中,一个其hash桶的计数小于阈值的k-itenset不可能是频繁的

Transaction reduction

基本思想:删除不可能对寻找频繁项集有用的事务

不包含任何频繁k项集的事务不可能包含任何k+1项集。因此这些事务在其后的考虑中,可以加上标记或删除。

Partitioning

基本思想:分而治之

项集在DB中是频繁的,它必须至少在DB的一个划分中是频繁的

  • 扫描1:划分数据库,并找出局部频繁模式
  • 扫描2:求出全局频繁模式
抽样

基本思想:选取原数据的一个样本,在样本利用Apriori挖掘频繁模式

牺牲一些精度换取有效性

3.3 FP-growth

3.3.1 构建FP树

  1. 支持度排序:扫描一次数据集,确定每个项的支持度计数。丢弃非频繁项,而将频繁项按照支持度的递减排序。L = {a:8, b:7, c:6, d:5, e:3}
  2. 构建FP树:第二次扫描数据集,读入第一个事务{a, b}之后,创建标记为a和b的结点。然后形成null->a->b路径。该路径上的所有结点的频度计数为1。

    读入第二个事务{b,c,d}之后,为项b,c和d创建新的结点集。然后,连接结点null->b->c->d,形成一条代表该事务的路径。该路径上的每个结点的频度计数也等于1.

注意:尽管前两个事务具有一个共同项b,但是它们的路径不相交,因为这两个事务没有共同的前缀.

举例说明

项头表建立

有了项头表和排序后的数据集,我们就可以开始FP树的建立了。开始时FP树没有数据,建立FP树时我们一条条的读入排序后的数据集,插入FP树,插入时按照排序后的顺序,插入FP树中,排序靠前的节点是祖先节点,而靠后的是子孙节点。如果有共用的祖先,则对应的公用祖先节点计数加1。插入后,如果有新节点出现,则项头表对应的节点会通过节点链表链接上新节点。直到所有的数据都插入到FP树后,FP树的建立完成。

    
似乎也很抽象,我们还是用第二节的例子来描述。
    

首先,我们插入第一条数据ACEBF,如下图所示。此时FP树没有节点,因此ACEBF是一个独立的路径,所有节点计数为1, 项头表通过节点链表链接上对应的新增节点。

接着我们插入数据ACG,如下图所示。由于ACG和现有的FP树可以有共有的祖先节点序列AC,因此只需要增加一个新节点G,将新节点G的计数记为1。同时A和C的计数加1成为2。当然,对应的G节点的节点链表要更新

依次类推 最终得到

FP Tree 挖掘

我们辛辛苦苦,终于把FP树建立起来了,那么怎么去挖掘频繁项集呢?看着这个FP树,似乎还是不知道怎么下手。下面我们讲如何从FP树里挖掘频繁项集。得到了FP树和项头表以及节点链表,我们首先要从项头表的底部项依次向上挖掘。对于项头表对应于FP树的每一项,我们要找到它的条件模式基。所谓条件模式基是以我们要挖掘的节点作为叶子节点所对应的FP子树。得到这个FP子树,我们将子树中每个节点的的计数设置为叶子节点的计数,并删除计数低于支持度的节点。从这个条件模式基,我们就可以递归挖掘得到频繁项集了。
    

实在太抽象了,之前我看到这也是一团雾水。还是以上面的例子来讲解。我们看看先从最底下的F节点开始,我们先来寻找F节点的条件模式基,由于F在FP树中只有一个节点,因此候选就只有下图左所示的一条路径,对应{A:8,C:8,E:6,B:2,F:2}。我们接着将所有的祖先节点计数设置为叶子节点的计数,即FP子树变成{A:2,C:2,E:2,B:2,F:2}。一般我们的条件模式基可以不写叶子节点,因此最终的F的条件模式基如下图右所示。

通过它,我们很容易得到F的频繁2项集为{A:2,F:2}, {C:2,F:2}, {E:2,F:2}, {B:2,F:2}。递归合并二项集,得到频繁三项集为{A:2,C:2,F:2},{A:2,E:2,F:2},…还有一些频繁三项集,就不写了。当然一直递归下去,最大的频繁项集为频繁5项集,为{A:2,C:2,E:2,B:2,F:2}
    

F挖掘完了,我们开始挖掘D节点。D节点比F节点复杂一些,因为它有两个叶子节点,因此首先得到的FP子树如下图左。我们接着将所有的祖先节点计数设置为叶子节点的计数,即变成{A:2, C:2,E:1 G:1,D:1, D:1}此时E节点和G节点由于在条件模式基里面的支持度低于阈值,被我们删除,最终在去除低支持度节点并不包括叶子节点后D的条件模式基为{A:2, C:2}。通过它,我们很容易得到F的频繁2项集为{A:2,D:2}, {C:2,D:2}。递归合并二项集,得到频繁三项集为{A:2,C:2,D:2}。D对应的最大的频繁项集为频繁3项集。

同样的方法可以得到B的条件模式基如下图右边,递归挖掘到B的最大频繁项集为频繁4项集{A:2, C:2, E:2,B:2}。

继续挖掘G的频繁项集,挖掘到的G的条件模式基如下图右边,递归挖掘到G的最大频繁项集为频繁4项集{A:5, C:5, E:4,G:4}。

E的条件模式基如下图右边,递归挖掘到E的最大频繁项集为频繁3项集{A:6, C:6, E:6}。

C的条件模式基如下图右边,递归挖掘到C的最大频繁项集为频繁2项集{A:8, C:8}。

至于A,由于它的条件模式基为空,因此可以不用去挖掘了。
    

至此我们得到了所有的频繁项集,如果我们只是要最大的频繁K项集,从上面的分析可以看到,最大的频繁项集为5项集。包括{A:2, C:2, E:2,B:2,F:2}。

3.3.2 FP Tree算法归纳

这里我们对FP Tree算法流程做一个归纳。FP Tree算法包括三步:

  1. 扫描数据,得到所有频繁一项集的的计数。然后删除支持度低于阈值的项,将1项频繁集放入项头表,并按照支持度降序排列。
        
  2. 扫描数据,将读到的原始数据剔除非频繁1项集,并按照支持度降序排列。
  3. 读入排序后的数据集,插入FP树,插入时按照排序后的顺序,插入FP树中,排序靠前的节点是祖先节点,而靠后的是子孙节点。如果有共用的祖先,则对应的公用祖先节点计数加1。插入后,如果有新节点出现,则项头表对应的节点会通过节点链表链接上新节点。直到所有的数据都插入到FP树后,FP树的建立完成。
  4. 从项头表的底部项依次向上找到项头表项对应的条件模式基。从条件模式基递归挖掘得到项头表项项的频繁项集。
  5. 如果不限制频繁项集的项数,则返回步骤4所有的频繁项集,否则只返回满足项数要求的频繁项集。

3.3.3 关联模式评估

关联分析算法往往产生大量的规则,而其中很大一部分可能是不感兴趣的。 因此,建立一组广泛接受的评价关联模式质量的标准是非常重要的。
- 第一组标准可以通过统计论据建立。涉及相互独立的项或覆盖少量事务的模式被认为是不令人感兴趣的,因为它们可能反映数据中的伪联系。(这些令人感兴趣的模式可以使用客观兴趣度度量来排除)。
- 第二组标准可以通过主观论据建立。一个模式被主观认为是无趣的,除非它能够揭示料想不到的信息或提供导致有益的行动的有用信息。

例如:{黄油} {面包}可能不是有趣的,尽管有很高的支持度和置信度,但是它表示的关系显而易见。另一方面,规则{尿布} {啤酒}是有趣的,因为这种联系十分出乎意料,并且可能为零售商提供新的交叉销售机会

现有的关联规则的挖掘算法依赖于支持度和置信度来除去没有意义的模式。 ==然而。。。==

假定希望分析爱喝咖啡和爱喝茶的人之间的关系。收集一组人关于饮料偏爱的信息,并汇总到下表

DrinkCoffeeNo Coffee
Tea15050200
No Tea650150800
8002001000

可以使用表中信息来评估关系规则{茶} ->{咖啡}。
似乎喜欢喝茶的人也喜欢喝咖啡,因为该规则的支持度(15%)和置信度(75%)都相当高。
但是所有人中,不管他是否喝茶,喝咖啡的人的比例为80%。这意味着,一个人如果喝茶,则他喝咖啡的可能性由80%减到了75%。

 强规则不一定是有趣的,甚至是“误导”的。

原因:置信度的缺点在于该度量忽略了规则后件中项集的支持度。

茶和咖啡的例子表明,由于置信度度量忽略了规则后件中出现的项集的支持度,高置信度的规则有时存在误导。
解决这个问题的一种方法是使用称作提升度lift的度量:它计算规则置信度和规则后件中项集的支持度之间的比率

Chapter 4 分类与预测

4.1 监督学习VS无监督学习

  • 无监督学习(关联规则,聚类分析)
    • 数据集的对象的类标记是未知的
    • 挖掘潜在的数据内部模式
  • 监督学习(分类/预测)
    • 数据集中的对象的类标记已知
    • 通过类标记的指导下学习数据中的模式
    • 利用获取的模式或者模型对新数据进行分类预测

4.2 模型分类

详解生成模型与判别模型
- 生成模型(Generative Model)希望从数据中学习/还原出原始的真实数据生成模型。常见的方法是学习数据的联合概率分布。E.g 朴素贝叶斯方法、隐马尔科夫模型等。
- 当容量大时,容易接近真实模型
- 能处理具有隐含变量的情景
- 估计的是联合概率分布(joint probability distribution),p(y, x)=p(y|x)*p(x),由数据学习联合概率密度分布P(X,Y),然后求出条件概率分布P(Y|X)作为预测的模型,即生成模型:P(Y|X)= P(X,Y)/ P(X)。基本思想是首先建立样本的联合概率概率密度模型P(X,Y),然后再得到后验概率P(Y|X),再利用它进行分类。==生成方法关心的是给定输入x产生输出y的生成关系==。
- 判别模型(Discriminative Model)从数据中学习到不同类概念的区别从而进行分类。如KNN,SVM, ANN, Decision Tree, etc.
- 速度快
- 准确率较高
- 估计的是条件概率分布(conditional distribution), p(y|x),是给定观测变量x和目标变量y的条件模型。由数据直接学习决策函数y=f(X)或者条件概率分布P(y|x)作为预测的模型。==判别方法关心的是对于给定的输入X,应该预测什么样的输出Y。==

==例如:== 比如说要确定一只羊是山羊还是绵羊,用判别模型的方法是先从历史数据中学习到模型,然后通过提取这只羊的特征x来预测出这只羊f(X)是山羊的概率,是绵羊的概率。用生成模型的方法是我们可以根据山羊的特征首先学习出一个山羊模型,然后根据绵羊的特征学习出一个绵羊模型。然后从这只羊中提取特征,放到山羊模型P(w1|X)中看概率是多少,再放到绵羊模型P(w2|X)中看概率是多少,如果P(w1|X)>P(w2|X),那么我们就认为X是属于w1类,即该羊属于山羊。

==再例如==:比如说你的任务是识别一个语音属于哪种语言。例如对面一个人走过来,和你说了一句话,你需要识别出她说的到底是汉语、英语还是法语等。那么你可以有两种方法达到这个目的:用生成模型的方法是学习每一种语言,你花了大量精力把汉语、英语和法语等都学会了,我指的学会是你知道什么样的语音对应什么样的语言。然后再有人过来对你说话,你就可以知道他的语言对应什么语言;用判别模型的方法是不去学习每一种语言,你只学习这些语言模型之间的差别,然后再分类。意思是指我学会了汉语和英语等语言的发音是有差别的,我学会这种差别就好了。

4.3 决策树

决策树又称为判定树,是运用于分类的一种树结构,其中的每个内部节点代表对某一属性的一次测试,每条边代表一个测试结果,叶节点代表某个类或类的分布。
决策树的决策过程需要从决策树的根节点开始,待测数据与决策树中的特征节点进行比较,并按照比较结果选择选择下一比较分支,直到叶子节点作为最终的决策结果。

4.3.1 决策树构造

  • 决策归纳树算法(一个贪心算法)
    • 自顶向下的分治方式构造决策树
    • 使用分类属性(如果是量化属性,则需先进行离散化)递归的通过选择相应的测试属性来划分样本
    • 测试属性是根据某种启发信息或者是统计信息来进行选择(如:信息增益)
具体流程
  1. 树以代表训练样本的单个结点开始。
  2. 如果样本都在同一个类.则该结点成为树叶,并用该类标记。
  3. 否则,算法选择最有分类能力的属性作为决策树的当前结点.
  4. 根据当前决策结点属性取值的不同,将训练样本数据集分为若干子集,每个取值形成一个分枝,有几个取值形成几个分枝。针对上一步得到的一个子集,重复进行先前步骤,递归形成每个划分样本上的决策树。一旦一个属性出现在一个结点上,就不必在该结点的任何后代考虑它。
  5. 递归划分步骤仅当下列条件之一成立时停止:
    1. 给定结点的所有样本属于同一类。
    2. 没有剩余属性可以用来进一步划分样本。
    3. 如果某一分枝,没有满足该分支中已有分类的样本,则以样本的多数类创建一个树叶。
属性选择度量
  • 属性选择度量
    • 又称分裂规则,决定给定节点上的元组如何分裂
    • 具有最好度量得分的属性(对分出的数据类别越“纯”)选定为分裂属性
  • 三种度量
    • 信息增益
    • 信息增益率
    • Gini指标
信息增益(ID3)
  • 信息熵

H(D)=i=1k(pi×logpi) H ( D ) = − ∑ i = 1 k ( p i × l o g p i )

pi p i 表示第i类的概率

  • 条件信息增益

刻画在已知X的基础上需要多少信息来描述Y

  • 信息增益

G(D,A)=H(D)H(D|A) G ( D , A ) = H ( D ) − H ( D | A )

H(D|A)=i=1kpiH(D|A=ai)=i=1kpij=1np(yj|xi)logp(yj|xi) H ( D | A ) = ∑ i = 1 k p i H ( D | A = a i ) = − ∑ i = 1 k p i ∑ j = 1 n p ( y j | x i ) l o g p ( y j | x i )

首先需要筛选出特定特征以及特定特征取值的数据集 D|A=aj D | A = a j ,再根据公式计算条件熵。

Eg:

XY
MathYes
HistoryNo
CSYes
MathNo
MathNo
CSYes
HistoryNo
MathYes

X = 专业

Y=是否喜欢IPHINEX

vi v i Prob(X=vi) P r o b ( X = v i ) `H(YX=vi) `
Math0.51
History0.250
CS0.250

H(Y|X)=0.5×1+0.25×0+0.25×0=0.5 H ( Y | X ) = 0.5 × 1 + 0.25 × 0 + 0.25 × 0 = 0.5

刻画在已知X的基础上需要节约多少信息来描述Y
IG(Y|X)=H(Y)H(Y|X)=10.5=0.5 I G ( Y | X ) = H ( Y ) − H ( Y | X ) = 1 − 0.5 = 0.5

信息增益率
  • 信息增益倾向于有大量不同取值的属性(划分更细,更纯)
    • 极端:每个划分子集只有一个样本,即一个类
    • 此时info(d)=0
  • C4.5(ID3升级)使用增益率来客服这一问题(规范化信息增益)
  • 具有最大增益率的属性选为分裂属性
Gini指标
  • 是指度量元组的不纯度。数据D包含n类别的样本,Gini(D)定义为:
    gini(D)=1nj=1p2j g i n i ( D ) = 1 − ∑ j = 1 n p j 2

    pj p j 为类别j在D中的频率

  • 具有最小gini的属性或者不纯度减少最大的用于分裂节点。

4.3.2 决策树过拟合问题

过拟合:为了得到一致假设而使假设变得过度复杂称为过拟合
- 决策树:一棵归纳的树可能过分拟合训练数据
- 分枝太多,某些反映训练数据中的异常,噪声/孤立点
- 对未参与训练的样本的低精度预测
- 过拟合是监督学习中普遍存在的一个问题
- 原因:训练样本只是真实模型下的一个抽样集
- 结果:模型泛化能力不强

  • 过拟合解决策略
    • 增加样本集,去除噪声
    • 降低模型复杂度
    • Train—Validation—Test
    • 模型选择:正则项
  • 决策树的过拟合的解决方案
    • 设定决策树的最大高度(层数)来限制树的生长。
    • 设定每个节点必须包含的最小记录数,当节点中记录的个数小于这个数值时就会停止分割
    • 树剪枝——先剪枝:提前终止树的构造,如果对一个节点的分裂会产生低于给定阈值的度量,划分停止。而选择一个合适的阈值很难
    • 树剪枝——后剪枝:从完全生长的树中剪去树枝。但是后剪枝的计算量代价比先剪枝方法大得多,特别是在大样本集中,不过对于小样本的情况,后剪枝方法还是优于预剪枝方法的。

4.3.3 由决策树提取分类规则

  • 可以提取决策树表示的知识,并以IF-THEN形式的分类规则表示
  • 对从根到树叶的每条路径创建一个规则
  • 沿着给定路径上的每个属性-值对形成规则前件(”IF”部分)的一个合取项
  • 叶节点包含类预测,形成规则后件(”THEN”部分)
  • IF-THEN规则易于理解,尤其树很大时

4.4 KNN(K近邻算法——K-Nearest Neighbor)

  • KNN算是理论上比较成熟的方法,最初由Cover和Hart于1968年提出,是非参数法中最重要的方法之一。其思路简单直观,易于快速实现。
  • 因此,KNN算法以其实现的简单性及较高的分类准确性在中文文本自动分类等领域中得到了广泛应用。

4.4.1 KNN的基本思想

  • 根据距离函数计算待分类样本X和每个训练样本的距离(作为相似度),选择与待分类样本距离最小的K个样本作为X的K个最近邻,最后以X的K个最近邻中的大多数所属的类别作为X的类别。
  • KNN可以说是一种最直接的用来分类未知数据的方法。
  • 有那么一堆你已经知道分类的数据,然后当一个新数据进入的时候,就开始跟训练数据里的每个点求距离,然后挑出离这个数据最近的K个点,看看这K个点属于什么类型,然后用少数服从多数的原则,给新数据归类。

image

4.4.2 算法计算步骤

  1. 算距离:给定测试对象,计算它与训练集中的每个对象的距离
  2. 找邻居:圈定距离最近的k个训练对象,作为测试对象的近邻
  3. 做分类:根据这k个近邻归属的主要类别,来对测试对象分类。

4.4.3 算法的优缺点

  • 优点:
    1. 简单,易于理解,易于实现,无需估计参数,无需训练;
    2. 准确度一般较高
    3. 特别适合与多标签的问题,KNN比SVM的表现要好。
  • 缺点:
    1. 懒惰算法,对测试样本分类时的计算量大,内存开销大,评分慢;
    2. 当样本不平衡时,如一个类的样本容量很大,而其他类样本容量很小时,有可能导致当输入一个新的样本时,该样本的K个邻居中大容量的样本占多数。
    3. 可解释性差,无法给出决策树那样的规则

4.4.4 KNN常见的问题

  • K值的设定
    • 值选择过小,得到的近邻数过少,会降低分类精度,同时也会放大噪声数据的干扰;
    • 而如果k值选择过大,并且待分类样本属于训练集中包含数据数较少的类,那么在选择k个近邻的时候,实际上并不相似的数据亦被包含进来,造成噪声增加而导致分类效果的降低。
  • 类别的判定方式
    • 投票法没有考虑近邻的距离的远近,距离更近的近邻也许更应该决定最终的分类,所以加权投票法更恰当一些。
  • 距离度量方式的选择
    • 当变量数越多(高维),欧式距离的区分能力就越差;
    • 值域越大的变量常常会在距离计算中占据主导作用,因此应先对变量进行标准化。
  • 训练样本的参考原则
    • 减少训练集的大小
    • 通过聚类,将聚类所产生的中心点作为新的训练样本
  • 性能问题
    • kNN是一种懒惰算法,而懒惰的后果:构造模型很简单但在对测试样本分类地的系统开销大,因为要扫描全部训练样本并计算距离。
    • 已经有一些方法提高计算的效率,例如压缩训练样本量等

4.4.5 实现代码

import numpy as np
import math

class KNN:
    x_train = []
    x_pre = []
    k = 0
    def __init__(self,x_train,x_pre,k):
        self.x_train = x_train
        self.x_pre = x_pre
        self.k = k

    def computeDis(self,x,y):
        di = 0
        for i in range(len(x)-1):
           di += math.pow((x[i])-(y[i]),2) 
        return math.sqrt(di)

    def knnClassify(self):
        pre_calss = []
        for pre_data in self.x_pre:
            dis = []
            votes = {}
            for tra_data in self.x_train:
                dis.append(self.computeDis(pre_data,tra_data))
            print(len(dis))
            index = sorted(range(len(dis)),key=lambda m : dis[m])[:self.k]
            print(index)
            for i in index:
                label = self.x_train[i][-1]
                if label not in votes.keys():
                    votes[label] = 1
                else:
                    votes[label] += 1
            print(votes)
            pre_calss.append(max(votes,key=votes.get))

        result,pre=self.pre_values(pre_calss)
        return pre_calss,pre
    def pre_values(self,pre_calss):
        result = []
        for i in range(len(self.x_pre)):
            if pre_calss[i] == self.x_pre[i][-1]:
                result.append(1)
            else:
                result.append(0)
        return result,sum(result)/len(result)

4.5 朴素贝叶斯(Naive Bayes)

详细讲解博客
- 贝叶斯分类算法是统计学的一种分类方法,它是一类利用概率统计知识进行分类的算法。在许多场合,朴素贝叶斯(Naïve Bayes,NB)分类算法可以与决策树和神经网络分类算法相媲美,该算法能运用到大型数据库中,而且方法简单、分类准确率高、速度快。
- 但由于对数据特征条件独立的强假设,所以如果数据集不符合这种假设,准确率可能会较低。

重要假设:类条件独立

X = 特征

C = 类别

P(X|Ci)=k=1nP(xk|Ci) P ( X | C i ) = ∏ k = 1 n P ( x k | C i )

P(Ci|X)=P(X|Ci)P(Ci)P(X)=P(Ci)nk=1P(Xi|Ci)P(X) P ( C i | X ) = P ( X | C i ) P ( C i ) P ( X ) = P ( C i ) ∏ k = 1 n P ( X i | C i ) P ( X )

max(P(Ci|X)) m a x ( P ( C i | X ) )

- 优点:
- 算法逻辑简单,易于实现(算法思路很简单,只要使用贝叶斯公式转化即可!)
- 分类过程中时空开销小(假设特征相互独立,只会涉及到二维存储
- 缺点:
- 理论上,朴素贝叶斯模型与其他分类方法相比具有最小的误差率。但是实际上并非总是如此, 这是因为朴素贝叶斯模型假设属性之间相互独立,这个假设在实际应用中往往是不成立的,在属性个数比较多或者属性之间相关性较大时,分类效果不好。

4.6 支持向量机 (Suppport Vector Machine)SVM

参考博客
- 支持向量机(Support Vector Machine)是Vapnik等于1995年首先提出的,它在解决小样本、非线性及高维模式识别中表现出许多特有的优势,并能够推广应用到函数拟合等其他机器学习问题中。
- SVM是建立在统计学习理论的VC 维理论结构风险最小原理基础上的,根据有限的样本信息在模型的复杂性学习能力之间寻求最佳折衷,以期获得最好的推广(泛化)能力

结构风险最小化
  • 所谓VC维是对函数类的一种度量,可以简单的理解为问题的复杂程度,VC维越高,一个问题就越复杂。
  • 经验风险Remp(w):分类器在样本数据上的分类的结果与真实结果(因为样本是已经标注过的数据,是准确的数据)之间的差值。

引入置信风险:
1. 样本数量,给定的样本数量越大,学习结果越有可能正确,此时置信风险越小;
2. 分类函数的VC维,显然VC维越大,推广能力越差,置信风险会变大。

R(w) ≤ Remp(w) + Ф(h, n)

统计学习的目标从经验风险最小化变为了寻求经验风险与置信风险的和最小,即结构风险最小

SVM-最大间隔化:我们要找到的线离两边的数据要有尽可能大的间隔,而这就是支持向量机最大间隔化的思想。

关于g(x)=wx+b这个表达式要注意三点
1. 式中的x不是二维坐标系中的横轴,而是样本的向量表示。
2. 这个形式并不局限于二维的情况,在n维空间中仍然可以使用这个表达式,只是式中的w成为了n维向量;
3. g(x)不是中间那条直线的表达式,中间那条直线的表达式是g(x)=0,即wx+b=0,我们也把这个函数叫做分类面。

开发者自述:我是怎样理解支持向量机(SVM)与神经网络的

边界上的点就是支持向量,这些点很关键,这也是”支持向量机“命名的由来

SVM小结
  • 线性不可分:
    • 将数据空间映射到高维空间,使原本线性不可分变为线性可分;
    • 引入核函数,简化映射空间中的内积运算。它避开了直接在高维空间中进行计算,而表现形式却等价于高维空间;
    • 不同的样本结构与不同的核函数结合,达到很好的分割效果。
  • SVM只与少量支持向量相关,结构风险最小

4.7 人工神经网络(Artificial Neural Network)ANN + 感知机 + BP

4.7.1 ANN

参考资料

  • 人工神经网络(ANN,Artificial Neural Networks)是在人类对大脑神经网络认识理解的基础上,人工构造的能够实现某种功能的神经网络。

  • 它是理论化的人脑神经网络的数学模型,是基于模仿大脑神经网络结构和功能而建立起来的一种信息处理系统。

人工神经元模型:是一个多输入单输出的非线性阈值器件

  • 神经网络结构和工作机理基本上是以人脑的组织结构和活动规律为背景的,它反映了脑的某些基本特征,但并不是要对人脑部分的真正实现,可以说它是某种抽象、简化或模仿。

  • 如果将大量功能简单的形式神经元通过一定的拓扑结构组织起来,构成群体并行分布式处理的计算结构,那么这种结构就是人工神经网络,在不引起混淆的情况下,统称为神经网络。

  • 输入层:是网络与外部环境打交道的地方,它接收外部输入模式,并由输入单元传送给相连隐层各单元;

  • 隐层:是网络的内部处理单元层,神经网络具有模式变换能力,如模式分类、模式完善、特征抽取等,主要体现在隐层单元的处理。根据模式变换功能的不同,隐层可以有多层,也可以没有。由于隐层单元不直接与外部输入输出打交道,故通常将中间层称为隐层;

  • 输出层:是网络产生输出模式并与显示设备或执行机构打交道的地方。

学习技术

权值修正学派认为:神经网络的学习过程就是不断调整网络的连接权,以获得期望的输出。如何调整权值即学习规则的研究是一个非常重要的课题。

典型的权值修正方法:相关学习和误差修正学习。

  1. 相关学习:其思想最早是由Hebb作为假设提出,并已得到神经细胞学说的证实,人们称之为Hebb(海布)学习规则。

    Hebb学习规则可描述为:如果神经网络中某一神经元与另一直接和其连接的神经元同时处于兴奋状态,那么,这两个神经元的连接强度应该加强。

    Wji(t+1)=Wji(t)+η[Xi(t)Xj(t)] W j i ( t + 1 ) = W j i ( t ) + η [ X i ( t ) X j ( t ) ]

    式中, Wji(t+1) W j i ( t + 1 ) 表示修正一次后的某一权值;η是一个正常量,决定每次权值修正量,又称为学习因子; Xi(t) X i ( t ) Xj(t) X j ( t ) 分别表示t时刻第i、第j个神经元状态。

2) 误差修正学习法:

是神经网络中另一类更重要的方法,像感知机学习、BP网络学习均属此类。

最基本的误差修正学习方法,即δ学习规则,由4步描述:

(1)选择一组初始权值Wji ( 0);

(2)计算某一输入模式对应的实际输出与期望输出的误差;

(3)更新权值:
    $W_{ji} (t + 1) = W_{ji} (t) + η[ d_j -y_j(t) ] x_i(t)$
  式中,η为学习因子;$d_j$、$y_j$分别表示第j个神经元的期望输出与实际输出;`$x_i$`为第j个神经元的输入。

(4)返回步骤(2),直到对所有训练模式网络输出均能满足要求。

4.7.2 感知机模型

模型
  • 感知机是人们为了研究大脑的存贮、学习和认识过程而提出的一种神经网络模型。
  • 基本感知机是一个两层网络,分为输入层和输出层,每层可由多个处理单元构成。输入层单元接收外部输入模式,并传递给相连的输出层单元;输出层单元对所有输入值加权求和,经阈值性传递函数产生一组输出模式。
  • 通常输入、输出模式用二进制表示。两层之间为全互连方式,即输入层各单元与输出层各单元均有连接,且两层之间的连接权值是可调的。
学习过程
  • 感知机的学习是典型的监督学习,可以通过训练达到学习目的。训练的要素有两个:训练集和训练规则。训练集是由若干个输入-输出模式对构成的一个集合,所谓输入-输出模式对是指一个输入模式及其期望输出模式所组成的向量对
  • 在训练期间,不断用训练集中的每个模式对训练网络。当给定某一训练模式时,感知机输出单元会输出一个实际输出向量,用期望输出与实际输出之差来修正网络连接权值。权值的更新采用最简单的δ学习规则。
感知机简单实现
from random import randint
import numpy as np
import matplotlib.pyplot as plt

class SimplePerceptron:
    def __init__(self,train_data = [],real_result = [],eta=1):
        self.w = np.zeros([1,len(train_data.T)],int)
        self.b = 0
        self.eta = eta
        self.train_data = train_data
        self.real_result = real_result
    def nomalize(self,x):
        if x>0:
            return 1
        else:
            return -1
    def model(self,x):
        #martrix dot multiply
        y =np.dot(x,self.w.T)+self.b
        predict_v = self.nomalize(y)
        return predict_v,y
    def update(self,x,y):
        self.w = self.w+self.eta*y*x
        self.b = self.b+self.eta*y
    def loss(self,fx,y):
        return fx.astype(int)*y
    def train(self,count):
        update_count = 0
        while count >0:
            count -=1

            if len(self.train_data)<=0:
                print('Exception')
                break
            #random select train data
            index = randint(0,len(self.train_data)-1)
            x = self.train_data[index]
            y = self.real_result.T[index]

            predict_v,linear_y_v =self.model(x)
            if self.loss(y,linear_y_v)>0:
                continue
            update_count = update_count+1
            self.update(x,y)
            #每训练500次,画出当前分类拟合出的曲线
            if(update_count %500 == 0):
                plt.plot(self.train_data.T[0].tolist()[0], 
                         -(np.array(self.train_data.T[0].tolist()[0]).dot(float(self.w.T[0]))
                           +float(self.b))/float(self.w.T[1]), 
                         '--',
                         color='green',
                         alpha=0.5)
        print('update_count:',update_count)
        pass
    def verify(self,verify_data,verify_result):
        size = len(verify_data)
        failed_count = 0
        if size <= 0:
            pass
        for i in range(size):
            x = verify_data[i]
            y = verify_result.T[i]
            if self.loss(y,self.model(x)[1])>0:
                continue
            failed_count += 1
        success_rate = (1.0-(float(failed_count)/size))*100
        print('Success Rate:',success_rate,'%')
        print('All input:',size,"failed_count:",failed_count)

    def predict(self,predict_data):
        size = len(predict_data)
        result = []
        if size <=0:
            pass
        for i in range(size):
            x = perdict_data[i]
            result.append(self.model(x)[0])
        return result

4.7.3 BP

BP网络的产生归功于BP算法的获得。 BP算法属于δ算法,是一种监督式(有导师)的学习算法。

主要思想为:对于q个输入学习样本: P1,P2…,Pq,已知与其对应的输出样本为:T1,T2…,Tq。
学习的目的是用网络的实际输出A1,A2…,Aq与目标矢量T1,T2…,Tq之间的误差来修改其权值,使Ai,(i=1,2…,q)与期望的Ti尽可能地接近;即:使网络输出层的误差平方和达到最小
- 它是通过连续不断地在相对于误差函数斜率下降的方向上计算网络权值和偏差的变化而逐渐逼近目标的。
- 每一次权值和偏差的变化都与网络误差的影响成正比,并以反向传播的方式传递到每一层的。
- 正向传播:输入信息从输入经隐含层逐层计算传向输出层,每一层神经元的状态只影响下一层神经元的状态。
- 误差的反向传播:如果在输出层没有得到期望的输出,则计算输出层的误差变化值,然后转向反向传播,通过网络将误差信号沿原来的连接通路反传回来修改各层神经元的权值直至达到期望目标。

推导连接

python实现简单BP
import numpy as np

def nonlin(x,derive=False):
    '''
    实现sigmoid函数,deriv为Ture返回求导结果
    '''
    if(derive==True):
        return(x*(1-x))
    return(1/(1+np.exp(-x)))

X=np.array([[0,0,1],[0,1,1],[1,0,1],[1,1,1]])
y = np.array([[0,0,1,1]]).T
np.random.seed(1)
syn0=np.random.normal(size=(3,1))

for iter in range(1000):
    l0=X
    l1=nonlin(np.dot(l0,syn0))

    l1_loss = y-l1 #损失函数

    l1_delta = l1_loss*nonlin(l1,True) 

    syn0 += np.dot(l0.T,l1_delta)# 更新权值
'''    
l1=array([[0.03210593],
       [0.02569687],
       [0.97917487],
       [0.97394839]])
'''

4.8 集成学习

集成学习 (ensemble learning) 通过构建并结合多个学习器来完成学习任务。 集成学习的一般结构:先产生一组“个体学习器” (individual learner),再用某种策略将它们结合。若集成中只包含同种类型的个体学习器,这样的集成是“同质的” (homogeneous),同质集成中的个体学习器称为“基学习器” (base learner),相应的学习算法称为“基学习算法” (base learning algorithm)。集成也可以包含不同类型的个体学习器,即“异质的” (heterogenous)。

集成学习通过将多个学习器进行结合,通常可以获得比单一学习器显著优越的泛化性能。这对“弱学习器” (weak learner) 尤为明显。实际中,要获得好的集成,个体学习器通常应该“好二不同”,即个体学习器要有一定的“准确性”,并且要有“多样性”,即学习器间具有差异。

4.8.1 Bagging(随机森林就是其一个应用)

  • 基本思想:给定包含 m个样本的数据集,先随机取出一个样本放入采样集,再把该样本放回初始数据集,使得下次采样时该样本仍有可能被选中,经过 m 次随机采样,得到含 m 个样本的采样集,初始训练集中有的样本在采样集多次出现,有的则从未出现。这样可采样出 T 个含 m 个训练样本的采样集,然后基于每个采样集训练出一个基学习器,再将这些基学习器结合。这就是 Bagging 的基本流程。
  • 对预测输出进行结合时,Bagging 通常对分类任务使用简单投票法,对回归任务使用简单平均法。
  • 由于Bagging算法每次都进行采样来训练模型,因此泛化能力很强,对于降低模型的方差很有作用。当然对于训练集的拟合程度就会差一些,也就是模型的偏倚会大一些。

4.8.2 Boosting

  • 基本思想:Boosting 是一族可将弱学习器提升为强学习器的算法:先从初始训练集训练出一个基学习器,再根据基学习器的表现对训练样本进行调整,使得先前基学习器做错的训练样本在后续受到更多的关注,然后基于调整后的样本训练下一个基学习器,如此重复进行,直至基学习器达到事先指定的值,最终将这 T 个基学习器进行加权结合。

4.8.3 Stacking

  • 基本思想:Stacking先从初始数据集训练出初级学习器,然后生成一个新数据集用于训练次级学习器。在这个新数据集中,初级学习器的输出被当作样例输入特征,而初始样本的标记仍被当作样例标记

4.9 分类器的评价标准

A\PrC-C
CTPFNP
-CFPTNN
p’N’ALL

A : 实际的类

Pr : 预测的类

TP:真正例,被正确分类的正样本

TN:真负例,被正确分类的负样本

FP:假正例,被错误分类的负样本

FN:假负例,被错误分类的正样本

P:正样本数;   N:负样本数

P':被分类器标记为正的样本数

N':被分类器标记为负的样本数
  • 准确度: Accuracy=TP+TNALL A c c u r a c y = T P + T N A L L

  • 误差率: Errorrate=FP+FNALL=1ACC E r r o r r a t e = F P + F N A L L = 1 − A C C

  • 精度:被分类器标记为正类的样本实际为“正类”的比例 precision=TPTP+FP p r e c i s i o n = T P T P + F P

  • 召回率:正样本标记为正的百分比 recall=TPTP+FN r e c a l l = T P T P + F N

  • F 度量:精度和召回率的调和平均值 F=2×precision×recallprecision+recall F = 2 × p r e c i s i o n × r e c a l l p r e c i s i o n + r e c a l l

类分布不平衡的问题
  • 灵敏度:正确识别的正样本的百分比 TPP T P P
  • 特效性:正确识别的负样本的百分比 TNN T N N

Chapter 5 聚类分析(Cluster Analysis)

5.1 认识聚类

  • 聚类就是将数据分为多个簇,使得在同一个簇内对象之间具有较高的相似度,而不同簇之间的对象差别较大
  • 探索数据内部潜在的自然分组结构
  • 无监督学习
  • 聚类分析的意义
    • 聚类分析是获得数据内部结构的有效方法。通过观察聚类得到的每个簇的特点,可以集中对特定的某些簇作进一步分析。这在诸如市场细分、目标顾客定位、业绩估评、生物种群划分、城市规划等方面具有广阔的应用前景。
    • 聚类分析可以作为其它算法的预处理步骤:利用聚类进行数据预处理,可以获得数据的基本概况,在此基础上进行特征抽取或分类就可以提高精确度和挖掘效率。也可将聚类结果用于进一步关联分析,以获得进一步的有用信息。
    • 聚类分析可以完成噪声点/孤立点的挖掘:许多数据挖掘算法试图使孤立点影响最小化,或者排除它们。然而孤立点本身可能是非常有用的。如在欺诈探测中,孤立点可能预示着欺诈行为的存在。许多聚类分析算法都具有噪声点检测的功能。
  • 聚类分析的目的:寻找数据中潜在的自然分组结构

5.1.1 聚类算法分类

  • 划分方法(partitioning method)
  • 层次方法(hierarchical method)
  • 基于密度的方法(density-based method)
  • 基于网格的方法(grid-based method)
划分方法
  • 给定一个有n个对象的数据集,划分聚类技术将构造数据k个划分,每一个划分就代表一个簇,k<=n。也就是说,它将数据划分为k个簇,而且这k个划分满足下列条件:
    • 每一个簇至少包含一个对象。
    • 每一个对象属于且仅属于一个簇
  • 基本思路:对于给定的k,算法首先给出一个初始的划分方法,以后通过反复迭代的方法改变划分,使得每一次改进之后的划分方案都较前一次更好。经典的算法有:K-Means(K-均值), K-Medoids(K-中心点)等 。
K-means
  • 目标:将数据集D划分为K个互不相容的簇,使得簇内对象互相相似,簇之间差异大
  • 聚类目标函数:簇对象到簇中心平方误差准则最小
    • E=ki=1xCi|xxi|2 E = ∑ i = 1 k ∑ x ∈ C i | x − x i | 2
    • xi x i 为第i个簇的均值, Ci C i 代表第i个簇
  • 简单实现过程

    随机选择K个点作为初始质心  
    repeat  
        将每个点指派到最近的质心,形成K个簇  
        重新计算每个簇的质心  
    until 簇不发生变化或达到最大迭代次数 
    
  • 优点
    • 经典算法、简单、快速
    • 对处理大数据,该算法是相对可伸缩和高效率的
  • 缺点
    • 必须事先给出k
    • 对初值敏感,不同的初始值,可能会导致不同的结果
    • 不适合于发现非球形状的簇或者大小差别很大的簇
    • 对于“噪声”和孤立点是敏感的
  • python实现代码:
import numpy as np
import pandas as pd

class KMeansCluster():
    def __init__(self,k=3,initCent='random',max_iter=500):
        self._k = k
        self._initCent = initCent
        self._max_iter = max_iter
        self._clusterAssment = None
        self._labels = None
    #计算欧式距离  
    def _calEDist(self,arrA,arrB):
        return np.math.sqrt(sum(np.power(arrA - arrB, 2)))
    #随机选择K个中心点
    def _randCent(self,data_X,k):
        n = data_X.shape[1]
        centroids = np.empty((k,n))
        for j in range(n):
            minJ = min(data_X[:,j])
            rangeJ = float(max(data_X[:,j]-minJ))
            centroids[:,j] = (minJ+rangeJ*np.random.rand(k,1)).flatten()
        return centroids
    #更新聚类中心点直到收敛
    def fit(self,data_X):
        if not isinstance(data_X,np.ndarray) or isinstance(data_X,np.matrixlib.defmatrix.matrix):
            try:
                data_X = np.asarray(data_X)
            except:
                raise TypeError('numpy.darray resuird for data_X')
        m = data_X.shape[0]
        #一个m*2的二维矩阵,矩阵第一列存储样本点所属的族的索引值,
        #第二列存储该点与所属族的质心的平方差
        self._clusterAssment = np.zeros((m,2))

        if self._initCent == 'random':
            self._centroids = self._randCent(data_X,self._k)

        clusterChanged = True
        for _ in range(self._max_iter):
            clusterChanged = False
            for i in range(m):#将每个样本点分配到离它最近的质心所属的族
                minDist = np.inf #首先将其置为无穷大的数
                minIndex = -1 #将最近的质心点下标置为-1
                for j in range(self._k):
                    arrA = self._centroids[j,:]
                    arrB = data_X[i,:]
                    distJI = self._calEDist(arrA,arrB)
                    if distJI<minDist:
                        minDist = distJI
                        minIndex = j
                if self._clusterAssment[i,0]!=minIndex or self._clusterAssment[i,1]>minDist**2:
                    clusterChanged = True 
                    self._clusterAssment[i,:]=minIndex,minDist**2
            if not clusterChanged:
                break
            for i in range(self._k):
                index_all = self._clusterAssment[:,0]
                value = np.nonzero(index_all == i)
                ptsInClust = data_X[value[0]]
                self._centroids[i,:]=np.mean(ptsInClust,axis=0)
        self._labels =self._clusterAssment[:,0]
K—中心点(K-medoids)
  • 出发点:利用代表性的对象(中心点),而不是均值代表每个簇,又称PAM算法(Partitioning Around Medoids)
  • 基本思路
    1. 为每个簇随机选择一个代表对象(中心点);
    2. 剩余的对象根据其与代表对象的距离分配给与其最近的一个簇;
    3. 反复地用非代表对象来替换代表对象,以提高聚类的质量,直至找到最合适的中心点。
  • 我们要选取一个最小的代价,显然有多种替换可以选择,选择第一个最小代价的替换,一直重复上述过程,直到代价不再减小为止。
  • 优点:相比于K-means,对于孤立点数据没有那么敏感
  • 缺点:时间复杂度很高,很难处理大规模数据
层次聚类方法
  • 层次聚类方法对给定的数据集进行层次的分解,直到某种条件满足为止。具体又可分为:
    • 凝聚的层次聚类:一种自底向上的策略,首先将每个对象作为一个簇,然后合并这些原子簇为越来越大的簇,直到某个终结条件被满足。(AGNES算法)
    • 分裂的层次聚类:采用自顶向下的策略,它首先将所有对象置于一个簇中,然后逐渐细分为越来越小的簇,直到达到了某个终结条件。(DIANA算法)
  • AGNES:AGNES (AGglomerative NESting)算法最初将每个对象作为一个簇,然后这些簇根据某些准则被一步步地合并。两个簇间的相似度由这两个不同簇中距离最近的数据点对的相似度来确定。聚类的合并过程反复进行直到所有的对象最终满足簇数目。
  • DIANA:是典型的分裂聚类方法。
    在聚类中,用户能定义希望得到的簇数目作为一个结束条件。同时,它使用下面两种测度方法:
    • 簇的直径:在一个簇中的任意两个数据点的距离中的最大值。
    • 平均相异度(平均距离):
基于密度的聚类方法
  • 密度聚类方法的指导思想是,只要一个区域中的点的密度大于某个阈值,就把它加到与之相近的聚类中去。这类算法能克服基于距离的算法只能发现“类圆形”的聚类的缺点,可发现任意形状的聚类,且对噪声数据不敏感。但计算密度单元的计算复杂度大,需要建立空间索引来降低计算量,且对数据维数的伸缩性较差。这类方法需要扫描整个数据库,每个数据对象都可能引起一次查询,因此当数据量大时会造成频繁的I/O操作。代表算法有:DBSCAN、OPTICS、DENCLUE算法等。
DBSCAN
  • DBSCAN(Density-Based Spatial Clustering of Applications with Noise)一个比较有代表性的基于密度的聚类算法。与划分和层次聚类方法不同,它将簇定义为密度相连的点的最大集合,能够把具有足够高密度的区域划分为簇。

  • DBSCAN算法可以利用类的高密度连通性,快速发现任意形状的类

    • 在一个数据空间中,高密度区总是被低密度区所分割
    • 它能够从含有噪音的空间数据中发现任意形状的聚类
  • 基本思想
    • 对于一个类中的每个对象,在其给定半径的领域中包含的对象不能少于某一给定的最小数目
    • 在DBSCAN中,发现一个类的过程是基于这样的事实:一个类能够被其中的任意一个核心对象所确定
  • 基本定义
    • 对象的ε-邻域:给定对象在半径ε内的区域
    • 核心对象:如果一个对象的ε-邻域至少包含最小数目MinPts个对象,则称该对象为核心对像
    • 直接密度可达:给定一个对象集合D,如果p是在q的ε-邻域内,而q是一个核心对象,我们说对象p从对象q出发是直接密度可达的
    • 密度可达:如果存在一个对象链p1,p2,…,pn,p1=q,pn=p,对pi∈D,(1<=i<=n),pi+1是从pi关于ε和MitPts直接密度可达的,则对象p是从对象q关于ε和MinPts密度可达的。
    • 密度相连:如果对象集合D中存在一个对象o,使得对象p和q是从o关于ε和MinPts密度可达的,那么对象p和q是关于ε和MinPts密度相连的。
    • 噪声:一个基于密度的簇是基于密度可达性的最大的密度相连对象的集合。不包含在任何簇中的对象被认为是“噪声”。

举例
image

由上图可看出m,p,o.r 都是核心对象,因为他们的内都只是包含3个对象。

  1. 对象q是从m直接密度可达的。对象m从p直接密度可达的。

  2. 对象q是从p(间接)密度可达的,因为q从m直接密度可达,m从p直接密度可达。

  3. r和s是从o密度可达的,而o是从r密度可达的,所有o,r和s都是密度相连的。

    • 基本流程:DBSCAN通过检查数据集中每个对象的ε-邻域来寻找聚类。如果一个点p的ε-邻域包含多于MinPts个对象,则创建一个p作为核心对象的新簇。然后,DBSCAN反复地寻找从这些核心对象直接密度可达的对象,这个过程可能涉及一些密度可达簇的合并。当没有新的点可以被添加到任何簇时,该过程结束。具体如下:

    DBSCAN算法描述
    算法5-5 DBSCAN
    输入:包含n个对象的数据库,半径ε,最少数目MinPts。
    输出:所有生成的簇,达到密度要求。

    1. REPEAT
    2. 从数据库中抽取一个未处理过的点;
    3. IF 抽出的点是核心点 THEN找出所有从该点密度可达的对象,形成一个簇
    4. ELSE 抽出的点是边缘点(非核心对象),跳出本次循环,寻找下一点;
    5. UNTIL 所有点都被处理;

Eg:
下面给出一个样本事务数据库(见左表),对它实施DBSCAN算法。
根据所给的数据通过对其进行DBSCAN算法,以下为算法的步骤(设n=12,用户输入ε=1,MinPts=4)  

序号xy步骤选择的点在ε中的点数通过计算可达的点而找到的新簇
110112
240222
301333
411445 C1 C 1 :{1,3,4,5,9,10,12}
521553已在 C1 C 1
631663
741775 C2 C 2 :{2,6,7,8,11}
851882已在 C2 C 2
902993已在 C1 C 1
101210104已在 C1 C 1
114211112已在 C2 C 2
121312122已在 C1 C 1

1. 第1步,在数据库中选择一点1,由于在以它为圆心的,以1为半径的圆内包含2个点(小于4),因此它不是核心点,选择下一个点。
2. 第2步,在数据库中选择一点2,由于在以它为圆心的,以1为半径的圆内包含2个点,因此它不是核心点,选择下一个点。
3. 第3步,在数据库中选择一点3,由于在以它为圆心的,以1为半径的圆内包含3个点,因此它不是核心点,选择下一个点。
4. 第4步,在数据库中选择一点4,由于在以它为圆心的,以1为半径的圆内包含5个点,因此它是核心点,寻找从它出发可达的点(直接可达4个,间接可达2个),聚出的新类{1,3,4,5,9,10,12},选择下一个点。
5. 第5步,在数据库中选择一点5,已经在簇1中,选择下一个点。
6. 第6步,在数据库中选择一点6,由于在以它为圆心的,以1为半径的圆内包含3个点,因此它不是核心点,选择下一个点。
7. 第7步,在数据库中选择一点7,由于在以它为圆心的,以1为半径的圆内包含5个点,因此它是核心点,寻找从它出发可达的点,聚出的新类{2,6,7,8,11},选择下一个点。
8. 第8步,在数据库中选择一点8,已经在簇2中,选择下一个点。
9. 第9步,在数据库中选择一点9,已经在簇1中,选择下一个点。
10. 第10步,在数据库中选择一点10,已经在簇1中,选择下一个点。
11. 第11步,在数据库中选择一点11,已经在簇2中,选择下一个点。
12. 第12步,选择12点,已经在簇1中,由于这已经是最后一点所有点都已处理,程序终止。

  • 优点
    • 可以发现任意形状的簇
    • 对噪声数据不敏感
  • 缺点
    • 对参数EPS和Minspt非常敏感,但这两个参数主要是依靠主观判断
    • 数据库比较大的时候,会进行大量的I/O开销
网格聚类
  • 基本思想:将对象空间量化为有限数目的单元,形成一个网格结构,所有的聚类都在这个网格结构中上进行。
  • 其优点是处理速度很快,其处理时间独立于数据对象的数目,只与量化空间中每一维的单元数目有关。
  • 在网格聚类方法中有利用存储在网格单元中的统计信息进行聚类的STING算法和在高维数据空间基于网格和密度的聚类方法等。
STING算法
  • STING(Statistaical Information Grid_based method)是一种基于网格的多分辨率聚类技术,它将空间区域划分为矩形单元。针对不同级别的分辨率,通常存在多个级别的矩形单元,这些单元形成了一个层次结构:高层的每个单元被划分为多个低一层的单元。高层单元的统计参数可以很容易的从底层单元的计算得到。这些参数包括属性无关的参数count、属性相关的参数m(平均值)、s(标准偏差)、min(最小值)、max(最大值)以及该单元中属性值遵循的分布类型。
  • STING算法采用了一种多分辨率的方法来较粗,则聚类质量会受到影响。进行聚类分析,该聚类算法的质量取决于网格结构最低层的粒度。如果粒度比较细,处理的代价会显著增加;但如果粒度

离群点(孤立点)检测

参考
- 离群点是一个数据对象,它显著不同于其它数据对象,好像它是被不同的机制产生的一样
- 离群点类型
- 全局离群点:给定数据集中,如果它显著偏离数据集中的其余对象,则成为全局离群点。
- 局部离群点(又称情景离群点):在给定数据集中,如果关于对象的特定情境,它显著偏离其他对象,则称为情景离群点。
- 集体离群点:在给定数据集中,如果这些对象作为整体显著偏离整个数据集,则数据集的这个子集为集体离群点
- 在有些应用领域识别异常数据是许多工作的基础和前提,异常数据会带给我们新的视角。 如在欺诈检测中,异常数据可能意味欺诈行为的发生,在入侵检测中异常数据可能意味入侵行为的发生。

  • 离群点分析
    • 统计学方法
    • 基于距离的方法
    • 基于偏差的方法
    • 基于密度的方法
基于统计学的孤立点检测
  • 基本思想:对给定的数据集合假设了一个分布或概率模型(例如, 正态分布), 然后根据模型采用不一致性检验(discordancy test)来确定孤立点
  • 检验要求的参数

    • 数据集参数:例如,假设的数据分布
    • 分布参数:例如平均值和方差
    • 和预期的孤立点数目
  • 缺点

    • 绝大多数检验是针对单个属性的, 而许多数据挖掘问题要求在多维空间中发现孤立点
    • 统计学方法要求关于数据集合参数的知识(如, 数据分布), 但是在许多情况下, 数据分布可能是未知的
    • 当没有特定的检验时, 统计学方法不能确保所有的孤立点被发现; 或者观察到的分布不能恰当地被任何标准的分布来模拟
基于距离的孤立点检测
  • 基于距离的孤立点: DB (p, d)-孤立点是数据集T 中的一个对象o, 使得 T 中的对象至少有p 部分与o 的距离大于d。
  • 将基于距离的孤立点看作是那些没有“足够多”邻居的对象. 这里的邻居是基于距给定对象的距离来定义的 。
  • 对许多不一致性检验来说, 如果一个对象 o根据给定的检验是一个孤立点, 那么对恰当定义的p和d,o也是一个DB(p,d) 孤立点。
基于偏离的孤立点检测
  • 基本思想:通过检查一组对象的主要特征来确定孤立点 ,如果与给出的描述偏离大的对象被认为是孤立点 。
基于密度的方法

Chapter 6 大数据分析

6.1 哈希技术

数据流挖掘

  • 什么是数据流:是数据对象的大量序列,有以下特征
    • 一个接一个(One by One)
    • 潜在的无限的(Potentially Unbounded)
    • 概念偏移(Concept Drift)
  • 数据流挖掘的挑战
    • 时间,空间维度的简单实时
    • 概念漂移
  • 概念漂移:基于数据的类别变化(P(C|X))
  • 概念漂移检测
    • 基于分布的检测(Distribution-based detector):监视数据在两个固定窗口或自适应窗口之间的分布变化,但很难决定窗口的大小,学习概念漂移会很慢
    • 基于错误率(Error-rate based detector):基于分类性能变化的捕获概念漂移,但对噪声敏感,难以处理渐进缓慢的概念漂移,太对依靠模型自身
  • 数据流分类
    • 要求:1.数据只处理一次。2.随时准备预测。3.用有限的内存。4.工作在有限的时间
    • VFDT
  • 数据流聚类

Hadoop/Spark

Hadoop
  • Hadoop is a software framework for distributed processing of large datasets across large clusters of computers
    • Large datasets —>Terabytes or petabytes of data
    • Large clusters —> hundreds or thousands of nodes
  • Hadoop is based on a simple programming model called MapReduce
  • Hadoop is based on a simple data model, any data will fit
Spark
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值