空间co-location模式挖掘基于全连接Join-Base原理与实现


  简单来说该文章就是将apriori算法应用到空间模式的挖掘,将事务篮子换为co-location模式,将事务等价为行实例和表实例。引入参与率和参与度来等价支持度。频繁项的挖掘和关联规则的生成还是遵循apriori算法的步骤和核心思想,即先验原理(频繁模式的子集一定是频繁的,非频繁模式的超集一定是不频繁的)。

基本理论知识

空间特征

  空间特征(或称空间对象、属性),代表了空间中不同种类的事物。空间特征代表了空间中不同种类的事物的集合。记为F = {f1, f2, f3, …, fn}。把一个具体空间位置上的对象称为空间实例。将实例的集合称为实例集,记为 S = S1 U S2 U …Sn,其中Si(1<=i<=n)是对应空间特征fi的实例集合。

  一个具体空间位置上的对象称为对象的空间实例。如A1,2,3,4为A的实例。 如空间中有四个空间特征F={A,B,C,D}.空间特征A有4个实例A1到A4,B有5个实例B1到B5,C有3个实例。

邻近关系

  空间邻近关系:描述了空间实例之间的空间关系。可以是拓扑、距离、混合关系。空间邻近关系需要满足自反性和对称性。
  以距离关系为例,空间邻近关系R为欧式距离小于等于阈值d,表示为:

  分布图中一个完全联通子图就是一个团。如{A3,B3,C1,D1}就是一个团

空间co-location模式

  一组空间特征集合c,其中c⊆F。如图中{A,B,C}就是一个co-location模式。

行实例和表实例

  行实例表示团包含了co-location模式c中的所有特征,并且它的子集不包含c中的所有特征。co-location模式c中的所有行实例集合为表实例。
  co-location模式c的长度称为co-location模式的阶。如co-location{A,B,C}的阶为3。
如:
  例如:假设{A3,C1,C3}都满足两两邻近,但是不是co-location{A,C}的行实例
   co-location{A,B,C}的行实例为{A2,B4,C5}和{A3,B3,C1}。所以表实例为{{A2,B4,C5},{A3,B3,C1}}

参与率与参与度

  简单来说就是数据挖掘里面的支持度,在空间数据挖掘中引入参与率
  参与率表示为PR(c,fi),它是fi的实例在空间co-location模式c的所有实例中不重复出现的个数与fi总实例个数的比率。

其中Π是关系投影

  参与度表示为PI(c),它是空间co-location模式c的所有空间特征的PR值中的最小值。

  min_prev是用户给定的最小参与度(最小频繁性)阈值,当PI©>=min_prev 时,称为co-location模式c是频繁的。

co-location规则

  c1 => c2(p,cp)称为co-location规则,其中c1和c2是co-location模式,c1∩c2不等于空集,p是规则参与度,cp是规则的条件概率。
  条件概率cp是从co-location模式c1推出co-location模式c2的可信度

主要步骤

类似于关联规则挖掘,大多数co-location挖掘算法通常将挖掘任务分解为如下两个子任务:

  1. 频繁co-location产生:其目标是发现满足最小参与度阈值min_prev的所有co-location模式。
  2. co-location规则产生:其目标是从上一步发现的频繁co-location模式中提取所有高条件概率的规则。

全连接算法Join-Base:

  • 候选co-location的生成:由频繁k阶模式,生成k+1阶候选模式,在判断是否频繁,过程类比apriori算法
  • 表实例的生成:k阶模式c1和k阶模式c2连接得到k+1阶候选模式c3,则候选模式c3的表实例是由模式c1的表实例和模式c2的表实例按前k-1个特征相同进行链接,同时要求最后两个实例满足邻近关系R。

书中给出的算法步骤

代码实现

我是基于python实现的,算法步骤与书中给出的步骤有一点出入
说明:
P是频繁项,C是候选项,T_cu是未判断是否满足参与率的表实例集合,T是满足参与率的表实例集合。
首先导入需要用到的包

import itertools
import copy
import math
import numpy as np
import matplotlib.pyplot as plt

准备好需要用到的数据

min_prev = 0.3 #最小参与率
min_conf = 0.3 #最小置信度
ET = ["A","B","C","D"]
E = [["A",1,[24,14]]
    ,["A",2,[64,44]]
    ,["A",3,[46,24]]
    ,["A",4,[63,7]]
    ,["B",1,[13,3]]
    ,["B",2,[19,45]]
    ,["B",3,[47.5,10.5]]
    ,["B",4,[62,52]]
    ,["B",5,[13,50]]
    ,["C",1,[39,11]]
    ,["C",2,[52,50]]
    ,["C",3,[40,36]]
    ,["D",1,[40,20]]
    ,["D",2,[6,10]]]
R = 16 #设最小邻近关系的距离为16

将数据做可视化,看一下数据的基本关系

#定义可视化函数,方便查看数据之间的关系
def drawData(E,R):
    values=[x[2] for x in E]
    x = np.array(values)[:,0]
    y = np.array(values)[:,1]
    n = [x[0]+str(x[1]) for x in E]
    fig,ax=plt.subplots(figsize=(12, 7))
    ax.scatter(x,y)
    for i,txt in enumerate(n):
        ax.annotate(txt,(x[i],y[i]))
    for i in range(len(values)-1):
        for j in range(i+1,len(values)):
            if math.sqrt((values[j][0]-values[i][0])**2 + (values[j][1]-values[i][1])**2) < R:
                ax.plot([values[i][0],values[j][0]],[values[i][1],values[j][1]])

执行一下,展示

drawData(E,R)

展示图像如下:
在这里插入图片描述
这是我自己参考书中图像构造的数据集,方便与书中结果比对

下面定义几个基本函数和类
获取空间实例E中每个实例出现的次数,方便后面求参与率

def get_count_ET(E,ET):
    count = {}
    for i in ET:
        count[i] = 0
        for j in E:
            if j[0] == i:
                count[i] += 1
    return count

测试一下

get_count_ET(E,ET)

输出为:{‘A’: 4, ‘B’: 5, ‘C’: 3, ‘D’: 2}

判断两个实例之间是否相邻
```python
#判断两个实例之间是否相邻
def isNiber(instance1,instance2,R):
    distance = ((instance1[2][0] - instance2[2][0]) ** 2 + (instance1[2][1] - instance2[2][1]) ** 2) ** 0.5
    if distance <= R:
        return 1
    else:
        return 0

计算该模式下各个实例的参与度

def get_canyudu(P,count_ET):
    canyudu = 1 #设置一个最大参与率
    for key in P.keys():
        canyulv = P[key]/count_ET[key]
        if canyulv < canyudu: #这里判断用于返回最下参与率
            canyudu = canyulv
    return canyudu

直接根据空间实例E和空间邻近关系R生成2阶表实例

def createT2(E,R):
    T2 = []
    E_len = len(E)
    for i in range(E_len-1):
        for j in range(i,E_len):
            if E[i][0]!=E[j][0] and isNiber(E[i],E[j],R):
                instance = []
                instance.append(E[i][0]+','+str(E[i][1]))
                instance.append(E[j][0]+','+str(E[j][1]))
                T2.append(instance)
    T_dic = Table_2_Tdic(T2)
    return T_dic

将表实例如[A1,B2]转换为表实例类{ A,B : [A1,B2] }

def Table_2_Tdic(T):
    table = {}
    for l in T:
        co = ""
        row_instance = []
        l_len = len(l)
        for i in range(l_len):
            if i != l_len-1:
                co += str(l[i]).split(',')[0] + ','
            else:
                co += str(l[i]).split(',')[0]
            row_instance.append(str(l[i]))
        if str(co) not in table.keys():
            table[str(co)] = [row_instance]
        else:
            table[str(co)].append(row_instance)
    # print(table)
    return table

由k-1阶满足参与率的表实例集生成k阶粗表实例集

def T_2_Tk(T,k):
    T_list = []
    keys = list(T.keys())
    keys.sort()
    keys_len = len(keys)
    for i in range(keys_len-1):
        if keys[i].split(',')[:-1] != keys[i+1].split(',')[:-1]:
            continue
        for j in range(i+1,keys_len):
            if keys[j].split(',')[:-1] == keys[i].split(',')[:-1]:
                for instance_i in T[keys[i]]:
                    for instance_j in T[keys[j]]:
                        if instance_i[:-1] == instance_j[:-1]:
                            tem = []
                            tem.extend(instance_i)
                            tem.append(instance_j[-1])
                            T_list.append(tem)
            else:
                break
    Tk = T_list.copy()
    for C_Tlist in T_list:
        for c in itertools.combinations(C_Tlist, k-1):
            c = list(c)
            c_len = len(c)
            co = ""
            row_list = []
            for i in range(c_len):
                if i != c_len-1:
                    co += c[i].split(",")[0]+','
                else:
                    co += c[i].split(",")[0]
                row_list.append(c[i])
            if co not in T.keys() or row_list not in T[co]:
                Tk.remove(C_Tlist)
                break
    T_dic = Table_2_Tdic(Tk)
    return T_dic

由k阶粗表实例集和k阶候选集以及最小参与率生成k阶频繁项集和满足参与率的表实例集

def Tk_2_Pk(T_dic, count_ET, min_prev):
    Pk = []
    T = {}
    keys = list(T_dic.keys())
    keys.sort()
    for key in keys:
        key_list = key.split(",")
        p = {}
        key_len = len(key_list)
        for i in range(key_len):
            p[key_list[i]] = len(set([wai[i] for wai in T_dic[key]]))
        canyudu = get_canyudu(p, count_ET)
        if canyudu >= min_prev:
            T[key] = T_dic[key]
            Pk.append(key_list)
    return T, Pk

由k阶频繁模式P,生成k+1阶候选模式C

def P_2_Ck(P):
    C = []
    p_len = len(P)
    for i in range(p_len):
        for j in range(i+1,p_len):
            if P[j][:-1] == P[i][:-1]:
                temp = []
                temp.extend(P[i])
                temp.append(P[j][-1])
                C.append(temp)
    return C

整合运行一下

if __name__ == '__main__':
    min_prev = 0.3  # 最小参与率
   	ET = ["A", "B", "C", "D"]
    E = [["A", 1, [24, 14]]
        , ["A", 2, [64, 44]]
        , ["A", 3, [46, 24]]
        , ["A", 4, [63, 7]]
        , ["B", 1, [13, 3]]
        , ["B", 2, [19, 45]]
        , ["B", 3, [47.5, 10.5]]
        , ["B", 4, [62, 52]]
        , ["B", 5, [13, 50]]
        , ["C", 1, [39, 11]]
        , ["C", 2, [52, 50]]
        , ["C", 3, [40, 36]]
        , ["D", 1, [40, 20]]
        , ["D", 2, [6, 10]]]
    R = 16  # 设最小邻近关系的距离为16
    # drawData(E, R)
    count_ET = get_count_ET(E, ET)
    k = 2
    T_C = createT2(E, R)
    C = list(T_C.keys())
    C.sort()
    print("C2")
    print(C)
    T, P = Tk_2_Pk(T_C, count_ET, min_prev)
    print("T2")
    for i in T.keys():
        print(i, T[i])
    print("P2")
    print(P)
    while (1):
        k += 1
        C = P_2_Ck(P)
        if len(C) == 0:
            break
        print("C{}".format(k))
        print(C)
        T_C = T_2_Tk(T, k)
        T, P = Tk_2_Pk(T_C, count_ET, min_prev)
        if bool(T):
            print("T{}".format(k))
            for i in T:
                print(i, T[i])
        if bool(P):
            print("P{}".format(k))
            print(P)

运行结果:
在这里插入图片描述

注:我没有写生成co-location规则的函数,所以这里没有产生规则,产生规则只需要从频繁项集中取子集,然后到表实例集中查找出现的次数,最后求出其概率就可以了

以上就是基于全连接的co-location模式挖掘,希望对你有帮助。

  • 8
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值