模糊集合 和 模糊逻辑 的数学原理其本身可追逆到 1965 年。它的发现之父是来自伯克利大学分校的卢特菲·扎德教授, 他首先于信息与控制学报上发表的文章里介绍了 "模糊集合" 这些概念。对于精确科学, 比如数学, 这种工具可引入模糊概念, 任何人都可使用, 并在 软计算 的基础上奠定了解决问题的基本新方法。所有这些创新, 利用得当时, 可极大地促进解决各类问题的过程, 建立专家系统以及建立神经网络。
然而, 模糊逻辑的实际应用不只于此, 实际上, 这种数学工具已演变为主要用于 自动化控制理论。这可以进一步联系到另一个新概念的出现 — 模糊模型, 其是 数学模型 的一个特例。
通过一定的方式, 卢特菲·扎德的新理论为我们熟悉的数理逻辑和集合论扩展了边界。数学逻辑仅具有操作严格形式数据的能力, 特定集合的对象隶属仅由两个概念来定义, 因此, 特征 "隶属" 持有一个离散数值, 它有两个含义:
在他的模糊几何理论中, 卢特菲·扎德从 "隶属" 的离散概念推演, 并引入了新特征 — "隶属度", 如同之前使用的特征 "集合" 已由 "模糊集合" 替代。
定义 1. 模糊集合 在论域上 是集合对 , 此处 显示模糊集合的元素隶属度 。
定义 2. 隶属度 是在范围 [0, 1] 内的数字。隶属度越高, 论域中更多元素对应到模糊集合的属性。因此, 如果隶属度等于 0, 则给定元素不对应于集合; 与之相反, 如果隶属度等于 1, 它变成完全对应。这是两种边界情况, 对于常规集合无需援引其它选项。所有其它选项的存在是区别模糊集合的一个关键。
定义 3. 隶属函数 是一个函数, 可以计算论域中一个随机元素到模糊集合的隶属度。因此, 隶属函数的域应在 [0, 1] 范围内。在大多数情况下, 隶属函数是一个连续的单调函数。
定义 4. 语义变量 是一个变量, 其值是单词或结合了自然或人造语言的词汇。模糊集合特别是由语义变量构成。当定义一个模糊集合时, 模糊变量的数量和性质对于每个独立任务均是主观的。
定义 5. 特征集合 是所有可能数值的集合, 其为语义变量的接收能力。
定义 6. 特征 可以是属于特征集合中的任何元素。在模糊集合理论中一个特征是模糊集合经由隶属函数形成的。每个特征的隶属函数非常独立且通常是唯一的。这些函数的构造方法可以多样: 直接, 间接 以及 相对次数。这些往往基于隶属函数的特点, 以及此领域专家的经验证据。
例如:
让我们来定义一个语义变量, 称为 "年龄"。通过定义, "年龄" 是一个周期, 是人类、动物、植物成长并向前进化的一个步骤。这个变量的最小数值是 0, 即意味着某个人甚至连一岁都没有。作为最大值, 设为 80。根据人的年龄, 我们可以给他了如下评价: "新生", "青年", "中年", "老年", "暮年" 等等。这份清单可以容纳相当多的项目。这将是我们的语义变量特征集合, 而它的元素将是特征。
一下图例显示一个模糊变量 "年龄" 的例子, 其中只设置了三个特征集合: "青年", "中年", "老年"。每个特征均有自己的隶属函数。
我们来深入研究当一些人为 30 岁的情况, 在图例上对应于 (30, 0) 的垂线。这条线将在以下几点穿越所有三个隶属函数:
从这三个点的坐标, 我们可以得出结论一名 30 岁的人不能称为老年, 且他接近青年和中年特征, 而第二个占优。对于特征 "中年" 的隶属度等于 0.29, 这相当小, 实际上, 对于 30 岁的人另一个特征 "青年" 将会更适合。
定义 7. 去模糊化 是将一个模糊集合转化为特定数字的过程。目前有超过 20 个方法可用, 并且它们的结果彼此明显不同。请注意, 迄今为止 最佳结果是利用 重心 去模糊方法实现的。
模糊逻辑 — 是当语义变量标记为真时, 将传统的亚里士多德逻辑合成。模糊逻辑, 等同于经典逻辑, 在已定义的模糊集合上有自己的 模糊逻辑操作。如同普通集合一样模糊集合可同样操作, 仅在于它们的计算更加困难。我们还应该注意, 多模糊集合的组合可构成一个模糊集合。
模糊逻辑的主要原理, 是经典逻辑的一部分, 最大可能地反映现实, 和较高水平的主观性, 这可能会导致明显的计算错误。
模糊模型 — 是基于模糊逻辑进行计算的数学模型。这些模型的构建可适用于当研究课题有弱形式化, 它的精确数学描述过于复杂, 或根本不知道时。这些模型的输出值 (误差模型) 的品质直接依赖于建立这个模型的专家。降低出错的最佳选项是绘制更完整和详尽的模型, 既而利用学习机和大型训练集合来磨合它。
模型构建进度可分为三个主要阶段:
第一阶段直接影响到随后的两个阶段, 并确定模型以后的操作。知识库或有时称为规则库 — 是一套模糊规则类型: "if, then (如果, 则)" 它定义被检查对象的输入和输出之间的关系。系统中的规则数量没有限制, 也是由专家来决定。模糊规则的通常格式如下:
If 规则条件, then 规则结论。
规则条件 描述对象的当前状态, 而 规则结论 — 此条件如何影响对象。条件和结论的一般视图不能够被选择, 因为它们是由模糊推理来确定。
系统中的每条规则有其 权重 — 这个特征定义了模型内每条规则的重要性。分配到每条规则的权重因子范围在 [0, 1]。在许多模糊模型的实例中, 这可以在相关文献中找到, 没有指定权重数据, 但并不意味着它不存在。事实上, 在此种情况下, 来自规则库的每条规则, 权重是固定等于 1。每条规则可以有两种类型的特征和结论:
根据所创建的知识库, 为模型确定模糊推理系统。模糊逻辑推理 是模糊集合相应于当前输入和知识库以及模糊操作形成的结论。两种模糊推理的主要类型是马丹尼和关野方法。
根据马丹尼型算法, 模糊推理的执行使用模糊知识库:
在知识库里输入和输出变量的值由模糊集合设置。
这个知识库也可写成:
应用于以下之处:
让我们引入一个新的标记: — 模糊输入或输出变量的隶属函数 v 到模糊特征 t。
输入向量的隶属度到模糊特征 的计算来自以下知识库:
— 这个特征函数的工作结果来自知识库的 j-th 规则;
此处 — s-范数 (t-范数) 操作, 即实现多个 OR/AND (或/与) 逻辑操作。以下的实现使用十分频繁: 对于 OR (或) 操作— 查找最大且对于 AND (与) 操作— 查找最小。
在查找 对应的 之后我们得到 m 新隶属函数, 它们一起将形成一个新的模糊集合, 将之表示为 , 对应的输入向量 。
这种模糊集合的一个特点是, 它的论域是输出变量的特征集合 。
那么, 需要以下:
换言之, 通过利用模糊逻辑的特征, 来产生条件的含义和聚合。有两种方法来建模, 含义: 查找最小或集合的乘积, 聚合 — 查找最大或集合的算术和。
之后, 我们将获得结果模糊集合, 它的去模糊化将给我们确切的系统输出。
根据关野型算法, 模糊推理的执行使用模糊知识库:
关野型知识库类似于马丹尼型知识库, 除了结论规则 , 它不是经模糊特征定义, 而是输入的线形函数:
在关野知识库中的规则, 可认为是确定的开关, 从一个线性规律 "输入 - 输出" 到其它,也是线性的。子域的边界是模糊的, 因此不同程度的多重线性规律可以同时执行。
这个知识库也可写成:
应用于以下之处:
让我们引入一个新的标记: — 模糊输入或输出变量的隶属函数 v 到模糊特征 t。
输入向量的隶属度到模糊特征 的计算来自以下知识库:
— 这个特征函数的工作结果来自知识库的 j-th 规则;
此处 — s-范数 (t-范数) 操作, 即实现多个 OR/AND (或/与) 逻辑操作。在关野型模糊推理中以下三角范数实现使用十分频繁: 作为 s-范数的概率或, 以及作为 t-范数的乘积。
在查找 对应的 之后我们得到 m 新隶属函数, 它们一起将形成一个新的模糊集合, 将之表示为 , 对应的输入向量 。
请注意, 对比马丹尼型的输出结果, 上面提到的模糊集合是第一顺序的通常模糊集合。它是基于精确数字的集合。结果输出值 定义为在 n-维因子空间依据给定点 执行线形叠加。出于此原因模糊集合 是去模糊化的, 计算 平均权重或加权和。
在实践中, 创建和运作过程可能是一个艰巨的任务, 即使仅涉及一个非常简单的模糊模型。不过, 有许多不同的软件工具和程序库, 可以极大地简化它。作为一个例子, 我们将观察来自 FuzzyNet 程序库 MQL5 版 的测试脚本是如何创建和操作两种模糊模型的。
第一个例子是 Tips_Sample_Mamdani.mq5, 来自 FuzzyNet 程序库 MQL5 版。它实现了一个计算小费的模糊模型, 即一位顾客基于他/她对于服务和食物品质的评价所支付的。这个系统有两个模糊逻辑输入, 一个输出, 知识库有三条规则构成, 且是马丹尼型逻辑输出系统。
输入参数是模糊变量 食物 和 服务, 两个变量的测量标尺从 0 至 10 — 这也是它们的最小和最大值。变量 "食物" 由两个特征构成: "垃圾", "美味"。变量 "服务" 将由三个模糊特征构成: 差, 好, 出色。
在输出里我们得到模糊变量 "小费"。我们将定义小费的数值范围是账单额度的 5% 到 30%, 并为这个变量引入三个特征: "吝啬", "一般", "大方"。
该系统的知识库包含三条规则:
现在我们对系统有了些总体认识, 我们将看看它的创建过程:
#include <Math\FuzzyNet\MamdaniFuzzySystem.mqh>
此文件允许您创建马丹尼型系统, 并操作它们。MamdaniFuzzySystem *fsTips=new MamdaniFuzzySystem();
FuzzyVariable *fvService=new FuzzyVariable("service",0.0,10.0);
fvService.Terms().Add(new FuzzyTerm("poor", new TriangularMembershipFunction(-5.0, 0.0, 5.0))); fvService.Terms().Add(new FuzzyTerm("good", new TriangularMembershipFunction(0.0, 5.0, 10.0))); fvService.Terms().Add(new FuzzyTerm("excellent", new TriangularMembershipFunction(5.0, 10.0, 15.0)));在此例中所有特征的隶属函数表现为三角函数。
fsTips.Input().Add(fvService);
FuzzyVariable *fvFood=new FuzzyVariable("food",0.0,10.0); fvFood.Terms().Add(new FuzzyTerm("rancid", new TrapezoidMembershipFunction(0.0, 0.0, 1.0, 3.0))); fvFood.Terms().Add(new FuzzyTerm("delicious", new TrapezoidMembershipFunction(7.0, 9.0, 10.0, 10.0))); fsTips.Input().Add(fvFood);
FuzzyVariable *fvTips=new FuzzyVariable("tips",0.0,30.0); fvTips.Terms().Add(new FuzzyTerm("cheap", new TriangularMembershipFunction(0.0, 5.0, 10.0))); fvTips.Terms().Add(new FuzzyTerm("average", new TriangularMembershipFunction(10.0, 15.0, 20.0))); fvTips.Terms().Add(new FuzzyTerm("generous", new TriangularMembershipFunction(20.0, 25.0, 30.0))); fsTips.Output().Add(fvTips);
MamdaniFuzzyRule *rule1 = fsTips.ParseRule("if (service is poor) or (food is rancid) then (tips is cheap)"); MamdaniFuzzyRule *rule2 = fsTips.ParseRule("if (service is good) then (tips is average)"); MamdaniFuzzyRule *rule3 = fsTips.ParseRule("if (service is excellent) or (food is delicious) then (tips is generous)");
编写模糊规则要求严格输入, 并且不允许使用非关键词。 关键词是: "if", "then", "is", "and", "or", "not", "(", ")", "slightly", "somewhat", "very", "extremely "。最后四个关键词是语义量词。此外, 在您的系统上可用的所有变量名, 特征和函数都包含在关键字列表中。模糊特征的重要性或关野线形函数是递增的, 或与之相反, 语义量词递减。以下实现的语义量词适用:
fsTips.Rules().Add(rule1); fsTips.Rules().Add(rule2); fsTips.Rules().Add(rule3);
现在我们有了一个现成的模型, 基于马丹尼型模糊推理系统来计算小费。
实现关野型系统作为一个例子, 我们将使用一个脚本来测量车载巡航控制系统的必要控制量。此脚本在文件 Cruise_Control_Sample_Sugeno.mq5, 来自 FuzzyNet L程序库 MQL5 版, 并作为模糊模型解决自动控制问题的一个应用例子。
模糊逻辑主要用于自动控制系统 (ACS) 的等效一维任务。这些目标的设置可描述如下: 一个物体在确定点和时间 状态是 "A", 并经过时间帧 它抵达一个条件 "B"。为解决类似任务, 整个时间帧被分割为 部分, 一个时间片等于 已知, 之后自动控制系统在每个时间点 对它进行管理, 此处 i = 0,1,2 ... n。
各种 PID 控制器 可以很容易地处理这个任务, 但它们有一个缺点, 就是它们不能做到 "平滑" 控制。换句话说, 如果您基于 PID 控制器构建一个汽车的巡航控制系统, 具有系统变速并调整到所需速度, 不过, 在过程中可能会出现跳跃和颠簸。从人的角度来看, 模糊控制器可以更平滑地执行, 带来更佳舒适感觉。
很明显, 当输入错误且第一个衍生误差发生时, 我们的 模糊控制器 输出将会请求速率加速改变。误差是当前状态与期望值的偏差。换言之, 系统输入将会接收如下信息:
因此, "速度误差" 的第一个输入参数范围从 -20 到 20 公里每小时, 且有三个特征 "较慢", "零", "较快"。所有三个特征将有三角形隶属函数。第二个输入 — "速度误差点" 范围从 -5 到 5, 且操作的模糊特征 "速度误差", "零", "较快" 也有三角形隶属函数。
由于我们的模型有关野推理系统, "加速" 的输出值将不会有最大和最小值, 且将由输入变量的线形组合来替代模糊特征, 它们也将名为: "零", "较快", "较慢", "函数"。让我们来描述所有四个线性组合。为此, 我们将变量 SpeedError 表示为 , SpeedErrorDot 表示为 , 以及 加速 表示为 并得到以下等式:
该系统的知识库将包括九条规则:
让我们来描述系统创作历程:
#include <Math\FuzzyNet\SugenoFuzzySystem.mqh>
此文件允许您创建关野型系统, 并操作它们。SugenoFuzzySystem *fsCruiseControl=new SugenoFuzzySystem();
我们将创建变量 "速度误差" 并将之添加到系统:
FuzzyVariable *fvSpeedError=new FuzzyVariable("SpeedError",-20.0,20.0); fvSpeedError.Terms().Add(new FuzzyTerm("slower",new TriangularMembershipFunction(-35.0,-20.0,-5.0))); fvSpeedError.Terms().Add(new FuzzyTerm("zero", new TriangularMembershipFunction(-15.0, -0.0, 15.0))); fvSpeedError.Terms().Add(new FuzzyTerm("faster", new TriangularMembershipFunction(5.0, 20.0, 35.0)));
我们将创建变量 "SpeedErrorDot" 并将之添加到系统:
FuzzyVariable *fvSpeedErrorDot=new FuzzyVariable("SpeedErrorDot",-5.0,5.0); fvSpeedErrorDot.Terms().Add(new FuzzyTerm("slower", new TriangularMembershipFunction(-9.0, -5.0, -1.0))); fvSpeedErrorDot.Terms().Add(new FuzzyTerm("zero", new TriangularMembershipFunction(-4.0, -0.0, 4.0))); fvSpeedErrorDot.Terms().Add(new FuzzyTerm("faster", new TriangularMembershipFunction(1.0, 5.0, 9.0)));
线形函数 的形成是按以下方式进行: 每个输入变量是一个等式的未知数, 系数取自一个系数数组。这种方式, 在数组中的系数必须按照输入变量的相同记录顺序放置。因此, 对于第一个输入变量, 系数的下标应为 0, 对于第二个 - 下标为 1, 等等。所以, 系数数组的长度必须大于一个单元, 或等于输入变量的数量。如果长度相等, 则自由特征的系数等于零, 否则其值将等于数组最后一个元素。
在我们的系统中有两个输入变量, 所以系数数组的长度应不超过 3。我们将声明所有的四个数组, 根据它们的信息, 我们将按照上述描述形成函数, 并将它们添加到关野型模糊变量, 然后将它们包括在系统中:SugenoVariable *svAccelerate=new SugenoVariable("Accelerate"); double coeff1[3]={0.0,0.0,0.0}; svAccelerate.Functions().Add(fsCruiseControl.CreateSugenoFunction("zero",coeff1)); double coeff2[3]={0.0,0.0,1.0}; svAccelerate.Functions().Add(fsCruiseControl.CreateSugenoFunction("faster",coeff2)); double coeff3[3]={0.0,0.0,-1.0}; svAccelerate.Functions().Add(fsCruiseControl.CreateSugenoFunction("slower",coeff3)); double coeff4[3]={-0.04,-0.1,0.0}; svAccelerate.Functions().Add(fsCruiseControl.CreateSugenoFunction("func",coeff4)); fsCruiseControl.Output().Add(svAccelerate);
SugenoFuzzyRule *rule1 = fsCruiseControl.ParseRule("if (SpeedError is slower) and (SpeedErrorDot is slower) then (Accelerate is faster)"); SugenoFuzzyRule *rule2 = fsCruiseControl.ParseRule("if (SpeedError is slower) and (SpeedErrorDot is zero) then (Accelerate is faster)"); SugenoFuzzyRule *rule3 = fsCruiseControl.ParseRule("if (SpeedError is slower) and (SpeedErrorDot is faster) then (Accelerate is zero)"); SugenoFuzzyRule *rule4 = fsCruiseControl.ParseRule("if (SpeedError is zero) and (SpeedErrorDot is slower) then (Accelerate is faster)"); SugenoFuzzyRule *rule5 = fsCruiseControl.ParseRule("if (SpeedError is zero) and (SpeedErrorDot is zero) then (Accelerate is func)"); SugenoFuzzyRule *rule6 = fsCruiseControl.ParseRule("if (SpeedError is zero) and (SpeedErrorDot is faster) then (Accelerate is slower)"); SugenoFuzzyRule *rule7 = fsCruiseControl.ParseRule("if (SpeedError is faster) and (SpeedErrorDot is slower) then (Accelerate is faster)"); SugenoFuzzyRule *rule8 = fsCruiseControl.ParseRule("if (SpeedError is faster) and (SpeedErrorDot is zero) then (Accelerate is slower)"); SugenoFuzzyRule *rule9 = fsCruiseControl.ParseRule("if (SpeedError is faster) and (SpeedErrorDot is faster) then (Accelerate is slower)");
fsCruiseControl.Rules().Add(rule1); fsCruiseControl.Rules().Add(rule2); fsCruiseControl.Rules().Add(rule3); fsCruiseControl.Rules().Add(rule4); fsCruiseControl.Rules().Add(rule5); fsCruiseControl.Rules().Add(rule6); fsCruiseControl.Rules().Add(rule7); fsCruiseControl.Rules().Add(rule8); fsCruiseControl.Rules().Add(rule9);
模糊变量和其值应被发送到一个模糊系统的输入端。正如上面提到的, 模糊变量从它们的特征集合里取值。因此, 系统的计算结果将取决于其相应的模糊输入变量所应用的特征值隶属函数。然而, 在大多数情况下, 模糊变量只是由发送到系统输入的简单数值所形成, 其目的是从输出结果里获取相同精度。在这种情况下, 事实证明, 模糊特征没有明确声明, 且其隶属函数表示为一个恒定隶属函数。使用 FuzzyNet 库编写的系统设计用于针对这种特定情况进行操作。
到底需要发送什么到系统输入, 且我们将从它的结果里得到什么形式?
模糊系统输入变量的数量没有限制, 每个入口都必须采集一些数值, 因此, 我们需要有每个输入所保存数值的清单。此清单的元素应是一个包含两个字段的复杂对象: 第一个字段 — 模糊变量, 第二个字段 — 数值类型 双精度。在取自 MQL5 版程序库 FuzzyNet 的文件 Dictionary.mqh 里, 类 Dictionary_Obj_Double 已经实现创建此对象。
我们将形成一份用于我们的马丹尼型系统的输入清单:
CList *in=new CList; Dictionary_Obj_Double *p_od_Service=new Dictionary_Obj_Double; Dictionary_Obj_Double *p_od_Food=new Dictionary_Obj_Double; p_od_Service.SetAll(fvService, Service); p_od_Food.SetAll(fvFood, Food); in.Add(p_od_Service); in.Add(p_od_Food);
此处 Service 和 Food - 是两个 输入参数 类行为 双精度.
在上述的例子中, 马丹尼和关野系统两者都仅有一个输出, 虽然通常与输入相同, 但也没有限制它们的数量。输入和输出的结构没有任何差别。
马丹尼型系统的输出:
CList *result=new CList; Dictionary_Obj_Double *p_od_Tips=new Dictionary_Obj_Double;
现在, 对于每个系统, 我们将调用一个函数 Calculate, 其取用一个参数 — 一份输入清单, 并返回一份输出清单。根据这份清单的下标 0, 我们将得到系统输出值, 其表现为一个 Dictionary_Obj_Double类对象。使用它的类方法 Key 和 Value 我们可以分别得到变量, 和其数值。
我们将进行马丹尼系统的计算并显示模糊输出变量 fvTips 收到的数字:
result=fsTips.Calculate(in); p_od_Tips=result.GetNodeAtIndex(0); Alert("小费, %: ",p_od_Tips.Value());
我们将利用关野型系统做同样的过程:
CList *in=new CList; Dictionary_Obj_Double *p_od_Error=new Dictionary_Obj_Double; Dictionary_Obj_Double *p_od_ErrorDot=new Dictionary_Obj_Double; p_od_Error.SetAll(fvSpeedError,Speed_Error); p_od_ErrorDot.SetAll(fvSpeedErrorDot,Speed_ErrorDot); in.Add(p_od_Error); in.Add(p_od_ErrorDot); CList *result=new CList; Dictionary_Obj_Double *p_od_Accelerate=new Dictionary_Obj_Double; result=fsCruiseControl.Calculate(in); p_od_Accelerate=result.GetNodeAtIndex(0); Alert("加速, %: ",p_od_Accelerate.Value()*100);
有关上述脚本, 以及创建您的模糊模型的更多信息, 请下载 FuzzyNet 程序库的 MQL5 或 MQL4 版本。必须要明白, 构造 "活性" 模糊模型是一项具有挑战性的任务, 即使拥有辅助程序库的协助。此外, 每个已完成的模型都需要彻底的强制检查和调整。
本社区仅针对特定人员开放
查看需注册登录并通过风险意识测评
5秒后跳转登录页面...
移动端课程