python算法之近似熵、互近似熵算法
理论基础
近似熵?
- 定义:近似熵是一个随机复杂度,反应序列相邻的m个点所连成折线段的模式的互相近似的概率与由m+1个点所连成的折线段的模式相互近似的概率之差。 
- 作用:用来描述复杂系统的不规则性,越是不规则的时间序列对应的近似熵越大。反应维数改变时产生的新的模式的可能性的大小。 
对于eeg信号来说,由于噪声存在、和信号的微弱性、多重信号源叠加,反映出来的是混沌属性,但是同一个人在大脑活动相对平稳的情况下,其eeg近似熵应该变化不大。
- 证明和对应几何意义可参考论文:https://wenku.baidu.com/view/4ec89e44b307e87101f696ef.html
互近似熵
- 从近似熵定义引申出来的,近似熵描述的是一段序列的自相似程度,互近似熵比较的是两段序列的复杂度接近程度;熵值越大越不相似,越小越相似;
近似熵算法分析
- 设存在一个以等时间间隔采样获得的m维的时间序列u(1),u(2),...,u(N). 
- 定义相关参数维数m,一般取值为2,相似容限即阀值r,其中,维数表示向量的长度;r表示“相似度”的度量值. 
- 重构m维向量X(1),X(2),...,X(N−m+1),其中X(i)=[u(i),u(i+1),...,u(i+m−1)],X(j)=[u(j),u(j+1),...,u(j+m−1)];计算X(i)和X(j)之间的距离,由对应元素的最大差值决定;d[X,X∗]=maxa|u(a)−u∗(a)|d[X,X∗]=maxa|u(a)−u∗(a)| 
- 统计所有的d[X,X∗]<=r的个数g,则g/(N-M)就是本次的i取值对应的相似概率,计算所有i和j取值的概率对数的平均值,即熵值Φm(r); 
- 取m+1重复3、4过程,计算近似熵: 
ApEn=Φm(r)−Φm+1(r)
参数选择:通常选择参数m=2或m=3;通常选择r=0.2∗std,其中std表示原时间序列的标准差.
- 互近似熵计算和近似熵的步骤一样,把计算X(i)和X(j)之间的距离改为计算序列a的向量X(i)和序列b的向量Y(j)的距离;相似容限r为两个原序列的0.2倍协方差;
python代码实现
github源码
使用Pincus提出的近似熵定义计算近似熵
class BaseApEn(object):
    """
    近似熵基础类
    """
    def __init__(self, m, r):
        """
        初始化
        :param U:一个矩阵列表,for example:
            U = np.array([85, 80, 89] * 17)
        :param m: 子集的大小,int
        :param r: 阀值基数,0.1---0.2
        """
        self.m = m
        self.r = r
    @staticmethod
    def _maxdist(x_i, x_j):
        """计算矢量之间的距离"""
        return np.max([np.abs(np.array(x_i) - np.array(x_j))])
    @staticmethod
    def _biaozhuncha(U):
        """
        计算标准差的函数
        :param U:
        :return:
        """
        if not isinstance(U, np.ndarray):
            U = np.array(U)
        return np.std(U, ddof=1)
class ApEn(BaseApEn):
    """
    Pincus提出的算法,计算近似熵的类
    """
    def _biaozhunhua(self, U):
        """
        将数据标准化,
        获取平均值
        所有值减去平均值除以标准差
        """
        self.me = np.mean(U)
        self.biao = self._biaozhuncha(U)
        return np.array([(x - self.me) / self.biao for x in U])
    def _dazhi(self, U):
        """
        获取阀值
        :param U:
        :return:
        """
        if not hasattr(self, "f"):
            self.f = self._biaozhuncha(U) * self.r
        return self.f
    def _phi(self, m, U):
        """
        计算熵值
        :param U:
        :param m:
        :return:
        """
        # 获取矢量列表
        x = [U[i:i + m] for i in range(len(U) - m + 1)]
        # 获取所有的比值列表
        C = [len([1 for x_j in x if self._maxdist(x_i, x_j) <= self._dazhi(U)]) / (len(U) - m + 1.0) for x_i in x]
        # 计算熵
        return np.sum(np.log(list(filter(lambda a: a, C)))) / (len(U) - m + 1.0)
    def _phi_b(self, m, U):
        """
        标准化数据计算熵值
        :param m:
        :param U:
        :return:
        """
        # 获取矢量列表
        x = [U[i:i + m] for i in range(len(U) - m + 1)]
        # 获取所有的比值列表
        C = [len([1 for x_j in x if self._maxdist(x_i, x_j) <= self.r]) / (len(U) - m + 1.0) for x_i in x]
        # 计算熵
        return np.sum(np.log(list(filter(lambda x: x, C)))) / (len(U) - m + 1.0)
    def jinshishang(self, U):
        """
        计算近似熵
        :return:
        """
        return np.abs(self._phi(self.m + 1, U) - self._phi(self.m, U))
    def jinshishangbiao(self, U):
        """
        将原始数据标准化后的近似熵
        :param U:
        :return:
        """
        eeg = self._biaozhunhua(U)
        return np.abs(self._phi_b(self.m + 1, eeg) - self._phi_b(self.m, eeg))
if __name__ == "__main__":
    U = np.array([2, 4, 6, 8, 10] * 17)
    G = np.array([3, 4, 5, 6, 7] * 17)
    ap = ApEn(2, 0.2)
    ap.jinshishang(U) # 计算近似熵
说明:
- jinshishang函数直接计算近似熵 
- jinshishangbiao函数将原始数据标准化后计算近似熵 
使用Pincus提出的近似熵定义计算互近似熵
class HuApEn(BaseApEn):
    def _xiefangcha(self, U, G):
        """
        计算协方差的函数
        :param U: 序列1,矩阵
        :param G: 序列2,矩阵
        :return: 协方差,float
        """
        if not isinstance(U, np.ndarray):
            U = np.array(U)
        if not isinstance(G, np.ndarray):
            G = np.array(G)
        if len(U) != len(G):
            raise AttributeError('参数错误!')
        return np.cov(U, G, ddof=1)[0, 1]
    def _biaozhunhua(self, U, G):
        """
        对数据进行标准化
        """
        self.me_u = np.mean(U)
        self.me_g = np.mean(G)
        self.biao_u = self._biaozhuncha(U)
        self.biao_g = self._biaozhuncha(G)
        # self.biao_u = self._xiefangcha(U, G)
        # self.biao_g = self._xiefangcha(U, G)
        return np.array([(x - self.me_u) / self.biao_u for x in U]), np.array(
            [(x - self.me_g) / self.biao_g for x in U])
    def _dazhi(self, U, G):
        """
        获取阀值
        :param r:
        :return:
        """
        if not hasattr(self, "f"):
            self.f = self._xiefangcha(U, G) * self.r
        return self.f
    def _phi(self, m, U, G):
        """
        计算熵值
        :param m:
        :return:
        """
        # 获取X矢量列表
        x = [U[i:i + m] for i in range(len(U) - m + 1)]
        # 获取y矢量列表
        y = [G[g:g + m] for g in range(len(G) - m + 1)]
        # 获取所有的条件概率列表
        C = [len([1 for y_k in y if self._maxdist(x_i, y_k) <= self._dazhi(U, G)]) / (len(U) - m + 1.0) for x_i in x]
        # 计算熵
        return np.sum(np.log(list(filter(lambda x_1: x_1, C)))) / (len(U) - m + 1.0)
    def _phi_b(self, m, U, G):
        """
        标准化数据计算熵值
        :param m:
        :param U:
        :return:
        """
        # 获取X矢量列表
        x = [U[i:i + m] for i in range(len(U) - m + 1)]
        # 获取y矢量列表
        y = [G[g:g + m] for g in range(len(G) - m + 1)]
        # 获取所有的条件概率列表
        C = [len([1 for y_k in y if self._maxdist(x_i, y_k) <= self.r]) / (len(U) - m + 1.0) for x_i in x]
        # 计算熵
        return np.sum(np.log(list(filter(lambda x: x, C)))) / (len(U) - m + 1.0)
    def hujinshishang(self, U, G):
        """
        计算互近似熵
        :return:
        """
        return np.abs(self._phi(self.m + 1, U, G) - self._phi(self.m, U, G))
    def hujinshishangbiao(self, U, G):
        """
        将原始数据标准化后的互近似熵
        :param U:
        :param G:
        :return:
        """
        u, g = self._biaozhunhua(U, G)
        return np.abs(self._phi_b(self.m + 1, u, g) - self._phi_b(self.m, u, g))
使用洪波提出的快速实用算法计算近似熵
class NewBaseApen(object):
    """新算法基类"""
    @staticmethod
    def _get_array_zeros(x):
        """
        创建N*N的0矩阵
        :param U:
        :return:
        """
        N = np.size(x, 0)
        return np.zeros((N, N), dtype=int)
    @staticmethod
    def _get_c(z, m):
        """
        计算熵值的算法
        :param z:
        :param m:
        :return:
        """
        N = len(z[0])
        # 概率矩阵C计算
        c = np.zeros((1, N - m + 1))
        if m == 2:
            for j in range(N - m + 1):
                for i in range(N - m + 1):
                    c[0, j] += z[j, i] & z[j + 1, i + 1]
        if m == 3:
            for j in range(N - m + 1):
                for i in range(N - m + 1):
                    c[0, j] += z[j, i] & z[j + 1, i + 1] & z[j + 2, i + 2]
        if m != 2 and m != 3:
            raise AttributeError('m的取值不正确!')
        data = list(filter(lambda x:x, c[0]/(N - m + 1.0)))
        if not all(data):
            return 0
        return np.sum(np.log(data)) / (N - m + 1.0)
class NewApEn(ApEn, NewBaseApen):
    """
    洪波等人提出的快速实用算法计算近似熵
    """
    def _get_distance_array(self, U):
        """
        获取距离矩阵
        :param U:
        :return:
        """
        z = self._get_array_zeros(U)
        fa = self._dazhi(U)
        for i in range(len(z[0])):
            z[i, :] = (np.abs(U - U[i]) <= fa) + 0
        return z
    def _get_shang(self, m, U):
        """
        计算熵值
        :param U:
        :return:
        """
        # 获取距离矩阵
        Z = self._get_distance_array(U)
        return self._get_c(Z, m)
    def hongbo_jinshishang(self, U):
        """
        计算近似熵
        :param U:
        :return:
        """
        return np.abs(self._get_shang(self.m + 1, U) - self._get_shang(self.m, U))
使用洪波提出的快速实用算法计算互近似熵
class NewHuApEn(HuApEn, NewBaseApen):
    """
    洪波等人提出的快速实用算法计算互近似熵
    """
    def _get_distance_array(self, U, G):
        """
        获取距离矩阵
        :param U:模板数据
        :return:比较数据
        """
        z = self._get_array_zeros(U)
        fa = self._dazhi(U, G)
        for i in range(len(z[0])):
            z[i, :] = (np.abs(G - U[i]) <= fa) + 0
        return z
    def _get_shang(self, m, U, G):
        """
        计算熵值
        :param U:
        :return:
        """
        # 获取距离矩阵
        Z = self._get_distance_array(U, G)
        return self._get_c(Z, m)
    def hongbo_hujinshishang(self, U, G):
        """
        对外的计算互近似熵的接口
        :param U:
        :param G:
        :return:
        """
        return np.abs(self._get_shang(self.m + 1, U, G) - self._get_shang(self.m, U, G))
简单测试
if __name__ == "__main__":
    import time
    import random
    U = np.array([random.randint(0, 100) for i in range(1000)])
    G = np.array([random.randint(0, 100) for i in range(1000)])
    ap = NewApEn(2, 0.2)
    ap1 = NewHuApEn(2, 0.2)
    t = time.time()
    print(ap.jinshishang(U))
    t1 = time.time()
    print(ap.hongbo_jinshishang(U))
    t2 = time.time()
    print(ap1.hujinshishang(U, G))
    t3 = time.time()
    print(ap1.hongbo_hujinshishang(U, G))
    t4 = time.time()
    print(t1-t)
    print(t2-t1)
    print(t3-t2)
    print(t4-t3)
- 测试后发现使用快速算法比使用定义算法的计算效率提高了6倍以上。 
- 参考: 
- 作者:天宇之游
- 出处:http://www.cnblogs.com/cwp-bg/
- 本文版权归作者和博客园共有,欢迎转载、交流,但未经作者同意必须保留此段声明,且在文章明显位置给出原文链接。
python算法之近似熵、互近似熵算法的更多相关文章
- Python机器学习笔记:奇异值分解(SVD)算法
		完整代码及其数据,请移步小编的GitHub 传送门:请点击我 如果点击有误:https://github.com/LeBron-Jian/MachineLearningNote 奇异值分解(Singu ... 
- Python下探究随机数的产生原理和算法
		资源下载 #本文PDF版下载 Python下探究随机数的产生原理和算法(或者单击我博客园右上角的github小标,找到lab102的W7目录下即可) #本文代码下载 几种随机数算法集合(和下文出现过的 ... 
- Python 最大公约数的欧几里得算法及Stein算法
		greatest common divisor(最大公约数) 1.欧几里得算法 欧几里德算法又称辗转相除法,用于计算两个正整数a,b的最大公约数. 其计算原理依赖于下面的定理: 两个整数的最大公约数等 ... 
- 《算法4》2.1 - 选择排序算法(Selection Sort), Python实现
		选择排序算法(Selection Sort)是排序算法的一种初级算法.虽然比较简单,但是基础,理解了有助于后面学习更高深算法,勿以勿小而不为. 排序算法的语言描述: 给定一组物体,根据他们的某种可量化 ... 
- 熵(Entropy),交叉熵(Cross-Entropy),KL-松散度(KL Divergence)
		1.介绍: 当我们开发一个分类模型的时候,我们的目标是把输入映射到预测的概率上,当我们训练模型的时候就不停地调整参数使得我们预测出来的概率和真是的概率更加接近. 这篇文章我们关注在我们的模型假设这些类 ... 
- [转]熵(Entropy),交叉熵(Cross-Entropy),KL-松散度(KL Divergence)
		https://www.cnblogs.com/silent-stranger/p/7987708.html 1.介绍: 当我们开发一个分类模型的时候,我们的目标是把输入映射到预测的概率上,当我们训练 ... 
- Python的多继承问题-MRO和C3算法
		大部分内容转载自C3 线性化算法与 MRO 理解Python中的多继承 Python 中的方法解析顺序(Method Resolution Order, MRO)定义了多继承存在时 Python 解释 ... 
- Python小白的数学建模课-16.最短路径算法
		最短路径问题是图论研究中的经典算法问题,用于计算图中一个顶点到另一个顶点的最短路径. 在图论中,最短路径长度与最短路径距离却是不同的概念和问题,经常会被混淆. 求最短路径长度的常用算法是 Dijkst ... 
- C++、Java、Python、Linux、Go、前端、算法,慕课资料分享
		C++.Java.Python.Linux.Go.前端.算法,慕课资料分享 微信公众号:大道同行JAVA 如有问题或建议,请后台留言,我会尽力解决你的问题. 前言 又见面了.废话不多说,最近多了一些在 ... 
随机推荐
- 第92天:CSS3中颜色和文本属性
			一.颜色的表示方式 1. rgba(255,0,0,0.1) rgba是代表Red(红色) Green(绿色) Blue(蓝色)和 Alpha透明度.虽然它有的时候被描述为一个颜色空间 新增了RGB ... 
- poj1655 Balancing Act求树的重心
			Description Consider a tree T with N (1 <= N <= 20,000) nodes numbered 1...N. Deleting any nod ... 
- BZOJ3613 HEOI2014南园满地堆轻絮
			不明白在某谷上是怎么标到紫的.二分答案或者发现答案就是最大逆序差的一半. #include<iostream> #include<cstdio> #include<cma ... 
- 《Node入门》读书笔记——用Node.js开发一个小应用
			Android APP的开发告一段落,一个稳定的.实现了基本功能的APP已经交付用户使用了!我和老板交流了下,接下来准备转战Node.js了,而且一部分前端的功能也要做进去!哈哈哈~~~接下来要朝一个 ... 
- Spring Boot系列教程七:Spring boot集成MyBatis
			一.创建项目 项目名称为 “springboot_mybatis_demo”,创建过程中勾选 “Web”,“MyBatis”,“MySQL”,第一次创建Maven需要下载依赖包(耐心等 ... 
- Netsh命令-修改网络IP设置
			原文链接地址:https://blog.csdn.net/qq_38054198/article/details/77990914 静态设置IP 修改IP地址addr和子网掩码mask: \>n ... 
- Alpha 冲刺 —— 十分之二
			队名 火箭少男100 组长博客 林燊大哥 作业博客 Alpha 冲鸭鸭! 成员冲刺阶段情况 林燊(组长) 过去两天完成了哪些任务 协调各成员之间的工作 协助前端界面的开发 搭建测试用服务器的环境 完成 ... 
- POJ.3894  迷宫问题 (BFS+记录路径)
			POJ.3894 迷宫问题 (BFS+记录路径) 题意分析 定义一个二维数组: int maze[5][5] = { 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, ... 
- 解题:APIO 2008 免费道路
			题面 我们发现我们可以很容易知道最终完成的生成树中有多少鹅卵石路,但是我们不好得到这棵生成树的结构,所以我们尽量“谨慎”地完成生成树·,最好是一点点加到我们要达到的标准而不是通过删掉一些东西来完成 我 ... 
- 【bzoj3678】wangxz与OJ
			Portal -- > bzoj 3678 Solution 这题==真实智力康复qwq 然而众多神犇都说是10min写完的题我..可能写了近1h吧==深深感受到自己的弱小qwq (丢上来是因为 ... 
