在这篇文章中,我将介绍有关规则学习的知识,其中将包含有关概念、一阶逻辑、序贯覆盖、剪枝优化、相关算法介绍等内容。
一、相关概念
首先,我们知道规则学习是机器学习的一个子领域,它专注于从数据中发现能够表达类别的条件模式,即规则。这些规则通常以“如果...则...”的形式出现,可以用来描述数据中的模式或进行预测。
然后,知道规则通常表示为前提条件和结论两部分。就比如说:“如果我送给她花,则她就会很开心”,其中“送给她花”是前提,“她会很开心”是结论。
而关于规则的分类则可以分为:命题规则与一阶逻辑规则。命题规则是由原子命题和逻辑连词:与、或、非、蕴含构成的简单陈述句。一阶逻辑规则的基本成分是能描述事物属性或关系的“原子公式”。
在此,我多说一下有关一阶逻辑的东西,一阶逻辑(First-Order Logic,FOL),也称为谓词逻辑或一级谓词演算,其基本成分是原子公式(也称作原子谓词),这些原子公式可以描述事物的属性或者不同事物之间的关系。一阶逻辑还包括量词(全称量词 ∀ 和存在量词 ∃),使得它可以表达关于一组或多组对象的更为复杂的陈述。
举个例子:
假设我们有一个简单的世界,这个世界中有猫(Cat)和老鼠(Mouse),并且猫会捉老鼠(Catches)。我们还知道汤姆是一只猫(Tom is a cat),杰瑞是一只老鼠(Jerry is a mouse),并且汤姆会捉住杰瑞(Tom catches Jerry)。
我们可以定义以下谓词:
Cat(x)
表示 x 是一只猫。
Mouse(x)
表示 x 是一只老鼠。
Catches(x, y)
表示 x 捉住了 y。
使用这些谓词,我们可以写出如下一阶逻辑的句子:
Cat(Tom)
:汤姆是一只猫。
Mouse(Jerry)
:杰瑞是一只老鼠。
Catches(Tom, Jerry)
:汤姆捉住了杰瑞。
如果我们想要表达一个更一般的断言,比如“所有的猫都会捉老鼠”,我们可以使用全称量词 ∀
来表示:
∀x (Cat(x) → ∃y (Mouse(y) ∧ Catches(x, y)))
:对于所有的 x,如果 x 是一只猫,那么存在一个 y,y 是一只老鼠,并且 x 捉住了 y。
同样,如果我们想说“存在一只老鼠,没有一只猫能够捉住它”,我们可以使用存在量词 ∃
:
∃y (Mouse(y) ∧ ∀x ¬(Cat(x) ∧ Catches(x, y)))
:存在一个 y,y 是一只老鼠,并且对于所有的 x,如果 x 是一只猫,则 x 不会捉住 y。
接着是规则集的概念:规则集是指一组规则,这些规则共同用于描述一个或多个类别的特征。规则集可以是互斥的(每个实例仅符合一个规则),也可以是非互斥的(一个实例可以符合多个规则)。
以及规则覆盖的概念为:规则覆盖指的是规则能够匹配的数据实例的数量。一个好的规则应该能够有效地覆盖足够多的正例,同时尽量少覆盖反例。
当我们生成了规则后,需要的就是去检验这些规则,所以需要一些指标来度量生成的规则的好坏,而这度量标准如下:
支持度(Support):规则覆盖的实例数目。
置信度(Confidence):规则覆盖的实例中属于指定类别的比例。
精确度(Accuracy):规则分类正确的比例。
提升度(Lift):规则条件下类别的概率与无条件下的概率之比。
卡方检验(Chi-Squared Test):衡量规则条件与类别分布之间的独立性。
在我们生成规则的时候,就要考虑规则提取了,规则提取是从已有的模型(如决策树、神经网络等)中提取出易于理解的规则。这有助于提高模型的透明性和可解释性。
在规则学习中,常见的算法有:CN2、FOIL、IREP、RIPPER等,有关这些算法具体的我将会在后文中详细介绍。
当我们在运行一些生成规则的算法时,就会发现算法会产生一些不必要的条件,这些条件会明显降低我们算法的性能,此时就需要规则简化和剪枝技术了。而上述的IREP与RIPPER就是常见的剪枝算法。关于剪枝还可分为“预剪枝”与“后剪枝”,同样我之后会详细介绍,在此就不赘述。
在我们生成了许多条规则或规则集后,同样可以考虑集成,这称为规则集成,规则集成是指将多个规则或规则集合并为一个更强大的预测模型。这可以通过投票机制、层次结构等方式实现。
最后是关于规则的应用,它的用途非常广泛像之前的文章所说的分类、回归、聚类等都可以使用。
二、序贯覆盖
我们知道,规则学习的目标是产生一个尽可能覆盖多的样例的规则集,而为了实现这个目标的做法就是“序贯覆盖”,也就是逐条归纳。其详细步骤为:
1.初始化:
从一个初始状态开始,此时规则集为空。准备好训练数据集,通常包括一系列带有标签的数据实例。
2.规则生成:
选择一个或多个特征作为候选规则的前提条件。生成一条或多条候选规则,这些规则能够区分目标类别。
3.规则评估:
对每一条候选规则进行评估,通常使用一些度量标准来确定规则的质量,如支持度、置信度、精确度等。选择最佳规则加入到规则集中。选择的标准可以是具有最高信息增益、最低错误率等。
4.规则应用:
使用选定的规则来覆盖训练集中的实例,即找出所有符合该规则前提条件的实例。移除已被当前规则覆盖的实例。
5.迭代重复:
对剩余未被覆盖的实例重复上述步骤,直到所有实例都被某条规则覆盖,或者达到某个停止条件(如最大规则数量限制、最小实例数量限制等)。
6.规则集整理:
在完成规则集的构建后,可以根据需要对规则集进行排序或优化,以确保规则集的简洁性和易读性。
7.剪枝与优化:
可选步骤,通过剪枝(如REP剪枝)去除冗余或过于复杂的规则,提高规则集的泛化能力。调整规则的顺序或内容,以优化规则集的整体性能。
在这个过程中,可以发现我们每次都是只处理一部分数据集,而后构成最优子结构,并不断将结果融合,所以可以说这也属于一种分治策略。也因此可以将之分为三个小部分:分解、解决、合并。
我们可以在这里用python代码来举个例子:
import pandas as pd
from sklearn.model_selection import train_test_split
def load_data():
# 示例数据集
data = {
'Outlook': ['Sunny', 'Sunny', 'Overcast', 'Rain', 'Rain', 'Rain', 'Overcast', 'Sunny', 'Sunny'],
'Temperature': ['Hot', 'Hot', 'Hot', 'Mild', 'Cool', 'Cool', 'Cool', 'Mild', 'Hot'],
'Humidity': ['High', 'High', 'High', 'High', 'Normal', 'Normal', 'Normal', 'Normal', 'High'],
'Wind': ['False', 'True', 'False', 'False', 'False', 'True', 'True', 'False', 'True'],
'PlayTennis': ['No', 'No', 'Yes', 'Yes', 'Yes', 'No', 'Yes', 'No', 'Yes']
}
df = pd.DataFrame(data)
return df
def find_best_rule(df, target_attribute):
best_rule = None
max_coverage = 0
for column in df.columns:
if column != target_attribute:
for value in df[column].unique():
subset = df[(df[column] == value) & (df[target_attribute] == 'Yes')]
coverage = len(subset)
if coverage > max_coverage:
max_coverage = coverage
best_rule = {column: value}
return best_rule
def sequential_covering(df, target_attribute):
rules = []
while True:
rule = find_best_rule(df, target_attribute)
if not rule:
break
rules.append(rule)
# 移除已经被正确分类的样本
df = df[~df.apply(lambda row: all(row[k] == v for k, v in rule.items()), axis=1)]
if df.empty:
break
return rules
if __name__ == "__main__":
df = load_data()
X = df.drop('PlayTennis', axis=1)
y = df['PlayTennis']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
train_df = pd.concat([X_train, y_train], axis=1)
rules = sequential_covering(train_df, 'PlayTennis')
print("Generated Rules:", rules)
其输出为:
Generated Rules: [{'Humidity': 'High'}, {'Temperature': 'Cool'}]
其意思是当湿度高时和气温凉爽时会去打网球。
三、剪枝优化
我们知道规则的生成本质上是一个贪心搜索的过程,所以需要一定的机制来缓解过拟合风险,其中最常见的做法就是剪枝(pruning)。它与决策树的剪枝类似,剪枝操作可以在规则生长过程中,也可以在产生后,而这两种情况就分别为:预剪枝和后剪枝。
关于预剪枝,一定会提到的就是CN2算法,它本身虽然不是一个典型的预剪枝算法,但它通过设置最小支持度、最小置信度等参数来控制规则的质量,从而间接实现了预剪枝的功能。
而至于后剪枝,则最常用的策略是“减错剪枝”,即REP,但其复杂度极高,是O(m^4)其中m是训练样例数。而算法IREP则可以将复杂度降至O(m(logm)^2)。
但如果我们将剪枝机制同其他一些后处理手段结合起来对规则集进行优化,那么往往就可以得到更好的效果,就比如RIPPER算法。
接下来,是关于上述几个算法的详细介绍:
首先是CN2算法,其步骤为:
1.初始化:
选一个初始规则为规则集,确定目标类,即要生成规则的类。
2.规则生成:
选一个目标类,尝试生成一条能覆盖该类别实例的规则,先从宽松规则开始,逐一细化,使用贪心法或其他算法来选择能最大化覆盖目标类别的特征或阈值。
3.规则评估:
使用一些标准去评估生成的规则,比如使用最小支持度、最小可信度等。以及评估的指标为:覆盖率、精确度等。
4.实例移除:
将当前用来生成规则的实例移除,然后寻找下一规则。
5.循环
接着是REP算法的步骤:
1.创建决策树:
使用训练数据构建完整的决策树。这通常通过递归地分割数据集来完成,直到满足停止条件(如纯度达到一定阈值、树的最大深度达到限制等)。
2.选择子树开始剪枝:
从决策树的叶节点开始,向上追溯到根节点。选择一个子树作为剪枝的起点。这通常从最底层的子树开始。
3.将子树标记为剪枝候选:
标记选定的子树作为剪枝候选。这通常意味着将该子树替换为一个叶子节点,并评估剪枝前后的模型性能。
4.对候选进行评估并决定:
使用验证数据集(或交叉验证技术)来评估剪枝前后模型的性能。通常,剪枝后模型的性能会通过减少过拟合来改善泛化能力。如果剪枝后的模型在验证集上的性能优于未剪枝的模型,那么就接受这次剪枝。否则,保留原子树,并继续评估下一个剪枝候选。
5.递归进行:对于已经标记为剪枝候选的子树,继续向上回溯,重复上述步骤,直到整棵树都被评估完毕或达到某个停止条件。通常,这个过程会递归地进行,直到整棵树都被检查过,或者没有进一步的剪枝能够带来性能提升。
还有就是IREP算法:
1.初始化:
初始化规则集为空。
2.创建规则:
从训练数据集中选择一个正例,并尝试生成一条能够正确分类该正例的规则。这条规则应尽可能地具体,即它应该能够匹配尽可能少的反例。
3.评估规则:
对于生成的每条规则,评估其对训练数据集的分类效果。通常会将训练数据集划分为训练子集和验证子集,以便评估新规则的泛化能力。
4.剪枝规则:
对于生成的规则,如果它在验证集上的性能不佳(例如,导致过多的错误分类),则进行剪枝。剪枝可以通过移除规则中的一些条件,或者通过调整规则的覆盖范围来实现。
5.更新规则集:
如果新生成的规则通过了评估,并且在验证集上的性能良好,则将其添加到规则集中。更新训练数据集,标记已经被现有规则正确分类的实例。
6.重复过程:
重复上述过程,直到满足某个停止条件,例如没有新的规则可以改善性能,或者达到了预设的规则数量上限。
7.最终规则集:
输出最终的规则集,这些规则集应该能够较好地分类训练数据集,并具有一定的泛化能力。
最后是RIPPER算法:
1.初始化:
初始一个空的规则集R与训练集D和验证集T
2.规则生成循环:
从D中选择一正例作为目标规则种子,生成一条规则,并能正确分类该正例,同时还要尽可能排除反例。
3.规则评估:
用T对生成的规则去评估,计算添加此规则后R的性能变化,就比如误差减少量。
4.剪枝:
如果刚才评估的性能提升,则保留这条规则,否则删去。
5.更新D并移除当前规则集
6.终止:
当D中无正例可被正确分类,或是说到达最大迭代次数,那么这个算法就终止。
四、决策树与规则学习
决策树与归纳学习都经常被用来进行分类与回归任务,这二者间存在许多的相似处,具体如下:
1.结构上的相似性:
决策树可以被视为一组规则的集合,每个从根到叶的路径都可以表示为一个规则。例如,在一个决策树中,一条路径可能对应着“如果年龄 > 30 岁并且收入 > 中等,则信用评级 = 高”。
2.逻辑表达:
决策树中的路径可以转换成逻辑表达式,这与规则学习产生的规则非常类似。例如,“IF (age > 30) AND (income > medium) THEN credit_rating = high”。
3.可解释性:
二者都提供了良好的可解释性,因为它们的结果可以很容易地被人类理解。这使得它们在需要解释模型决策的情况下特别有用。
4.归纳学习:
它们都是基于归纳学习的方法,即从特定的训练实例中学习出一般化的规则或决策树。
5.剪枝技术:
它们都会使用剪枝技术来降低复杂度,并且关于剪枝技术都分为预剪枝与后剪枝。
但他们也存在着许多的不同之处,如下:
1.表示方式:
决策树:以树状结构表示,每个内部节点代表一个属性上的测试,每个分支代表一个测试输出,每个叶节点代表一个类别(或输出值)。
规则学习:以一组“IF-THEN”规则的形式表示,每个规则对应一个分类或动作。
2.生成过程:
决策树:通过递归分割数据集,每次选择一个属性进行分割,直到满足停止条件。
规则学习:通常采用序贯覆盖(Sequential Covering)方法,逐个生成规则,每次生成一个规则后,将被该规则覆盖的样本从训练集中移除。
3.规则独立性:
决策树:路径之间有依赖关系,即上层节点的决策影响下层节点的选择。
规则学习:生成的规则通常是相互独立的,每个规则可以单独用于分类。
4.处理冲突:
决策树:通过路径到达叶子节点确定分类。
规则学习:如果有多个规则匹配同一个实例,需要解决规则间的冲突(例如,按照规则顺序、规则优先级等)。
5.剪枝技术:
决策树:既可以使用预剪枝(如设置最大深度、最小样本数等),也可以使用后剪枝(如基于验证集剪枝)。
规则学习:通常使用预剪枝技术(如限制规则长度、设置最小支持度等),较少使用后剪枝。
6.复杂度控制:
决策树:通过设置树的最大深度、最小叶子节点样本数等来控制模型复杂度。
规则学习:通过限制规则的最大长度、最小支持度、最小置信度等来控制模型复杂度。
五、归纳逻辑程序设计
5.1 一阶规则学习
在刚才,我有介绍过一阶逻辑(FOL),知道它是一种逻辑语言与推理工具,而接下来说的一阶规则学习(FORL)则是使用这种语言与工具去进行模式识别与规则提取的方法论。可以说FOL为FORL提供了表达学习结果的框架,而FORL则是在这个框架内进行自动化规则发现的过程。
在FORL中,可以更容易引入邻域知识,这是极大的一种优势,比如在如下这个疾病诊断中:
假设我们正在开发一个辅助医生诊断疾病的系统。在这个系统中,我们使用FORL来学习关于症状和疾病之间关系的规则。
领域知识:
医学术语:
常量:Patient
, Disease
, Symptom
谓词:has_symptom(Patient, Symptom)
, is_diagnosed_with(Patient, Disease)
已知的医学事实:
某些症状经常与特定疾病相关联。患者A有症状S1和S2,被诊断为疾病D1。患者B有症状S1、S2和S3,被诊断为疾病D2。
已知的规则:如果患者表现出症状S1、S2和S3,则可能是疾病D2。如果患者表现出症状S1并且没有其他常见症状,则可能是疾病D1。
学习过程
当系统尝试从数据中学习规则时,它可以利用上述领域知识来引导学习过程。例如,学习算法可以优先考虑那些与已知医学规则一致的新规则。
生成的规则示例
假设通过学习算法,我们得到了以下几条规则:
1.is_diagnosed_with(Patient, D1) :- has_symptom(Patient, S1), not has_symptom(Patient, S3)
. (如果患者有症状S1并且没有症状S3,则该患者可能被诊断为疾病D1。)
2.is_diagnosed_with(Patient, D2) :- has_symptom(Patient, S1), has_symptom(Patient, S2), has_symptom(Patient, S3)
. (如果患者同时具有症状S1、S2和S3,则该患者可能被诊断为疾病D2。)
在FORL 中,最著名的一个算法是FOIL,它遵循序贯覆盖框架且采用自顶项下的规则归纳策略。在它的步骤中:
1.初始化:
首先初始一个空的规则集以便后续的添加。
2.规则生成:
FOIL通过增、删、改规则中的谓词来改进规则,并且通过计算每个候选规则的FOIL信息增益(FOIL gain)来选择最佳的规则修改。
3.信息增益的计算:
对每个可能的规则修改,然后FOIL会计算这个修改对于正反例分类的贡献,这个计算方式就是用FOIL信息增益来计算。具体地,关于这个FOIL信息增益的表达式为:
其中的、分别表示为增加候选文字后新规则所覆盖的正、反例数;、we为原规则覆盖的正、反例数。它的信息增益与决策树的信息增益不同,它仅考虑正例的信息量,并且用新规则覆盖的正例数作为权重。这是因为关系数据中正例数往往少于反例数,因此通常对正例应赋予更多的关注。
4.迭代改进
5.规则集生成
5.2 归纳逻辑程序设计
当我们在FORL中引入函数与逻辑表达式的嵌套就有了归纳逻辑程序设计(ILP)。归纳逻辑程序设计(Inductive Logic Programming, ILP)是机器学习的一个分支,它专注于从数据中学习逻辑规则。ILP结合了归纳推理(从特定实例归纳出一般原理)和逻辑编程(使用逻辑语言如Prolog来表达知识和规则),旨在从一组已知的正例和反例中学习出逻辑规则,这些规则可以解释数据并推广到新的实例。
当我们从具体实例中总结出规则后,如果要让这个规则成为更普遍适用的规则,那么就需要泛化,即将“特殊”规则变为“一般”规则。为了达到这个目的,最基础的技术就是“最小一般泛化”(LGG)。其步骤为:
1.找相同谓词的文字:
对于给定的一阶公式r1和r2,LGG会先找出涉及相同谓词的文字。而若r1和r2中没有相同谓词的文字则直接忽视。
2.判断相同常量:
对于找出的这个相同文字,LGG会对它的每个位置的常量逐一考察,然后会有两种情况:
(1)常量在文字中的位置相同时:保持不变,然后记为:LGG(t,t)=t;
(2)常量在文字中的位置不同时:将它们替换为同一个新变量,并将这个替换应用于公式的所有其他位置,加入这两个常量为s,t,新变量为V,记为:LGG(s,t)=V,并在之后所有出现的s,t都用V来替换。
举个例子:
我们有如下两个规则:
1.r1:P(a,b)
2.r2:P(a,c)
然后进行LGG,我们找出相同谓词P,然后按位置逐个考察变量,其中人r1的a与r2的a一样,所以不变,而r1的b与r2的c不同,所以统一变为新变量V,则r1,r2一起变为:
1.r2:P(a,V)
2.r2:P(a,V)
在ILP中逆归结也是十分重要的一种技术,用于从已知的正例和反例中学习出能够解释这些例子的逻辑规则。逆归结的思想是基于经典逻辑编程中的归结(Resolution)技术,但它反过来用于生成规则而非验证规则。
此上
标签:剪枝,df,介绍,规则学习,实例,规则,决策树,生成,一份 From: https://blog.csdn.net/2301_79096986/article/details/142902676