您的位置:首页 > 其它

使用马尔可夫逻辑网(MLNs)进行分类实验

2012-11-19 08:39 267 查看
1. 引子 一阶逻辑: 规则:如果A是人,那么A会死(人是会死的) 已知事实:柏拉图是人 推理事实:柏拉图会死 其思想就是对于已知事实使用非常确定的规则进行推理,希望能发现未知的事实。 但是在现实世界中,很少有规则是没有意外的,比如: 好人有好报(才怪呢),郎才配女貌(也不一定),功到自然成(更是屁话),甚至连是人就会死都不一定(如果你相信电影《那个男人来自地球》所言其实的话)。 那末,我们如何对这类的知识进行建模呢? 马尔可父逻辑网提供了一种表示该知识的模型。它通过对规则引入权重来表示规则的确定性,如果权重非常大非常大(正无穷),则表示该规则非常之肯定,比如人是会死的;如果权重不是非常大,则表示该规则不一定很确定,比如吸烟会减少寿命;权重为零,则表示该规则有等于没有,比如读书会让人快乐(我乱扯的,嘿嘿);如果权重非常小非常小(负无穷),则表示该规则非常之肯定不成立,比如人是不会死的。通过对已知事实结合规则构建一个马尔可夫逻辑网,并进行概率推理,计算出未知事实成真的概率。 大概思想就是这样。 2. 分类 这样的模型非常之适合知识推理,但是用于分类问题好像不是很明显。 这个时候我们需要对问题进行一些转换: 分类问题<==>指定对象类别<==>确定该对象是否属于该类别<==>是否能推导出该对象属于该类别 也就是说: 加入需要对文档doc进行分类,他可能属于C1,C2和C3,则我们需要通过已知的事实证据计算其能推导出C1(doc)、C2(doc)、C3(doc)的可能性分别有多大,最简单的一种方式就是选择概率最的类别为其分类类别。 3.实践 该例子为一个3类文本分类问题,使用MLN目前唯一的Alchemy作为实验平台: 依照Alchemy用户手册给出的语法和规则,定义各个文件如下: 1) three.mln
//predicate declarations HasToken(doc, token) Class0(doc) Class1(doc) Class2(doc) //formulas HasToken(d, +t) => Class0(d) HasToken(d, +t) => Class1(d) HasToken(d, +t) => Class2(d)

2) three-train.db
Class0(Doc37261) Class0(Doc37913) ... HasToken(Doc37261, ASheep) HasToken(Doc37261, AVisualization) HasToken(Doc37261, AXref) ...

3) three-test.db
HasToken(Doc39063, ASystems) HasToken(Doc39063, AWet) HasToken(Doc39063, ATIF) ...

权重学习命令:../../bin/learnwts -d -i three.mln -o three-out.mln -t three-train.db -ne HasToken,Class0,Class1,Class2 学习到的规则及其权重如下:
//predicate declarations HasToken(doc,token) Class0(doc) Class1(doc) Class2(doc) // 1.80043 HasToken(d,ASheep) => Class0(d) 1.80043 !HasToken(a1,ASheep) v Class0(a1) // 2.96212 HasToken(d,AVisualization) => Class0(d) 2.96212 !HasToken(a1,AVisualization) v Class0(a1) ...

推理事实命令:../../bin/infer -i three-out.mln -e three-test.db -r three.results -q Class0,Class1,Class2 推理结果为: 注:该次试验是失败的,效果也N不好,因为没有对特征进行任何处理,连词干化都没做
... Class0(Doc61551) 4.9995e-05 Class0(Doc61552) 4.9995e-05 ...

最后文件组织如下图:

分别给定训练集路径和测试集路劲,转换语料库为Alchemy格式的数据,数据的组织如下图:

转换格式的python脚本如下:
#encoding:utf-8 import os import re tp = re.compile(r'\W') mlnfile = "three.mln" traindb = "three-train.db" testdb = "three-test.db" validb = "three-validate.db" #对指定文件路径生成token列表 def genetoken(filepath): lines = open(filepath).readlines() tokens = list() line_tokens = [token for line in lines for token in tp.split(line) if len(token.strip())>0] map(tokens.append, line_tokens) tokens = map(upperToken, tokens) return ["A"+token for token in list(set(tokens))] #把token首字符变大写 def upperToken(token): token = token[0].upper()+token[1:] if len(token) > 1 else token.upper() return token def getTitle(title): return "Doc"+title if __name__ == '__main__': train_path = 'train'#train set path test_path = 'test' #test set path classIndex = dict()#类别索引 for index, subfile in enumerate(os.listdir(train_path)): className = "Class" + str(index) classIndex[subfile] = "Class" + str(index) #生成训练集 for subdir in os.listdir(train_path): className = classIndex[subdir]#类别名 subdir = os.path.join(train_path, subdir)#子目录,即类别目录 titledb = [className + "(" + getTitle(title) + ")" for title in os.listdir(subdir)] #如Class1(Doc1111), Class2(Doc2222) open(traindb,'a').write('\n'.join(titledb) + '\n\n') for subdir in os.listdir(train_path): className = classIndex[subdir]#类别名 subdir = os.path.join(train_path, subdir)#子目录,即类别目录 for docfile in os.listdir(subdir): titleName = getTitle(docfile) tokens = genetoken(os.path.join(subdir, docfile)) tokendb = ["HasToken(" + titleName + ", " + token + ")" for token in tokens] open(traindb,'a').write('\n'.join(tokendb)+ '\n\n') #生成验证集 for subdir in os.listdir(test_path): className = classIndex[subdir]#类别名 subdir = os.path.join(test_path, subdir) titledb = [className + "(" + getTitle(title) + ")" for title in os.listdir(subdir)]#如Class1(Doc1111), Class2(Doc2222) open(validb,'a').write('\n'.join(titledb) + '\n\n') for docfile in os.listdir(subdir): titleName = getTitle(docfile) tokens = genetoken(os.path.join(subdir, docfile)) tokendb = ["HasToken(" + titleName + ", " + token + ")" for token in tokens] open(testdb,'a').write('\n'.join(tokendb) + '\n\n')

4. 尾巴 我必须坦白,如果数据量大了该程序根本没发工作,3*1000个文档集更不跑不动,最后只有减少数据量实验了,并且我现在开始考虑: 0) 该模型做文本分类是不适合滴,开始的大数据根本没法跑,减少到mini型数据还是跑了N个小时:Done learning discriminative weights. Time Taken for learning = 3 hrs, 6.43783 mins Total time = 3 hrs, 10.7546 mins 1) 该模型对实际应用的可能性,特别是对网络数据的知识抽取和知识发现; 2) 还有很多优化值得做,很可能该系统已经做了,只不过我不知道如何使用; 3) 还有很多工作可以做,开发很快更有效的推理学习算法,扩展模型; 对于该分类任务呢,还有不少工作没有做,比如确定最后类别,评价分类效果等等。 没办法,老板又派新活了,这个MLN只有先放到一边。那边书都没看完就乱扯一通确实非常不合适,但是什么都不写吧,又怕这么久的东西事是白看了。 5. 参考 Pedro Domingos, etc. Markov Logic : An Interface Layer for Artificial Intelligence. 2009. 徐从富等. 马尔可父逻辑网研究. 软件学报. 2011. Alchemy用户手册. http://alchemy.cs.washington.edu/user-manual/manual.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: