马尔可夫逻辑网络 python Pracmln库 实战

马尔可夫逻辑网络介绍

一阶逻辑知识库是一阶逻辑公式所构成的集合,亦可看作施加于可能世界集合上的限制集合。在传统的一阶逻辑知识库中,每个可能世界必须满足知识库中的所有公式,否则该世界不可能存在的, 这致使人们很难在实际充满不确定性的世界中进行推理。

马尔可夫逻辑网的基本思想是将一阶逻辑的限制放松,即一个可能的世界中,它违反公式越多,其世界发生概率越小,但未必为零。

用公式权值来表示公式限制强度的大小,权值越大,满足该公式世界的发生概率越高,也与不满足该公式世界的发生概率之间的差就越大。

参考文献

  1. https://homes.cs.washington.edu/~pedrod/papers/aaai06c.pdf 论文, 内含公式和简例
  2. https://image.hanspub.org/pdf/SEA20150300000_13676271.pdf Markov逻辑网研究综述
  3. https://homes.cs.washington.edu/~pedrod/papers/mlj05.pdf 华盛顿大学Markov逻辑网原理论文
  4. http://www.pracmln.org/ Pracmln 库的文档
  5. http://aiweb.cs.washington.edu/ai/mln/database.html 大型学生老师关系预测数据集Pracmln
  6. http://www.wanfangdata.com.cn/details/detail.do?_type=degree&id=Y1781489 Markov逻辑网及其在社会网络中的应用研究 胡谦谦

安装使用

  1. 在windows 的中, 先安装好python 2.7 或 3.5环境, 及pip install 功能
  2. 用管理员权限, 以管理员身份打开cmd(Commend Prompt), 输入
pip install pracmln

然而, pracmln 中用到 dnutils库, 而dnutils库中某些函数在windows中没法使用,
参见 https://github.com/danielnyga/pracmln/issues/18

因此, 有以下解决方法:

  1. 安装以前的pracmln版本:

即以管理员身份打开cmd(Commend Prompt), 输入:

pip install pracmln==1.2.2
  1. 安装kaivalyar github主的 pracmln库 https://github.com/kaivalyar/pracmln (非必须)

先下载解压文件, 再进行安装:

cd pracmln-gsoc18-cython路径
python setup.py install

再安装dnutils 库

pip install dnutils

注: kaivalyar github主的 pracmln库 用了 Cython 改写, 运算速度增加了15-25%, 亲测真实, 参见
https://kaivalyar.github.io/gsoc18-pracmln/

  1. (不建议但有效) 手动删去致使程序错误的代码, 并保存运行:

安装完 dnutils 库后, 在dnutils库的安装位置中, 打开 signals.py 档案, 修改成以下内容:

import signal as signal_
import threading
from collections import defaultdict

__usrreg = defaultdict(list)
__sysinit = defaultdict(list)
__systerm = defaultdict(list)

SIGINT = signal_.SIGINT
SIGTERM = signal_.SIGTERM
#SIGKILL = signal_.SIGKILL
SIGABRT = signal_.SIGABRT
#SIGALRM = signal_.SIGALRM
#SIGBUS = signal_.SIGBUS
#SIGCHLD = signal_.SIGCHLD
#SIGCLD = signal_.SIGCLD
#SIGCONT = signal_.SIGCONT
SIGFPE = signal_.SIGFPE
#SIGHUP = signal_.SIGHUP
SIGILL = signal_.SIGILL
SIGINT = signal_.SIGINT
#SIGIO = signal_.SIGIO
#SIGIOT = signal_.SIGIO
#SIGKILL = signal_.SIGKILL
#SIGPIPE = signal_.SIGPIPE
#SIGPOLL = signal_.SIGPOLL
#SIGPROF = signal_.SIGPROF
# ============================================================================
#SIGPWR = signal_.SIGPWR
#SIGQUIT = signal_.SIGQUIT
#SIGRTMAX = signal_.SIGRTMAX
#SIGRTMIN = signal_.SIGRTMIN
SIGSEGV = signal_.SIGSEGV
#SIGSTOP = signal_.SIGSTOP
#SIGSYS = signal_.SIGSYS
SIGTERM = signal_.SIGTERM
#SIGTRAP = signal_.SIGTRAP
#SIGTSTP = signal_.SIGTSTP
#SIGTTIN = signal_.SIGTTIN
#SIGTTOU = signal_.SIGTTOU
#SIGURG = signal_.SIGURG
#SIGUSR1 = signal_.SIGUSR1
#SIGUSR2 = signal_.SIGUSR2
#SIGVTALRM = signal_.SIGVTALRM
#SIGWINCH = signal_.SIGWINCH
#SIGXCPU = signal_.SIGXCPU
#SIGXFSZ = signal_.SIGXFSZ
# =============================================================================

_lock = threading.Lock()


def _run_handlers(signal, args):
    '''Executes all handlers that are registered for the given
    siganl in the order of registration.'''
    # run system handlers for preparing the signal handling
    for handler in __sysinit[signal]:
        handler(*args)
    # run user defined signal handlers
    for handler in __usrreg[signal]:
        handler(*args)
    # run system handlers for cleaning up the signal handling
    for handler in __systerm[signal]:
        handler(*args)


def add_handler(signal, handler):
    '''
    Add a handler to be executed on the signal ``signal``

    :param signal:  the signal to react to.
    :param handler: a callable that will be called on the signal.
    :return:
    '''
    _add_handler(signal, handler, __usrreg)


def _add_handler(signal, handler, registry):
    '''
    Add a handler to be executed on the signal ``signal``

    :param signal:  the signal to react to.
    :param handler: a callable that will be called on the signal.
    :return:
    '''
    with _lock:
        handlers_ = registry[signal]
        if not handlers_:
            signal_.signal(signal, lambda *args: _run_handlers(signal, args))
        if handler not in handlers_:
            handlers_.insert(0, handler)


def rm_handler(signal, handler):
    '''
    Remove a handler if it is registered to the given signal.
    :param signal:  the signal that the handler is registered for
    :param handler: the handler function.
    :return:
    '''
    _rm_handler(signal, handler, __usrreg)


def _rm_handler(signal, handler, registry):
    '''
    Remove a handler if it is registered to the given signal.
    :param signal:  the signal that the handler is registered for
    :param handler: the handler function.
    :return:
    '''
    with _lock:
        try:
            registry[signal].remove(handler)
        except ValueError:
            pass


def keyint(*_):
    raise KeyboardInterrupt()


def enable_ctrlc():
    '''
    Allows to interrupt the main thread by pressing Ctrl-C.
    :return:
    '''
    _add_handler(SIGINT, keyint, __systerm)


def disable_ctrlc():
    '''
    Disables interruption of the main thread by the Ctrl-C key combination.
    :return:
    '''
    _rm_handler(SIGINT, keyint, __systerm)
  

示例问题描述: 社会链接预测应用

链接预测是以它所链接的社会主体(例如人, 公司, 组织), 和该社会主体已观测到的社会链接关系为条件, 来预测它与其他社会主体的某社会链接或社会关系是否存在。如判断两个社会主体是否存在朋友关系,两者是否会共同参与同一项活动等等。进而在有限的社会讯息中, 估算社会规模及其潜在隐藏的互动关系

利用 Pracmln 库的帮助, 我们首先建立以一阶逻辑所描绘的社会互动关系现象和假设:

data.txt:

data ###

Cancer(Alex)
!Cancer(Douglas)
!Cancer(Nixon)
Friends(Alex,Nixon)
Smokes(Alex)

在data.txt中,
Cancer(Alex) 指 Alex是Cancer的子集, 即Alex患上癌症;
!Cancer(Douglas) 指 Douglas不是Cancer的子集, 即Douglas没有患上癌症;
Friends(Alex,Nixon) 指 Alex 和 Nixon是Friends的二元子集, 即 Alex 和 Nixon存在朋友关系;
Smokes(Alex) 指 Alex有抽烟习惯

predicate.txt:

Cancer(person)
Friends(person,person)
Smokes(person)

谓词命名, 及谓词内变量命名

formula.txt:

Smokes(x) => Cancer(x)
Friends(x,y) => (Smokes(x) <=> Smokes(y))

在formula.txt中, 我们把对社会互动关系的假设和已有或未知真实程度的现象, 以一阶逻辑形式表示:

Smokes(x) => Cancer(x) 指 如果 x 有抽烟习惯, 则 x 患上癌症
Friends(x,y) => (Smokes(x) <=> Smokes(y)) 指 如果 x 和 y 是朋友关系, 则 x 有抽烟习惯 当且仅当 y 有抽烟习惯

在还没有接受数据 data.txt 的训练前, 我们将假定以上公式权重為零, 在训练后补上相应权重。一般而言, 如果data.txt 中的证据越是和公式一致, 其公式权重越高。

推理求解的命题:

Smokes(NIXON)

即在已知事实和相关社会假设下求解, Nixon 有抽烟习惯的概率

代码演示

@author: Alex Yu
"""

import os
import sys
from pracmln.utils.project import PRACMLNConfig
from pracmln.utils import config, locs
from pracmln.utils.config import global_config_filename
import os
from pracmln.mlnlearn import MLNLearn
from pracmln import MLN, Database, query


class social_modelling():

    def read_data(paths, predicate):      # 读txt数据用
        content = []
        base_path = os.getcwd()
        file = open(base_path + '\\' + paths,'r',encoding = 'utf8')
        pre_content = file.read()
        pre_content = pre_content.split('###')
        pre_content = [x for x in pre_content if x !='']
        for i in pre_content:
            element = i.split('\n')
            element = [x.replace(':','_') for x in element if x !='']
            for j in element[1::]:
                splited = j.split('(')
                content.append((element[0],splited[0]+'('+splited[1].upper()))    
                # pracmln 要求 证据数据库db中的格式為 Predicate(CONTANT_1), 即谓语首字及谓语内
                # 变量contant首字為大写, 还有不可以有空格. 这里单纯方便而把变量大写
                # 另外暂不支持中文输入.        
        return content
    
    def read_formula(paths,predicate):
        predicate_list = [x.split('('
  • 8
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值