介绍
本文介绍了一种基于晶格理论的机器学习程序的新版本。这个版本的主要优点是Python程序员可以使用C ++编程的高效算法的接口。
如今,机器学习程序(例如卷积神经网络,随机森林和支持向量机)已达到很高的水平,在语音,视频和图像识别方面已经超过了人类。但是,他们无法提供论据来证明其结论的正确性。
另一方面,机器学习的符号方法(归纳逻辑编程,使用整数编程的学习覆盖率)具有非常高的计算复杂性,实际上甚至不适用于较小尺寸的样本。
此处描述的方法使用概率算法来避免这些问题。机器学习的ICF方法使用现代代数晶格理论(形式概念分析)和概率论(尤其是马尔可夫链)的技术。但是,现在您不需要使用高级数学知识即可使用ICF系统来创建程序。作者创建了一个库(在Windows下为vkf.cp38-win32.pyd或在Linux下为vkf.cpython-38-x86_64-linux-gnu.so),以通过Python程序员可以理解的界面提供对程序的访问。
与所描述的方法相关的是一种家长方法,该方法是在20世纪80年代初发明的,是技术科学博士。教授 VK。用于自动假设生成的Finn JSM方法。正如其创建者所说,它现已发展成为一种自动支持科学研究的方法。它允许您使用论证逻辑的方法,在扩展训练样本时检查发现的假设的稳定性,并使用JSM推理的各种策略来组合预测结果。
不幸的是,本文的作者及其同事发现并研究了JSM方法的一些理论缺陷:
- 在最坏的情况下,与输入数据(训练样本)的大小相比,生成相似度的数量可能成倍增加。
- (NP-).
- .
- «» , .
- .
作者的研究综述于论文的第二章。最后一点是作者最近发现的,但是在他看来,这终止了扩展的样本方法。
最后,JSM社区不提供对其系统源代码的访问。而且,所使用的编程语言(Fort和C#)将不允许普通大众使用。作者已知的唯一免费的JSM求解器的C ++版本(作者T.A. Volkova)robofreak)中包含一个令人讨厌的错误,有时会导致异常终止计算。
最初,作者计划与JSM社区共享为VKF方法系统开发的编码器。因此,他将所有同时适用于JSM和VKF系统的算法放在一个单独的库中(Windows下为vkfencoder.cp38-win32.pyd或Linux下为vkfencoder.cpython-38-x86_64-linux-gnu.so) ... 不幸的是,事实证明这些算法未被JSM社区要求。VKF库实现了这些算法(例如vkf.FCA类),但是依赖于不是通过文件而是直接通过Web界面填充表。在这里,我们将使用vkfencoder库。
1使用库处理离散功能的过程
假设读者知道如何安装MariaDB服务器+ MariaDB Connector / C(默认情况下,我们使用IP地址127.0.0.1:3306和用户“ root”,密码为“ toor”)。首先,将vkfencoder和vkf库安装到演示虚拟环境中,并创建一个名为'mushroom'的空MariaDB数据库。
krrguest@amd2700vii:~/src$ python3 -m venv demo
krrguest@amd2700vii:~/src$ source demo/bin/activate
(demo) krrguest@amd2700vii:~/src$ cd vkfencoder
(demo) krrguest@amd2700vii:~/src/vkfencoder$ python3 ./setup.py build
(demo) krrguest@amd2700vii:~/src/vkfencoder$ python3 ./setup.py install
(demo) krrguest@amd2700vii:~/src/vkfencoder$ cd ../vkf
(demo) krrguest@amd2700vii:~/src/vkf$ python3 ./setup.py build
(demo) krrguest@amd2700vii:~/src/vkf$ python3 ./setup.py install
(demo) krrguest@amd2700vii:~/src/vkf$ cd ../demo
(demo) krrguest@amd2700vii:~/src/demo$ mysql -u root -p
MariaDB [(none)]> CREATE DATABASE IF NOT EXISTS mushroom;
MariaDB [(none)]> exit;
作为工作的结果,数据库“蘑菇”
将出现,文件vkfencoder.cpython-38将出现在〜/src/demo/lib/python3.8/site-packages/vkfencoder-1.0.3-py3.8-linux-x86_64.egg/ 文件夹中-x86_64-linux-gnu.so,并且vkf.cpython
文件将出现在〜/ src / demo / lib / python3.8 / site-packages / vkf-2.0.1-py3.8-linux-x86_64.egg / 文件夹中38-x86_64-linux-gnu.so
启动Python3并在Mushrooms数组上运行CCF实验。假定〜/ src / demo / files /文件夹中有3个文件(mushrooms.xml,MUSHROOMS.train,MUSHROOMS.rest)。这些文件的结构将在下一节中介绍。第一个文件'mushrooms.xml'在描述蘑菇的每个属性的值上定义下半格的结构。第二个和第三个文件是文件“ agaricus-lepiota.data”,该文件除以随机数生成器的一半左右-1981年在纽约出版的数字化书籍“北美蘑菇的标识符”。以下名称是“编码器”,“晶格”,“火车''和``测试''分别是数据库``蘑菇''中表的名称,分别用于按位子字符串对特征值进行编码,这些值上半格图的覆盖关系,培训和测试示例。
(demo) krrguest@amd2700vii:~/src/demo$ Python3
>>> import vkfencoder
>>> xml = vkfencoder.XMLImport('./files/mushrooms.xml', 'encoder', 'lattices', 'mushroom', '127.0.0.1', 'root', 'toor')
>>> trn = vkfencoder.DataImport('./files/MUSHROOMS.train', 'e', 'encoder', 'trains', 'mushroom', '127.0.0.1', 'root', 'toor')
>>> tst = vkfencoder.DataImport('./files/MUSHROOMS.rest', 'e', 'encoder', 'tests', 'mushroom', '127.0.0.1', 'root', 'toor')
最后两行中的“ e”对应于蘑菇的可食用性(这是在此数组中对目标性状进行编码的方式)。
重要的是要注意,有一个vkfencoder.XMLExport类,它允许您将两个表“ encoder”和“ lattices”中的信息保存在xml文件中,进行更改后,可以由vkfencoder.XMLImport类再次进行处理。
现在我们来看看实际的VKF实验:我们连接编码器,加载先前计算的假设(如果有的话),将假设的额外数量(100)计算为指定数量(4)的流,并将其保存在``vkfhyps''表中。
>>> enc = vkf.Encoder('encoder', 'mushroom', '127.0.0.1', 'root', 'toor')
>>> ind = vkf.Induction()
>>> ind.load_discrete_hypotheses(enc, 'trains', 'vkfhyps', 'mushroom', '127.0.0.1', 'root', 'toor')
>>> ind.add_hypotheses(100, 4)
>>> ind.save_discrete_hypotheses(enc, 'vkfhyps', 'mushroom', '127.0.0.1', 'root', 'toor')
您可以获取编号为ndx的CCF假设的所有非平凡对(feature_name,feature_value)的Python列表
>>> ind.show_discrete_hypothesis(enc, ndx)
决定蘑菇食用性的假设之一是
[('gill_attachment', 'free'), ('gill_spacing', 'close'), ('gill_size', 'broad'), ('stalk_shape', 'enlarging'), ('stalk_surface_below_ring', 'scaly'), ('veil_type', 'partial'), ('veil_color', 'white'), ('ring_number', 'one'), ('ring_type', 'pendant')]
由于CCF方法算法的概率性质,可能无法生成该假设,但作者已经证明,如果生成的CCF假设数量足够多,就会出现一个与之非常相似的假设,这几乎可以预测重要测试用例的目标属性。详细信息在作者论文的第4章中。
最后,我们转向预测。我们创建一个测试样本,以评估所生成假设的质量,同时预测其元素的目标属性
>>> tes = vkf.TestSample(enc, ind, 'tests', 'mushroom', '127.0.0.1', 'root', 'toor')
>>> tes.correct_positive_cases()
>>> tes.correct_negative_cases()
>>> exit()
2数据结构说明
2.1离散特征上的晶格结构
vkfencoder.XMLImport类解析一个XML文件,描述了特征值之间的顺序,创建并填充了两个表``encoder''(将每个值转换为位字符串)和``lattices''(在一个特征的值之间存储关系)。
输入文件的结构应类似于
<?xml version="1.0"?>
<document name="mushrooms_db">
<attribute name="cap_color">
<vertices>
<node string="null" char='_'></node>
<node string="brown" char='n'></node>
<node string="buff" char='b'></node>
<node string="cinnamon" char='c'></node>
<node string="gray" char='g'></node>
<node string="green" char='r'></node>
<node string="pink" char='p'></node>
<node string="purple" char='u'></node>
<node string="red" char='e'></node>
<node string="white" char='w'></node>
<node string="yellow" char='y'></node>
</vertices>
<edges>
<arc source="brown" target="null"></arc>
<arc source="buff" target="brown"></arc>
<arc source="buff" target="yellow"></arc>
<arc source="cinnamon" target="brown"></arc>
<arc source="cinnamon" target="red"></arc>
<arc source="gray" target="null"></arc>
<arc source="green" target="null"></arc>
<arc source="pink" target="red"></arc>
<arc source="pink" target="white"></arc>
<arc source="purple" target="red"></arc>
<arc source="red" target="null"></arc>
<arc source="white" target="null"></arc>
<arc source="yellow" target="null"></arc>
</edges>
</attribute>
</document>
上面的示例表示来自机器学习数据存储库(加利福尼亚大学尔湾分校)的Mushrooms数组的第三个特征'cap_color'的值之间的顺序。每个``属性''字段代表相应属性值上的晶格结构。在我们的示例中,该组对应于离散属性“ cap_color”。所有特征值的列表构成一个子组。我们添加了一个值来指示平凡(缺失)的相似性。其余值与随附文件``agaricus-lepiota.names''中的描述相对应。
它们之间的顺序由子组的内容表示。每个项目都描述了一对特征值之间的更具体/更一般的关系。例如,表示粉红色的蘑菇帽比红色的帽更具体。
作者证明了由vkfencoder.XMLImport类的构造函数生成并存储在“ encoder”表中的表示形式正确性的定理。他的算法和正确性定理证明使用了称为理论概念分析的现代格点理论分支。有关详细信息,请读者再次参考作者的论文(第1章)。
2.2离散特征的样本结构
首先,应该注意,读者可以在数据库中实现自己的培训和测试用例加载器,也可以使用库中可用的vkfencoder.DataImport类。在第二种情况下,读者应考虑到目标特征必须位于第一个位置并由一个字符组成(例如,“ +” /“-”,“ 1” /“ 0”或“ e” /“ p”)。
培训样本应该是描述培训示例和反例(不具有目标属性的示例)的CSV文件(带有逗号分隔的值)。
输入文件的结构应类似于
e,f,f,g,t,n,f,c,b,w,t,b,s,s,p,w,p,w,o,p,k,v,d
p,x,s,p,f,c,f,c,n,u,e,b,s,s,w,w,p,w,o,p,n,s,d
p,f,y,g,f,f,f,c,b,p,e,b,k,k,b,n,p,w,o,l,h,v,g
p,x,y,y,f,f,f,c,b,p,e,b,k,k,n,n,p,w,o,l,h,v,p
e,x,y,b,t,n,f,c,b,e,e,?,s,s,e,w,p,w,t,e,w,c,w
p,f,f,g,f,f,f,c,b,g,e,b,k,k,n,p,p,w,o,l,h,y,g
p,x,f,g,f,f,f,c,b,p,e,b,k,k,p,n,p,w,o,l,h,y,g
p,x,f,y,f,f,f,c,b,h,e,b,k,k,n,b,p,w,o,l,h,y,g
p,f,f,y,f,f,f,c,b,h,e,b,k,k,p,p,p,w,o,l,h,y,g
p,x,y,g,f,f,f,c,b,h,e,b,k,k,p,p,p,w,o,l,h,v,d
p,x,f,g,f,c,f,c,n,u,e,b,s,s,w,w,p,w,o,p,n,v,d
p,x,y,g,f,f,f,c,b,h,e,b,k,k,p,b,p,w,o,l,h,v,g
e,f,y,g,t,n,f,c,b,n,t,b,s,s,p,g,p,w,o,p,k,y,d
e,f,f,e,t,n,f,c,b,p,t,b,s,s,p,p,p,w,o,p,k,v,d
p,f,y,g,f,f,f,c,b,p,e,b,k,k,p,b,p,w,o,l,h,y,p
每行描述一个训练示例。根据所描述的蘑菇的可食用性/毒性,第一位置包含“ e”或“ p”。其余位置(以逗号分隔)包含字母(短名称)或字符串(对应属性值的全名)。例如,第四个位置与属性“ cup_color”匹配,其中“ g”,“ p”,“ y”,“ b”和“ e”代表“灰色”,“粉红色”,“黄色”,“沙子”和“红色” , 分别。上表中间的问号表示缺少值。但是,其余(非目标)特征的值可以是字符串。重要的是要注意,当保存到数据库时,其名称中的空格将被替换为'_'字符。
带有测试用例的文件具有相同的形式,只是不向系统告知示例的真实符号,并且将其预测与之进行比较以计算生成的假设的质量及其预测能力。
2.3连续特征的样本结构
在这种情况下,选项仍然是可能的:读者可以在数据库中实现自己的培训师和测试用例加载器,或者使用库中提供的vkfencoder.DataLoad类。在第二种情况下,读者应考虑到目标特征应位于第一位置并由自然数组成(例如0、7、15)。
训练样本必须是CSV文件(其值由某种分隔符分隔),描述训练示例和反示例(不具有target属性的示例)。
输入文件的结构应类似于
"quality";"fixed acidity";"volatile acidity";"citric acid";"residual sugar";"chlorides";"free sulfur dioxide";"total sulfur dioxide";"density";"pH";"sulphates";"alcohol"
5;7.4;0.7;0;1.9;0.076;11;34;0.9978;3.51;0.56;9.4
5;7.8;0.88;0;2.6;0.098;25;67;0.9968;3.2;0.68;9.8
5;7.8;0.76;0.04;2.3;0.092;15;54;0.997;3.26;0.65;9.8
6;11.2;0.28;0.56;1.9;0.075;17;60;0.998;3.16;0.58;9.8
5;7.4;0.7;0;1.9;0.076;11;34;0.9978;3.51;0.56;9.4
5;7.4;0.66;0;1.8;0.075;13;40;0.9978;3.51;0.56;9.4
5;7.9;0.6;0.06;1.6;0.069;15;59;0.9964;3.3;0.46;9.4
7;7.3;0.65;0;1.2;0.065;15;21;0.9946;3.39;0.47;10
7;7.8;0.58;0.02;2;0.073;9;18;0.9968;3.36;0.57;9.5
在我们的案例中,这是从UCI数据存储库的Wine Quality数组中的葡萄牙红葡萄酒的“ winequality-red.csv”文件生成的“ vv_red.csv”文件的前几行,用于通过将最后一列重新安排到最开始来测试机器学习过程。重要的是要注意,当保存到数据库时,其名称中的空格将被替换为'_'字符。
3个具有连续特征的示例的CCF实验
如前所述,我们将演示UCI存储库中Wine Quality阵列上的工作。让我们首先在MariaDB下创建一个名为“ red_wine”的空数据库。
(demo) krrguest@amd2700vii:~/src/demo$ mysql -u root -p
MariaDB [(none)]> CREATE DATABASE IF NOT EXISTS red_wine;
MariaDB [(none)]> exit;
作为工作的结果,将显示“ red_wine”数据库。
我们启动Python3并在Wine Quality数组上进行VKF实验。假定〜/ src / demo / files /文件夹中有一个vv_red.csv文件。这些文件的结构已在上一段中进行了描述。以下名称“ verges”,“ complex”,“ trains”和“ tests”分别是“ red_wine”数据库中表的名称,分别用于阈值(初始值和回归计算出的特征),阈值之间的显着逻辑回归系数对功能,培训和测试用例。
(demo) krrguest@amd2700vii:~/src/demo$ Python3
>>> import vkfencoder
>>> nam = vkfencoder.DataLoad('./files/vv_red.csv', 7, 'verges', 'trains', 'red_wine', ';', '127.0.0.1', 'root', 'toor')
第二个参数设置阈值(在我们的示例中为7),在该阈值之上该示例被声明为正。参数';' 匹配定界符(默认为',')。
如作者先前的注释所述,该过程与离散特征的情况不同。首先,我们使用vkf.Join类计算逻辑回归,其系数存储在“复杂”表中。
>>> join = vkf.Join('trains', 'red_wine', '127.0.0.1', 'root', 'toor')
>>> join.compute_save('complex', 'red_wine', '127.0.0.1', 'root', 'toor')
现在,使用信息论,我们使用vkf.Generator类计算阈值,该阈值与最大值和最小值一起存储在“ verges”表中。
>>> gen = vkf.Generator('complex', 'trains', 'verges', 'red_wine', 7, '127.0.0.1', 'root', 'toor')
第五个参数设置原始特征的阈值数量。默认情况下(值为0)将其计算为要素数量的对数。回归寻找单个阈值。
现在我们来看看实际的VKF实验:我们连接编码器,加载先前计算的假设(如果有的话),将假设的额外数量(300)计算为指定数量(8)的流,并将其保存在'vkfhyps'表中。
>>> qual = vkf.Qualifier('verges', 'red_wine', '127.0.0.1', 'root', 'toor')
>>> beg = vkf.Beget('complex', 'red_wine', '127.0.0.1', 'root', 'toor')
>>> ind = vkf.Induction()
>>> ind.load_continuous_hypotheses(qual, beg, 'trains', 'vkfhyps', 'red_wine', '127.0.0.1', 'root', 'toor')
>>> ind.add_hypotheses(300, 8)
>>> ind.save_continuous_hypotheses(qual, 'vkfhyps', 'red_wine', '127.0.0.1', 'root', 'toor')
您可以获取编号为ndx的CCF假设的Python三元组列表(feature_name,(lower_boundary,upper_boundary))
>>> ind.show_continuous_hypothesis(enc, ndx)
最后,我们转向预测。我们创建一个测试样本,以评估所生成假设的质量,同时预测其元素的目标属性
>>> tes = vkf.TestSample(qual, ind, beg, 'trains', 'red_wine', '127.0.0.1', 'root', 'toor')
>>> tes.correct_positive_cases()
>>> tes.correct_negative_cases()
>>> exit()
由于我们只有一个文件,因此在这里我们将训练集用作测试用例。
4.关于上传文件的注意事项
我使用aiofiles库将文件(例如“ mushrooms.xml”)上传到Web服务器。这是一段您可能会发现有用的代码
import aiofiles
import os
import vkfencoder
async def write_file(path, body):
async with aiofiles.open(path, 'wb') as file_write:
await file_write.write(body)
file_write.close()
async def xml_upload(request):
#determine names of tables
encoder_table_name = request.form.get('encoder_table_name')
lattices_table_name = request.form.get('lattices_table_name')
#Create upload folder if doesn't exist
if not os.path.exists(Settings.UPLOAD_DIR):
os.makedirs(Settings.UPLOAD_DIR)
#Ensure a file was sent
upload_file = request.files.get('file_name')
if not upload_file:
return response.redirect("/?error=no_file")
#write the file to disk and redirect back to main
short_name = upload_file.name.split('/')[-1]
full_path = f"{Settings.UPLOAD_DIR}/{short_name}"
try:
await write_file(full_path, upload_file.body)
except Exception as exc:
return response.redirect('/?error='+ str(exc))
return response.redirect('/ask_data')
结论
vkf.cpython-38-x86_64-linux-gnu.so库包含许多隐藏的类和算法。他们使用先进的数学概念,如“封闭式运算”,“惰性评估”,“配对马尔可夫链”,“马尔可夫链”的瞬态,总变化量度等。
在实践中,使用机器学习数据存储库阵列进行实验(加利福尼亚大学尔湾分校)展示了C ++“ VKF方法”程序对中型数据(成人数组包含32560个训练和16280个测试用例)的真正适用性。
在预测准确性方面,“ VKF方法”系统的性能优于SPECT阵列上的CLIP3(整数编程覆盖学习v.3)系统,其中CLIP3是SPECT阵列作者创建的程序。在蘑菇阵列(随机分为训练样本和测试样本)上,“ VKF方法”系统显示出100%的准确性(相对于蘑菇毒性标准和可食用性标准)。该程序还应用于Adult数组,以生成超过一百万个假设(无毛刺)。
vkf CPython库的源代码在savannah.nongnu.org进行了预审核。可以从Bitbucket获得vkfencoder辅助库的代码。
作者要感谢他的同事和学生(D.A. Anokhin,E.D。Baranova,I.V。Nikulin,E.Y.Sidorova,L.A。Yakimova)的支持,有益的讨论和共同研究。但是,像往常一样,作者应对所有现有缺陷承担全部责任。