AI算法Python实现:Transfer entropy

一、原理

Transfer entropy(转移熵/传递熵)是一种非参数统计量,用于测量两个随机过程之间定向(时间不对称)的信息转移量。给定两个随机过程XY,在A时刻,Y的值为Y_{A},随着时间的推移,由于不确定性,到达B时刻后,Y的值只能在一定的范围内被确定。在变化过程中,如果过程X对过程Y(定向)施加一定的影响(信息转移量),那么到达B时刻后,Y的值的范围会发生变化,这个变化的量,就是Transfer entropy所代表的过程X到过程Y,导致Y变化的非确定性的减少量。用公式可以表示为:

T_{X\rightarrow Y}=H\left ( Y_{t}|Y_{t-1:t-L} \right )-H\left ( Y_{t}|Y_{t-1:t-L} ,X_{t-1:t-L}\right )

 其中,H(X)代表X的熵(香农熵)。

二、代码实现

  • transferEntropy.py
  • main.py

transferEntropy.py

import numpy as np

from ctypes import byref, c_int, c_ulong, c_double, POINTER
from pyinform import _inform
from pyinform.error import ErrorCode, error_guard


def transfer_entropy(source, target, k, condition=None, local=False):
    """
    Compute the local or average transfer entropy from one time series to
    another with target history length *k*. Optionally, time series can be
    provided against which to *condition*.

    :param source: the source time series
    :type source: sequence or ``numpy.ndarray``
    :param target: the target time series
    :type target: sequence or ``numpy.ndarray``
    :param int k: the history length
    :param condition: time series of any conditions
    :type condition: sequence or ``numpy.ndarray``
    :param bool local: compute the local transfer entropy
    :returns: the average or local transfer entropy
    :rtype: float or ``numpy.ndarray``
    :raises ValueError: if the time series have different shapes
    :raises ValueError: if either time series has no initial conditions
    :raises ValueError: if either time series is greater than 2-D
    :raises InformError: if an error occurs within the ``inform`` C call
    """
    ys = np.ascontiguousarray(source, np.int32)
    xs = np.ascontiguousarray(target, np.int32)
    cs = np.ascontiguousarray(condition, np.int32) if condition is not None else None

    if xs.shape != ys.shape:
        raise ValueError("source and target timeseries are different shapes")
    elif xs.ndim > 2:
        raise ValueError("source and target have too great a dimension; must be 2 or less")

    if cs is None:
        pass
    elif cs.ndim == 1 and cs.shape != xs.shape:
        raise ValueError("condition has a shape that's inconsistent with the source and target")
    elif cs.ndim == 2 and xs.ndim == 1 and cs.shape[1:] != xs.shape:
        raise ValueError("condition has a shape that's inconsistent with the source and target")
    elif cs.ndim == 2 and xs.ndim == 2 and cs.shape != xs.shape:
        raise ValueError("condition has a shape that's inconsistent with the source and target")
    elif cs.ndim == 3 and cs.shape[1:] != xs.shape:
        raise ValueError("condition has a shape that's inconsistent with the source and target")
    elif cs.ndim > 3:
        raise ValueError("condition has too great a dimension; must be 3 or less")

    ydata = ys.ctypes.data_as(POINTER(c_int))
    xdata = xs.ctypes.data_as(POINTER(c_int))
    cdata = cs.ctypes.data_as(POINTER(c_int)) if cs is not None else None

    if cs is None:
        b = max(2, max(np.amax(xs), np.amax(ys)) + 1)
    else:
        b = max(2, max(np.amax(xs), np.amax(ys), np.amax(cs)) + 1)

    if cs is None:
        z = 0
    elif cs.ndim == 1 or (cs.ndim == 2 and xs.ndim == 2):
        z = 1
    elif cs.ndim == 3 or (cs.ndim == 2 and xs.ndim == 1):
        z = cs.shape[0]
    else:
        raise RuntimeError("unexpected state: condition and source are inconsistent shapes")

    if xs.ndim == 1:
        n, m = 1, xs.shape[0]
    else:
        n, m = xs.shape

    e = ErrorCode(0)

    if local is True:
        q = max(0, m - k)
        te = np.empty((n, q), dtype=np.float64)
        out = te.ctypes.data_as(POINTER(c_double))
        _local_transfer_entropy(ydata, xdata, cdata, c_ulong(z), c_ulong(n), c_ulong(m), c_int(b), c_ulong(k), out, byref(e))
    else:
        te = _transfer_entropy(ydata, xdata, cdata, c_ulong(z), c_ulong(n), c_ulong(m), c_int(b), c_ulong(k), byref(e))

    error_guard(e)

    return te


_transfer_entropy = _inform.inform_transfer_entropy
_transfer_entropy.argtypes = [POINTER(c_int), POINTER(c_int), POINTER(c_int), c_ulong, c_ulong, c_ulong, c_int, c_ulong, POINTER(c_int)]
_transfer_entropy.restype = c_double

_local_transfer_entropy = _inform.inform_local_transfer_entropy
_local_transfer_entropy.argtypes = [POINTER(c_int), POINTER(c_int), POINTER(c_int), c_ulong, c_ulong, c_ulong, c_int, c_ulong, POINTER(c_double), POINTER(c_int)]
_local_transfer_entropy.restype = POINTER(c_double)

main.py

from transferEntropy import *


xs = [0, 1, 1, 1, 1, 0, 0, 0, 0]
ys = [0, 0, 1, 1, 1, 1, 0, 0, 0]

a = transfer_entropy(xs, ys, k=2)
print(a)

测试结果: 

三、参考资料

1. Transfer entropy - Wikipedia

2. Transfer Entropy - PyInform

3. 机器学习——建立因果连系(传递熵)

  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值