[论文阅读]TANE: An Efficient Algorithm for Discovering Functional and Approximate Dependencies

TANE:发现函数和近似依赖关系的有效算法

函数依赖:如果我们把这种先有数据规律后再产生数据的过程称为正向过程的话,那么FD挖掘过程中更多的应用在于“反向过程”:即从大量数据中,挖掘数据之间存在的一种“决定与被决定”的关系。函数依赖可以降低数据库的冗余,增强信息的一致完整性。

i.生成并测试候选集的方法:总体策略同Apriori算法,具体处理某一结点的做法是基于属性集X的具体不同取值而将元组集划分等价类。

ii.最小覆盖(The Minimal Cover)方法从原始关系中提取一个简化的划分,然后使用这样的划分,计算一致的元组集合,并生成最大一致元组集,最后根据最大一致元组集可以找到最小FD 

iii.规范概念分析(Formal Concept Analysis)方法根据关系数据库理论与规范概念分析之间的关系,使用预定义的规范概念分析闭集操作符来提取数据库中成立的函数依赖。

本文要介绍的算法TANE就是属于生成并测试候选集的方法。

总结:

本文需要大量引理的推导,理解起来比较困难,需要结合大量的例子才能很好的理解,如果有空,可以去github上下载一份代码来阅读一下,这样能够更加容易的理解代码。

本文的一些基本性质:

等价类:属性集X的某一等价类[t]_X是指在给定关系实例中,所有与元组t在X上取值相等的元组的集合

划分:属性集X上的划分的\Pi_X的含义是在给定关系实例r中,X的所有等价类的集合。就是说\Pi_X是一组不相交的元组的集合(等价类)的集合。这样,每个集合(等价类)内部的元组在属性集X中的取值是相等的,并且,这些集合的并集就等于关系实例r。

集合的阶:指集合中所含元素个数,集合S的阶记为|S|,比如等价类[t]_X的阶|[t]_X| ,表明等价类内有多少个元组。划分的阶|\Pi_X|指的是划分\Pi_X的内部有多少个等价类

精简划分:X的精简划分\widehat{\Pi_X}是指在划分\Pi_X的基础上去除所有阶为1的等价类后的划分

等价类:[1]_{\{A\}} = [2]_{\{A\}} = \{1,2 \}     划分:\Pi_D={{1,4,7},{2},{3},{5},{6},{8}}      精简划分:\widehat{\Pi_D}={{1,4,7}}

右方集C^+(X)定义:C^+(X)={A∈R |∀B∈X: X \ {A,B}→{B}不成立}。即:A \in C^+(X)是指对R中任意属性A,如果属性集X中除去属性A,则X内部不存在着任何非平凡函数依赖。

A \in C^+(X),并且X\{A}→A成立,则我们可以认为X\{A}→A是最小非平凡函数依赖。

C^+(X)的剪枝依据:按照C^+(X)的含义,当C^+(X) = \o时,即R中的任一属性在属性集X\{A}里,仍会出现函数依赖,因此无论如何,\forall B \in X:X\{A,B}→B都不是最小函数依赖,故X集以及X的任何真超集都可不用计算,从而将X剪枝

键剪枝: 如果不能检测出属性集X是一个键或超键,则任意A\inR\X,非平凡函数依赖X→A成立,且X的任意真超集Y,都有任意\forall B \in R,X\{A,B}→B成立,但Y→B并非最小函数依赖,故X的任意真超集都不用计算,从而可以剪去键Y

如何判断函数依赖:

划分细化的概念:当划分\Pi_X中的每个等价类都是划分\Pi_A中相应唯一一个等价类的子集时,我们称划分\Pi_X细化了划分\Pi_A

FD判断依据1:当且仅当\Pi_X细化划分\Pi_A时,函数依赖X→A成立

如果每种颜色代表一个等价类的话,则左图\Pi_X细化了\Pi_A,但右图由于元组5的存在,所以\Pi_X并非细化\Pi_A。再细想,若\Pi_X划分细化\Pi_A,那么必有|\Pi_X| = |\Pi_{X\cup \{A\}}|,这是说,{X\cup \{A\}}所含有的种种要素的等价类的个数与X含有的等价类的个数是相等的,且对{X\cup \{A\}}的任一等价类,总能在X的等价类中找到一个与之相等,于是我们可以得到以下的FD判断依据:

FD判断依据2:当且仅当|\Pi_X| = |\Pi_{X\cup \{A\}}|时,X→A成立。

判断依据可以理解为:当把划分所依据的属性集理解为响应收到限制的属性集,则属性集每多一个属性就多一个约束条件,所以对{X\cup \{A\}}划分所得结果必是对X所划分的结果的子集,因而\Pi_{X\cup \{A\}}总是细化\Pi_A,从而|\Pi_X| \leq = |\Pi_{X\cup \{A\}}|总是成立的。若\Pi_X细化了\Pi_A,则\Pi_{X\cup \{A\}}\Pi_A总对应相等。

TANE算法:

a)总体过程:

注解:

1、第六行COMPUTE_DEPENDENCIES(L_l)用于找所有X\{A}→A型的最小函数依赖

2、第七行通过右方集剪枝与键剪枝将搜索范围缩小

3、第八行通过所有e层结点生成相应e+1层结点。

b)计算函数依赖过程:

1、第1、2行正是前述的通过上层结点的C^+(X)来计算下层结点的初始C^+(X)的做法

2、第4-8行充分体现了定理3.1以及C^+(X)的内在含义

3、第3行可以看出是依次处理L_l层的结点

c)剪枝过程:

1、第1、2、3行体现的正是右方集的剪枝策略

2、第4-8行体现的是键剪枝的策略

3、假设X是一个超键,则函数依赖X\{A}→A是成立且是最小的,当且仅当X\{A}是键且\forall B \in X: A \in C^+(X),由此可知,第7行的输出是正确的

d)生成下层结点:

1、第2行的PREFIX_BLOCK(L_l)是指对L_l逻辑上按共同的前缀进行分组

2、第3行体现的是同一具共同前缀组中两个不同结点,两两合并形成一个下层结点

3、第1行对于刚生成的阶L_{l+1}的节点从小到大的检查,确定他所有阶为l 的真子集节点是否存在于L_l中,若都是存在,则将这个阶为l = 1的结点纳入到L_{l+1}集合中

e)生成下层划分

摘要

从关系中发现函数依赖关系是一项重要的数据库分析技术。我们提出了TANE,一种从大型数据库中寻找函数依赖性的有效算法。TANE基于对行集的属性值进行分区,这使得测试函数依赖的有效性变得非常快,甚至对于大量元组也是如此。分区的使用也使得发现近似的函数依赖关系变得容易和有效,并且错误或异常的行可以很容易地识别出来。实验表明,实际应用中,TANE速度快。对于基准数据库,运行时间比以前发布的结果提高了几个数量级。该算法也适用于比以往方法大得多的数据集。

1、函数依赖性和近似依赖性

函数依赖是数据库关系内属性之间的一个关系:函数依赖表示属性的值是唯一被其他属性值所决定的。例如:在一个地址数据库中,邮编是被城市和街道地址所决定的。函数依赖关系的发现引起了人们极大的兴趣。

当然,自动化数据库分析对于知识发现和数据挖掘(KDD)来说是很有趣的。例如,考虑一个包含化合物及其在各种生物测定中的结果的数据库。发现一种化合物的基本性质,如致癌性,在功能上依赖于某些结构属性是非常宝贵的。函数依赖在数据库管理、逆向工程和查询优化[等领域也有著名的应用。

从形式上讲,关系模式R上的函数依赖关系是表达式X→A,其中X⊆R且A∈R。对所有的元组t,u∈r,我们有:对所有的B∈X,如果t[B] = u[B],则t[A] = u[A](我们也说t和u同意X和A),那么这个依赖关系在给定的关系a / R中有效。若A不是函数依赖于X的任何真子集那么这个函数依赖X→ A是最小的,例如,若对于任意Y ⊂ X,Y → A在r中不成立,如果A ∈ X则依赖X→A是平凡的。我们考虑的中心任务如下:给定一个关系,找到r中所有最小的非平凡依赖关系。

近似函数依赖是一种几乎成立的函数依赖性。例如,性别大致由名字决定。在许多数据库中,当属性之间存在自然依赖时,这种依赖就会出现,但有些元组包含错误或表示规则的例外。在许多数据挖掘应用程序中,发现意外但有意义的近似依赖关系似乎是一个有趣和现实的目标。再来看看化合物数据库。从一组结构属性到致癌性的近似依赖可能和函数依赖一样有价值:两者都可以为生物化学家提供有价值的提示,说明癌症的潜在原因,但如果没有领域专家的进一步分析,这两种都不能被视为事实。近似函数依赖性在数据库设计中也有应用。

有许多可能的方法来定义依赖项X→A的近似性。我们使用的定义是基于需要从关系r中移除的最小元组数,r中包含X→A: error e(X → A)被定义为e(X → A) = min{|s| | s ⊆ r 且X→A在r\s中成立} /|r|。度量e也可以解释为找到r中多余的元组,有没有这些元组X→A都成立,当然度量e有一个很自然的解释,就是元组的部分,这些元组有异常或错误影响相关性。给定误差阈值ε, 0≤ε≤1,当且仅当e(X→A)最多是ε,我们说X→A是一个近似的(函数的)依赖。在本文中,我们也考虑近似依赖推理任务:给定一个关系r和一个阈值ε,找到所有最小的非平凡近似依赖。

我们描述了一种发现函数和近似依赖关系的新方法,并提出了实现这种思想的算法TANE。主要的创新是一种确定依赖关系是否成立的新方法该方法基于元组集合的等价类划分来表示属性集。TANE也有一个改进的方法来搜索函数依赖的空间。

最坏情况下,算法的时间复杂度相对于属性的数量是指数级的,但这是不可避免的,因为最小依赖的数量可以是指数级的属性数量[2,12]。然而,对于元组的数量,时间复杂度只是线性的(前提是依赖关系的集合不会随着元组数量的增加而改变)。据我们所知,之前只有一个算法可以声明这个[13]。以前的算法几乎总是基于对关系的元组进行重复排序或将每个元组与所有其他元组进行比较,这对于大型关系来说显然效率低下。线性使得TANE特别适合与大量元组的关系。

实验结果表明,该算法在实际应用中是有效的,即使是几十万元组的关系也可以发现函数依赖性和近似依赖性。据报道需要几分钟甚至几小时才能完成的依赖项发现任务,在PC上用新算法只需几秒甚至不到一秒就能解决。

1.1 相关工作

一些发现函数依赖关系的算法已经被提出[1,3,5,6,12,13,14]。我们回顾了这些算法,并将它们与第5.3节中的方法进行了比较。发现函数依赖关系的复杂性已经在[2,12,15]中得到了研究。

在[7,8,16,17]中已经考虑了近似函数相关性。Kivinen和Mannila[16]定义了依赖误差的几种度量方法,并推导出发现依赖误差的边界;用g3表示度量e

在[8]中,我们建议使用分区来描述和定义函数和近似依赖关系。这里的重点是一个概念的观点,没有给出算法。[18]中考虑了关系的划分语义,[19]中考虑了一种粗糙集方法。

我们的搜索策略是,在抽象的层面上,类似于关联规则的搜索:首先计算一些关于属性集的重要信息(在我们的例子中是分区,而在关联规则中是频繁项目集),从这些信息可以很容易地计算依赖关系(相对于关联规则)。计算依赖关系的水平方法是通用数据挖掘算法[21]的一个实例,它也成功地用于关联规则挖掘的先验算法中。

1.2 论文组织

在第2节中,我们将根据等价类和划分来确定依赖项发现任务。在第3节中,我们列出了搜索函数依赖关系空间的原则。第四节给出了详细的算法,第五节给出了分析。我们在第6节给出了实验结果,并在第7节得出结论。

这篇论文的一个较早和较短的版本出现了[22]。本文中非平凡引理的证明可以在[23]中找到。TANE算法的实现可以通过WWW页面http:// www.cs.helsinki.fi/research/fdk/datamining/tane/获得。

2. 分区和依赖关系

如果所有认同X的元组也认同A,那么依赖项X→A就成立我们发现依赖项的方法是基于考虑认同某些属性的元组集合。确定依赖关系是否成立可以通过检查元组是否在右边一致来完成,只要它们在左边一致。此外,如果不是这样,我们可以很容易地识别在右侧不一致的元组。因此,这种方法很自然地扩展到近似的依赖关系。形式上,这种方法可以用等价类和划分来描述。

2.1 划分

对于X中的所有A如果t[A] = u[A],那么两个元组t和u对于给定的属性集合X是等价的。任何属性集X将关系的元组划分为等价类。我们[t]_X来表示元组t相对于给定集X⊆ R 的等价类(t∈r),即[t]_X= {u∈r | \forallA∈X,t[A] = u[A] }。等价类的集合π_X\Pi_X = \{[t]_X | t\in r \}就是r在X下的划分。即\Pi _X是元组的不相交集(等价类)的集合,每个集合对属性集X都有一个唯一的值,集合的并集等于关系者。分区π的秩|π|是π上等价类的数目。

例1、考虑图1中的关系。属性A只有在元组1和元组2中值为1,所以它们构成了一个等价类[1]_{\{A\}} = [2]_{\{A\}} = \{ 1,2 \} (这里我们使用元组标识符来表示元组)。整个关于A的分区是π{A}={{1,2},{3,4,5},{6,7,8}}。分区对{B, C}是π{B, C} ={{1},{2},{3、4},{5},{6},{7},{8}}。

2.2 分区细化

分区细化的概念几乎直接提供了函数依赖性。如果π中的每一个等价类都是π'的等价类的子集,则一个分区π可以细化另一个分区π'。我们有以下引理。

引理2.1:当且仅当\Pi _X细化π{A}时,函数依赖性X→A成立。因为\Pi _X中的每一个等价类都是π{A}的一些等价类的子集,\Pi _X={{1},{2},{3,4},{5},{6},{7},{8}},π{C}={{1,3,4,6},{2,5,7},{8}},显然所有认同X成立的元组都认同A成立,因为X={B,C}

检验X→A是否成立还有一个更简单的方法:检验|\Pi _X| = |\Pi _{X\cup \{ A\}}| 。如果\Pi _X细化了π{A},则\Pi _{X\cup \{ A\}}等于\Pi_X.另一方面,因为\Pi _{X\cup \{ A\}}总是细化\Pi_X,除非\Pi _{X\cup \{ A\}}\Pi _X相等,否则\Pi _{X\cup \{ A\}}\Pi _X不可能有相同数量的等价类。我们已经展示了下面的引理。

引理2.2:当且仅当|\Pi _X| = |\Pi _{X\cup \{ A\}}|,函数依赖性X→A成立 。

2.3 近似的依赖性

回想一下,依赖项X→A的错误e(X→A)是必须从X→A保持的关系中移除的元组的最小分数。由\Pi_X\Pi _{X\cup \{ A\}}的分区可按如下方法计算误差e(X→A)。\Pi_X的任意等价类c是\Pi _{X\cup \{ A\}}的一个或多个等价类{c^'}_1,{c^'}_2,…的并集,并且为了保持X→A,c'_i中除了一个元组之外的所有元组都必须被删除。因此,要删除的最小元组数是c的大小减去c'_i中最大的元组的大小。对\Pi _X的所有等价类c求和,得到要删除的元组总数。

因此我们有e(X\rightarrow A)=1-\sum_{c\in \Pi_X} max\{|c'| | c'\in \Pi_{X \cup \{A\}} and c' \subseteq c \} / |r|,第4节给出了在\Pi_X\Pi _{X\cup \{ A\}}分区下计算e(X→A)的算法。

3.搜索

3.1 搜索策略

为了找到所有最小的非平凡的依赖关系,TANE的工作方式如下。它从单个属性集开始搜索,并通过一级一级的集合包含格向更大的属性集前进。当算法处理集合X时,测试形式为X \ {A}→A的依赖关系,其中A∈X。这保证了只考虑非平凡的依赖关系。从小到大的算法方向可以用来保证只输出最小的依赖项。它还可以用来有效地修剪搜索空间(参见图2)。

类似的从小到大的搜索策略,levelwise算法,已经成功地应用于许多数据挖掘应用[21]。除了有效的剪枝,level - wise算法的效率是基于使用前一层的结果来减少每一层的计算。

在本节中,我们将考虑搜索的不同方面,包括对水平算法min TANE的有效修剪准则,以及快速的分区计算。在水平策略中,这两个任务都可以有效地利用来自前一层次的信息来解决。根据本节的内容,第四节给出了精确的算法。

3.2 精简搜索空间

3.2.1 Rhs候选修剪

TANE通过格子工作,直到找到保持的最小依赖关系。为了测试潜在依赖项X \ {A}→A的最小值,我们需要知道Y \ {A}→A对于X的某个真子集Y是否成立。我们把这个信息存储在Y的右边候选的集合C(Y)中。

对于给定的集合X,如果A∈C(X),则A不依赖于X的任何真子集。更准确地说,某一集X的初始rhs候选项的集合为C(X) = R\\overline{C(X)}\overline{C(X)}={A ∈ X | X \{A} → A holds}。要找到最小的依赖项,只需测试依赖项X \ {A}→A,其中A ∈ X 且对所有B ∈ X, A ∈ C(X \ {B})。

例2、为了说明初始rhs候选集,假设TANE正在考虑集合X = {A, B,C}并且{C}→A是一个有效的依赖项。既然{C}→A成立,则有A\notinC({A,C}) = C(X\{B}),这就告诉TANE {B,C}→A不是最小值。C(X\{B}) = C{A,C} = {A,B,C,D} \ {A} = {B,C,D}

对TANE中的搜索空间进行剪枝时,假设C(X) =∅,则所有X的超集Y都是C(Y) =∅,这样就不存在Y \ {A}→A形式的依赖,也不需要处理集合Y。在集合包含格中的广度优先搜索可以有效地使用该信息,如图2所示。

3.2.2 Rhs+候选

当初始rhs候选项足以保证发现的依赖项最小时,我们将使用改进的rhs+候选项C^+(X)来更有效地修剪搜索空间:

C^+(X) ={A∈R |∀B∈X: X \ {A,B}→{B} does not hold}。

请注意,A可以等于B。下面的引理表明,我们可以使用rhs+候选项来测试依赖性的最小值,就像我们使用初始rhs候选项一样。

引理3.1 设A∈X,且X \ {A}→A为有效依赖项。当且仅当B∈X,我们有A∈C^+(X \ {B})时,依赖项X \ {A}→A是最小的。 C^+(X \ {B}) = { A∈R |∀C∈X: X \ {A,C}→{C} does not hold }

如果我们用C(X \ {B})替换C^+(X \ {B}),引理成立,但是 rhs +候选项与初始rhs候选项相比有两个优势。首先,我们可能会遇到一个B,其中a \notinC+(X \ {B})并停止更早的检查,从而节省一些时间。第二点也是更重要的一点,对于某些B,C^+(X\{B})可以是空的,而C(X \{B})不是。当rhs+ 候选时,由于修剪,集合X永远不会被处理。

C^+(X)的定义基于函数依赖关系的一个基本属性,如下引理所述。

引理3.2 设B∈X,且X \ {B}→B为有效依赖项。如果X→A成立,则X \ {B}→A成立。

引理允许我们从初始rhs候选集C(X)中删除附加属性。假设X\{B}→B对某些B∈X成立,那么根据引理,与左侧X的依赖关系不可能是最小的,因为我们可以在不改变依赖关系有效性的情况下从左侧删除B。因此,我们可以安全地从C(X)中删除以下集合:

例3 假设TANE考虑集合X = {A, B,C},并且{C}→B是一个有效的依赖项。因为{B,C} \ {B}  = {C} →B 是一个有效依赖项,所以\overline{C'(\{B,C\})} = R\X ,因为A\notin{B,C},所以A∈\overline{C'(\{B,C\})} = \overline{C'(X / \{A\})},这就告诉TANE X\{A}→A不是最小值。注意,TANE不需要知道X \ {A}→A是否成立。

此外,假设X有一个真子集Y,使得对于某个B∈Y, Y \ {B}→B成立,那么我们也可以从C(X)中删除所有A∈X \ Y,通过该规则删除的属性集如下:

例4 假设TANE考虑集合X = {A, B,C, D},并且{C}→B是一个有效的依赖项。那么A∈C''({A, B,C}) = C''(X \ {D})就告诉TANE X \ {A}→A不是最小值。

最后,由下面引理可知,rhs+候选集合C+(X)的充分优化集合也可以用C(X)、C'(X)、C''(X)来定义。

3.2.3 键修剪

如果没有两个元组同意X,则属性集X是超键,即划分\Pi_X仅由单例等价类组成。如果集合X是一个超键,并且它没有一个真子集是超键,那么它就是一个键。当在搜索依赖项时找到一个键时,可以应用额外的修剪方法。

引理3.4 设B∈X,且X \ {B}→B为有效依赖项。如果X是一个超键,那么X \ {B}是一个超键。

一般在处理X∪{A}时,对一个依赖项X→A, A\notinX进行检验,因为检验其有效性需要\Pi_{X\cup \{A \}}。但是,如果X是超键,那么X→A总是有效的,我们不需要X∪{a}。

现在,考虑一个不是键的超键X。很明显,对\forall A \notin X,依赖X→A不是最小的。此外,如果A ∈ X和X \ {A} → A成立,那么,根据引理3.4, X\{A}是一个超键,我们不需要\Pi_X来检验X \ { A \ }→A的有效性。换句话说,在寻找最小依赖关系时,我们不使用X或\Pi_X。因此,我们可以删除所有键及其超集,即不是键的超键。

3.3 计算与分区

我们接下来介绍两种方法来减少使用分区的时间和空间需求。第一个用一个更紧凑的表示来代替分区,“剥离分区”。第二种是快速逼近e误差的方法。这些方法优化了下一节中描述的算法。然后,我们描述了如何在逐级TANE算法中有效地计算分区。

对于这两种优化,我们都需要近似超键的概念。误差测度可以推广到关系的其他性质;具体来说,它可以扩展到作为超键的属性集的属性。我们将e(X)定义为需要从关系r中移除的元组的最小分数,以使X成为超键。如果e(X)很小,那么X就是一个近似超键。使用等式e(X)= 1- |\Pi_X| / | r | ,很容易从分区\Pi_X计算出误差e(X)。

3.3.1.剥离分区

剥离分区是删除了大小为1的等价类的分区。分区π的剥离版本用\widehat{\Pi}表示。例如,图1关系中的\widehat{\Pi_{\{D\}}}= { {1,4,7}}。抛弃单例等价类的一个直观解释是单例等价类(左侧)不能打破任何依赖。

剥离分区包含与完整分区相同的信息。例如,值e(X)很容易通过使用以下等式从剥离的分区中计算出来

其中||\widehat{\Pi_X}||是\widehat{\Pi_X}中等价类的大小之和。此外,划分的细化关系是相同的,因此引理2.1也适用于剥离的划分。

引理 2.2对于剥离分区不成立,因为|\widehat{\Pi_X}|可以和| \πX∩{ A }一样|即使\Pi_X \notin \Pi_X ∩{ A }。但是,由于e(X) = e(Y)当且仅当|πX| = |πY|,我们可以用下面的引理代替引理2.2。

引理 3.5。一个函数依赖X → A成立当且仅当e(X)= e(X∩{ A })。

3.3.2.边界e

从分区计算误差e(X → A)需要O(|r|)时间。通常可以通过使用以下界限来避免这种计算。e(X) − e(X ∪ {A}) ≤ e(X → A) ≤ e(X).

如果e(X)e(X∑{ A })>ε或e(X) < ε,TANE不需要计算e(X → A)来寻找X → A是否近似成立。这种优化可以节省大量时间,因为所考虑的函数依赖的数量可以是所处理的属性集数量的|R|/2倍。

3.3.3.计算分区

分区不是为每个属性集从头开始计算的。取而代之的是,当TANE在晶格中运行时,它将一个分区计算为两个先前计算的分区的乘积:两个分区π0和π00的乘积,用π0 π00表示,是对π0和π00进行细化的最小细化分区π。我们有以下结果。

引理 3.6. 对所有的X,Y ⊆ R, πX· πY= πX∪Y.

TANE直接从数据库中为每个A ∈ R计算分区π{A}。分区πX,f o r |X| ≥ 2被计算为分区相对于X的两个子集的乘积。大小| X | 1的任何两个不同子集都可以,这对于逐级算法是方便的,因为只需要来自前一级的分区。

一旦TANE有了划分πX,它就计算误差e(X),用于基于引理3.5的有效性测试。只有在下一级计算分区时才需要完整的分区。

在所有A ∈ R的第一个分区π{ A }的初始设置之后,TANE只处理元组标识符。这有两个好处。首先,可以区分不同的属性类型和值,计算实际上是在整数上进行的。因此分区操作简单而快速。第二,当计算近似依赖时,例外元组的标识符是容易获得的。

4.算法

4.1 TANE主要算法

为了找到所有有效的最小非平凡依赖,TANE以水平方式搜索集合包含格。L_l级是l大小的属性集的集合,因此L_l中的属性集可以根据前面部分的考虑来构建依赖关系。TANE从L_1= { {A} | A ∈ R} 开始,并且根据算法过程中得到的信息,计算L_1L_2L_2L_3,等等。

算法:TANE

输入: 关系R在模式R之上

输出:最小的非平凡的函数依赖

“计算依赖关系”(L_l)程序找出L_{l-1}中左侧的最小依赖关系。程序PREEN(L_l)通过删除L_l中的集合来修剪搜索空间,如第3节所述。程序GENOTE_NEXT_LEVEL(L_l)从当前级别形成下一个级别。这些步骤将在以下小节中介绍。

4.2.生成级别

“下一层”程序从“L_l”计算出“L_{l+1}”层。级别L_{l+1}将只包含大小为l+1的属性集,这些属性集的所有大小子集都在L_l中。修剪方法保证没有依赖关系丢失。GENERA TE _ NEXT _ LEVEL的规格为:

算法如下:

过程前缀块(L’)将L’分成不相交的块,如下所示。考虑一个集合X ∈ L '是一个属性的排序列表。如果两个集合X,Y∈L’具有长度为1的公共前缀,则它们属于同一个前缀块,即它们仅在一个属性上不同,并且不匹配的属性是X和Y中的最后一个属性。每个前缀块在L’的词典编纂中形成一个连续的块。prefixblocksarethuseasy很容易从按字典顺序排列的L '中计算出来。这个过程的想法来自[20],并在[25,算法3]中详细解释。

PREFIX_BLOCKS(L_l)过程将L_l分割成不相交的块,如下所示。假设集合X∈L_l是一个已排序的属性列表。两组X, Y∈L_l”属于相同的前缀块,如果他们有一个共同的前缀长度的 l −1,即他们在只有一个属性不同,不搭调的属性是最后一个属性X和Y每个前缀块形成一个连续的块在词典的顺序L_l。因此,前缀块很容易从字典顺序的L_l计算出来。这个过程的思想来自[20],在[25,算法3]中有详细的说明。

4.3.计算依赖

下面是TANE算法的计算依赖过程。

通过引理3.1,步骤2、4和5保证了过程输出正好是形式X \ {A} → A的最小依赖,其中X∈L_l和A ∈ X .第5行的有效性测试基于引理3.5。

COMPUTE DEPENDENTS(L_l)还计算所有X∈L’的集合C+(X)。下面的引理说明这样做是正确的。

引理4.1 为了正确计算L L Y∈L_{l+1},l e t C+(Y)。在执行过程COMPUTE DEPENDENTS(L_l)之后,对所有的X∈L_l正确地计算了C+(X)。

第8行实现了C+(X)和C(X)的区别。如果删除该行,算法将正常工作,但修剪可能会不太有效。

4.4.修剪格子

TANE算法的剪枝过程如下。

PRUNE过程实现了第3节中描述的两个修剪规则。根据第一条规则,如果C+(X) = ∅.,则删除x根据第二个规则,如果X是一个键,则删除X。在后一种情况下,算法也可能输出一些依赖关系。我们将展示修剪不会导致算法丢失任何依赖关系。

我们先考虑用空c++(X)剪枝。I f C+(X) = ∅,程序计算依赖项中第4–8行的循环和程序修剪中第5–7行的循环根本不会执行。由于C+(Y) = ∅也适用于所有Y ⊃ X,删除x对算法的输出没有影响。

现在让我们考虑修剪键。修剪的正确性基于以下引理。

引理4.2。设X是超键,设a∈X T h e依赖项X \ {a}→a是有效且最小的,当且仅当X \ {a}是键,对所有B∈X, a∈C+(X \ {B})。

依赖X→A在第7行输出的程序删除当且仅当X是一个关键,∈C + X (X) \ n d∈C + (X∪{}\ {B}), f o r l l B∈X引理4.2表明,这种依赖是有效的和最小。引理还表明,如果最小依赖项X \ {a}→a由于剪枝而没有在过程计算依赖项中输出,那么它将在过程剪枝中输出。因此,修剪工作是正确的。

4.5 计算分区

上面的算法不包含对分区的引用。然而,在计算依赖关系的第5行上实现中心测试需要知道e(X)和e(X \ {A})。同时,对剪枝第4行进行的超键测试也是基于e(X)。在TANE中,这些值通过公式(1)从剥离的分区中计算。分区的计算如下。

一开始,针对单例属性集的分区直接从关系r计算。从列r[A]计算分区π{A},如下所示。首先,将列的值替换为整数1、2、3、…使等价关系不变,即用相同的整数代替相同的值,用不同的整数代替不同的值。

这可以在线性时间内完成,使用trie或哈希表等数据结构将原始值映射到整数。至此,值t[A]就是π{A}的等价类[t]{A}的标识符,π{A}易于构造。最后,将π{A}中的单例等价类剥离,形成剥离分区d π{A}。

当在下一层属TE的第6行中将X添加到其级别时,将计算关于更大属性集X的分区。其中tX为Y∪Z, π x为πY·πZ的乘积。在线性时间内,用下列方法计算T和e的乘积。

这个过程假设表T已经被初始化为全空。由于过程在退出之前将T重置为all NULL,所以可以重复使用相同的表,而无需重新初始化。

4.6.近似依赖

对于给定的阈值ε,可以修改TANE算法以计算e(X → A) ≤ ε的所有最小近似依赖关系X → A。关键的修改是将“计算相关性”程序第5行的有效性测试改为

此外,通过将第8行的计算依赖项替换为

上述算法只返回最小的近似依赖关系。在某些应用程序中,了解不是最小但误差较小的近似依赖关系可能也很有用。我们把必要的修改留给读者去做。

TANE试图通过使用边界条件(2)来解决第50行的测试。如果失败,则使用以下过程从分区计算e的确切值(X\{A} → A)。

请注意与“剥离产品”程序的相似之处。在这里,表T必须一次全部初始化为0,但之后不需要重新初始化。

 

7.结束语

我们提出了一个新的算法,TANE,用于发现函数和近似依赖关系。该方法基于考虑关系的分区,并从分区中导出有效的依赖关系。该算法以广度优先或水平优先的方式搜索依赖性。我们展示了如何有效地修剪搜索空间,以及如何有效地计算分区和依赖关系。实验结果和比较表明,该算法在实际应用中速度较快,其放大性能优于以往的方法。该方法适用于多达几十万个元组的关系

当依赖关系相对较小时,该方法处于最佳状态。当(最小)依赖的大小大约是属性数量的一半时,依赖的数量是属性数量的指数,这种情况对任何算法来说或多或少都是不好的。当依赖性大于这个值时,从小的依赖性开始搜索的水平方向方法显然离最优值更远。原则上,水平搜索可以从大的依赖关系开始。然而,分区不能被有效地计算。

还有其他有趣的分区数据挖掘应用程序。属性-值对之间的关联规则可以通过对当前算法的小修改来计算。等价类则对应于属性集的特定值组合。通过比较等价类而不是全分区,可以找到关联规则。一个可能的未来研究方向是使用分区为函数依赖和关联规则提供的统一视图(也在[8]中独立观察到),以找到两者的适当推广,并开发发现这种规则的算法。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值