一行行的代码解密马尔可夫链

news2024/11/23 18:43:08

使用Python的马尔科夫链实例的实践 一行行的代码解密马尔可夫链。

当我开始学习物理时,我并不喜欢概率的概念。我对用物理学可以对整个世界进行建模的想法非常振奋,不确定性的想法让我很生气:)

事实是,当我们想研究真实的现象时,我们迟早都必须处理一定程度的不确定性。而处理它的唯一方法是获得对支配我们过程的概率的准确估计。

马尔科夫链是一个很好的方法。马尔科夫链背后的想法是非常简单的。

未来将发生的一切只取决于现在正在发生的事情。

用数学术语来说,我们说有一个随机变量X_0, X_1, ..., X_n的序列,可以在某个集合A中取值。然后我们说,如果一个事件的序列是一个马尔科夫链,我们就有。

alt

图片由我用LaTeX生成 如何用python生成LaTex请参考链接:

这听起来很复杂,但它只不过是上面所表达的概念而已。

另一个假设是,该方程对每一步都有效(不仅是最后一步),而且概率总是相同的(尽管从形式上看,这只对同质马尔科夫链而言是真的)。

现在,可能状态A的集合通常被表示为样本空间S,你可以用所谓的过渡概率来描述从S中的一个状态x到S中的一个状态y的概率。

但我答应过你,这将是一篇 "手把手 "的文章,所以让我们开始把这些概念形象化吧!

公平地说,Python不是进行数值模拟的最佳环境。专业研究人员使用的是更复杂的、在某些方面更可靠的语言,如C或Fortran。

尽管如此,本博客的目标是介绍一些非常简单的概念,使用Python可以使这个学习过程更容易。

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import seaborn as sns
plt.style.use('ggplot')
plt.rcParams['font.family'] = 'sans-serif' 
plt.rcParams['font.serif'] = 'Ubuntu' 
plt.rcParams['font.monospace'] = 'Ubuntu Mono' 
plt.rcParams['font.size'] = 14 
plt.rcParams['axes.labelsize'] = 12 
plt.rcParams['axes.labelweight'] = 'bold' 
plt.rcParams['axes.titlesize'] = 12 
plt.rcParams['xtick.labelsize'] = 12 
plt.rcParams['ytick.labelsize'] = 12 
plt.rcParams['legend.fontsize'] = 12 
plt.rcParams['figure.titlesize'] = 12 
plt.rcParams['image.cmap'] = 'jet' 
plt.rcParams['image.interpolation'] = 'none' 
plt.rcParams['figure.figsize'] = (12, 10) 
plt.rcParams['axes.grid']=False
plt.rcParams['lines.linewidth'] = 2 
plt.rcParams['lines.markersize'] = 8
colors = ['xkcd:pale orange''xkcd:sea blue''xkcd:pale red''xkcd:sage green''xkcd:terra cotta''xkcd:dull purple''xkcd:teal''xkcd: goldenrod''xkcd:cadet blue',
'xkcd:scarlet']

因此,让我们深入了解一下:这是你需要的东西是一堆主流的库,如pandas、matplotlib、seaborn和numpy。

让我们从最简单的场景开始。

  1. 随机漫步

简单随机漫步是一个极其简单的随机漫步的例子。

第一个状态是0,然后你以0.5的概率从0跳到1,以0.5的概率从0跳到-1。

alt

图片由我使用Power Point制作

然后你对x_1, x_2, ..., x_n做同样的事情。

你认为S_n是时间n的状态。

有可能证明(实际上非常容易),在时间t+1时处于某种状态的概率,即一个整数x,只取决于时间t的状态。

因此,这就是如何生成它。

start = 0
x = []
n = 10000
for i in range(n):
    step = np.random.choice([-1,1],p=[0.5,0.5])
    start = start + step
    x.append(start)
    
plt.plot(x)
plt.xlabel('Steps',fontsize=20)
plt.ylabel(r'$S_{n}$',fontsize=20)

而这就是结果:

alt

现在,随机漫步的想法是模拟如果我们决定从一个点开始,通过投掷一枚完美的硬币随机选择向上或向下,将会发生什么。

这个过程相当简单,但就其理论应用和特性而言,却非常有趣。

这个过程的第一个合理的扩展是考虑一个随机行走,但有一个非完美的硬币。这意味着,上升的概率与下降的概率不一样。这被称为有偏见的随机漫步。

让我们考虑以下几个概率。

 [0.1,0.9] , [0.2,0.8], [0.4,0.6], 
 [0.6,0.4], [0.8,0.2],[0.9,0.1]

所以我们有6种可能的随机行走。注意,概率必须是1,因此考虑 "向上 "或 "向下 "的概率即可。

这里是你如何做的。

x = []
p = [[0.5,0.5],[0.9,0.1],[0.8,0.2],[0.6,0.4],[0.4,0.6],[0.2,0.8],[0.1,0.9]]
label_p = ['Simple',r'$p=0.9$',r'$p=0.8$',r'$p=0.6$',r'$p=0.4$',r'$p=0.2$',r'$p=0.1$']
n = 10000
x = []
for couple in p:
    x_p = []
    start = 0
    for i in range(n):
        step = np.random.choice([-1,1],p=couple)
        start = start + step
        x_p.append(start)
    x.append(x_p)

而这是我们将其形象化后的结果。

i=0
for time_series in x:
    plt.plot(time_series, label = label_p[i])
    i=i+1
plt.xlabel('Steps',fontsize=20)
plt.ylabel(r'$S_{n}$',fontsize=20)
plt.legend()
alt
  1. 赌徒的毁灭链

另一种扩展随机漫步的简单方法是赌徒的毁灭链。 从概念上讲,它与随机漫步非常相似:你从一个状态x开始,你可以以概率p进入一个状态y=x+1,或者以概率1-p进入一个状态y=x-1。

alt

有趣的是,当你到达1或N时,你基本上就被卡住了。你只能永远停留在这个状态下,别无他法。

这个函数给定:

起始点(例如3)

第一个可能的值(例如:0)

和最后一个可能的值(例如:5)

步骤数(如10000)

给你最终的状态。

def gamblersruinchain(start,first,last,n):
    for k in range(n):
        if start==first or start==last:
            start = start
        else:
            step = np.random.choice([-1,1],p=[0.5,0.5])
            start = start + step
    return start

现在,在尝试这个函数之前,让我们考虑一个更有趣的情况。

假设我们从状态3开始。两步之后,结束在状态5的概率是多少?

嗯,就是从状态3到状态4,然后再从状态4到状态5的概率。

alt

LaTeX制作

在我们的例子中,它只是0.25。

如果现在我们问这个方程。

假设我们从状态3开始。两步之后,结束在状态1的概率是多少?

同样,这是从状态3到状态2,再从状态2到状态1的概率。

唯一的其他选择是在两步之后从状态3到状态3。我们可以用一个非常简单的方法来计算这个概率。由于总的概率必须是1,所以它只是。

alt

图片由我用LaTeX制作 而如果p=0.5,则又是0.5。

alt

同样,概率的概念是,如果我们无限次地重复一个实验,我们应该能够验证概率值所暗示的发生情况。


state_list = []
for i in range(100000):
    state_list.append(gamblersruinchain(3,0,5,2))
data_state = pd.DataFrame({'Final State':state_list})
data_occ = pd.DataFrame(data_state.value_counts('Final State')).rename(columns={0:'Count'})
data_occ['Count'] = data_occ['Count']/100000
sns.barplot(x=data_occ.index,y=data_occ['Count'],palette='plasma')
plt.ylabel('Normalized Count')
alt
  1. 自定义马尔科夫链

前面的模型是众所周知的,并被用作马尔科夫链的介绍性例子。让我们试着发挥创意,建立一个全新的、不存在的模型,就像下图中的模型。

alt

图片由我使用Power Point制作 我是个糟糕的画师,但这个模型本身很简单。

当你看到两个节点(比方说A和B)之间有一个箭头时,这意味着你可以从节点A出发,以一定的概率去到节点B,这个概率是用黑色书写的。

例如,从状态A到状态B的概率是0.5。

一个重要的概念是,模型可以用过渡矩阵来概括,它解释了马尔科夫链中可能发生的一切。这就是我们模型的过渡矩阵。

state_1 = [0.2,0.5,0.3,0,0]
state_2 = [0,0.5,0.5,0,0]
state_3 = [0,0,1,0,0]
state_4 = [0,0,0,0,1]
state_5 = [0,0,0,0.5,0.5]
trans_matrix = [state_1,state_2,state_3,state_4,state_5]
trans_matrix = np.array(trans_matrix)
trans_matrix
array([[0.2, 0.5, 0.3, 0. , 0. ],
       [0. , 0.5, 0.5, 0. , 0. ],
       [0. , 0. , 1. , 0. , 0. ],
       [0. , 0. , 0. , 0. , 1. ],
       [0. , 0. , 0. , 0.5, 0.5]])

如果你仔细观察这个模型,你可以看到一些非常特别的东西。比方说,你从状态2跳到状态3。你能回到状态2吗?答案是不能。

同样的情况也适用于状态3和状态1。因此,状态1、3和2被定义为短暂的状态。

另一方面,如果你从状态4开始,总是有可能在某一时刻,你会回到状态4。同样的情况也适用于状态5。这些状态被称为反复出现的状态。

让我们做一些实验,以便我们能够正确理解这个概念。

直观地讲,我们可以看到,从状态2开始,不回到状态2的概率随着步骤数的增加而趋于0。

事实上,从状态2开始,我们在N步之后发现自己处于状态2的概率是如下。

alt

图片由我用LaTeX制作 事实上,如果我们从状态2到状态3,就不可能再回到状态2。让我们把这个理论函数定义为t(N),并把它画出来。

def t(N):
    step = np.arange(1,N+1,1)
    y = []
    for s in step:
        v = 0.5**s
        y.append(v)
    return y
    
plt.plot(t(10))
plt.ylabel(r'$t(N-1)$',fontsize=20)
plt.xlabel(r'$N-1$',fontsize=20)
alt

现在,让我们使用马尔科夫链,看看我们是否验证了同样的结果。

我们从状态2开始,在N步之后验证处于状态2的概率。在这种情况下,概率只是最终状态中2的数量与发生次数的比率。为了保持一致,出现的次数需要趋于无穷大。让我们考虑1000次测试。

这就是我们要使用的函数。

def prob(N):
    states = np.arange(1,6,1)
    steps = np.arange(1,N+1,1)
    n=1000
    state_collection = []
    for k in range(n):
        start = 2 
        for i in range(N):
            start = np.random.choice(states,p=trans_matrix[start-1])
        if start==2:
            state_collection.append(1)
        else:
            state_collection.append(0)
    state_collection = np.array(state_collection)
    return state_collection.sum()/n

让我们对各种N使用这个函数,并称其为p(N)。

def p(N):
    step = np.arange(1,N+1,1)
    y = []
    for s in step:
        v = prob(s)
        y.append(v)
    return y
    
p_20 = p(20)
plt.plot(t(20),label=r'Theory, $t(N-1)$')
plt.plot(p_20,'x',label=r'Simulation, $p(N-1)$',color='navy')
plt.ylabel(r'Result',fontsize=20)
plt.xlabel(r'$N-1$',fontsize=20)
plt.legend()
alt

可以看到,我们使用了过渡矩阵来做这个模拟。我们可以使用过渡矩阵来评估我们所考虑的马尔科夫链的所有属性。

  1. 结论

在这本笔记本中,我们已经看到了非常知名的模型,如随机漫步和赌徒毁灭链。然后,我们创建了自己的全新模型,并对其进行了一番研究,发现了一些重要的概念,如过渡矩阵、循环状态和瞬态。最重要的是,我们已经看到了如何使用Python和非常知名的库以非常简单的方式验证这些概念。

本文由 mdnice 多平台发布

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2355.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

硬件电路(3)设计篇----为什么栅极型推挽电路不用上P下N?

在做信号控制以及驱动时,为了加快控制速度,经常要使用推挽电路。推挽电路可以由两种结构组成:分别是上P下N,以及上N下P。其原理图如下所示, 在平时中,我个人经常遇到的推挽电路是第一种。当我每次问身边的…

推荐一个不到2MB的C#开发工具箱,集成了上千个常用操作类

今天给大家推荐一个C#开发工具箱,涵盖了所有常用操作类,体积小、功能强大。 项目简介 C# 开发工具箱。大都是静态类,加密解密,反射操作,权重随机筛选算法,分布式短id,表达式树,lin…

单链表简单实现

单链表实现一、为什么会存在单链表?二、什么是单链表?三、单链表结构定义四、单链表的基本操作1、 创建结点2、 销毁链表3、 打印链表4、 尾插节点5、 头插结点6、 尾结点的删除7、 头结点的删除8、 单链表的查找9、 单链表在pos位置之后插入10、单链表在…

在jenkins上创建一个CANoe Job

目录实战项目CANoe 工程配置全局安全创建 slave 节点创建pipline Job: CANoeAutoRun实战项目CANoe 工程 配置全局安全 将代理和SSH Server都设置成随机选取,后面再本机创建slave 节点要用,因为我们会在用一台机器上创建了master和slave节点…

快充伤电池?我来帮何同学做个假设检验

最近看到何同学的视频,拿40部手机花两年半做了关于各种充电的实验视频,视频确实很好看,花里胡哨,看着科技感满满~。但是关于实验设计和根据实验的数据得出最后的结论上似乎有些草率。 实验设计上就不提了,…

周涛:在大数据沙滩上捡拾“珍珠”|奋斗者正青春

“我始终觉得,创新的本原就是好奇心,要像小孩儿一样,一直不断地追问,向这个世界讨要答案。在追寻答案的过程中,要有独立探索和批评的精神,不能轻信权威。” 1 提起电子科技大学教授周涛,大多…

【定语从句练习题】who、which

1. 填空训练 翻译的时候加上 … 的 1.who 2.which 3.which 4.which 5.who 6.which 7.which 8.who 9.who 10.which 11.which 12.who 2. 选择 1.took 2.live 3.she is 3.lost 5.bought 6.is parked 7.it cuts 8.writes 9.make 10.lent you. 10.lend sb. sth 这里需要&…

Java反射06:反射的应用之动态代理

反射的应用之动态代理 (这里没听懂,知道反射体现了代理动态性就行,后面框架再学习) 代理设计模式的原理 使用一个代理将对象包装起来, 然后用该代理对象取代原始对象。任何对原 始对象的调用都要通过代理。代理对象决定是否以及何…

C语言之指针详解

文章目录1 指针1.1 简介1.2 什么是指针1.3 使用指针1.3.1 简单使用1.3.2 NULL 指针1.3.3 指针算术运算1.3.3.1 定义1.3.3.2 遍历数组:递增一个指针1.3.3.3 遍历数组:递减一个指针1.3.3.4 指针的比较1.3.4 指针数组1.3.5 指向数组的指针1.3.6 指向指针的指…

Django中利用Admin后台实现Excel/CSV的导入更新数据库和导出数据到Excel/CSV

本文基于Django自带的admin 后台实现Excel,csv,Json等格式文件的导入并更新后台数据库。 核心是引入 django-import-export模块。 1、测试相数据准备: 我们先创建一个app:app01 python manage.py startapp app01 然后在app01…

软考下午题第1题——数据流,题目分析与案例解析:

答题技巧-【11-12分】分必拿方法: 下午第一题肯定是数据流的题目,那么,数据流肯定要找到对应的实体、关系模式等内容,审题的时候一定要细致,下午时间也是相当够的,所以每句话记住,至少读3遍&am…

【pyhon】利用pygame实现彩图版飞机大战(附源码 可供大作业练习使用)

源码请点赞关注收藏后评论区留言或私信博主 演示视频已上传到我的主页 有需要者可自行观看 演示视频如下: 飞机大战接下来先介绍一下游戏的玩法 在PyCharm中运行《彩图版飞机大战》即可进入如图1所示的游戏界面。 具体的操作步骤如下: (1&…

Android Native APP开发笔记:多线程编程

文章目录目的Java中的多线程ThreadRunnableTimerAndroid中的多线程HandlerAsyncTask总结目的 Android中UI线程对于开发者和用户来说都是最主要接触到的线程。一般来说为了UI流畅、不卡顿,耗时操作是不推荐放在UI线程中的。但是耗时操作的需求又是存在的&#xff0c…

Spring Cloud(八):Spring Cloud Alibaba Seata 2PC、AT、XA、TCC

事务简介 分布式事务:https://www.processon.com/view/link/61cd52fb0e3e7441570801ab 本地事务 JDBC 事务模式 Connection conn ... //获取数据库连接 conn.setAutoCommit(false); //开启事务 try{//...执行增删改查sqlconn.commit(); //提交事务 }catch (Exce…

【C++学习】日期类和内存管理

🐱作者:一只大喵咪1201 🐱专栏:《C学习》 🔥格言:你只管努力,剩下的交给时间! 日期类的实现和内存管理🏬日期类的实现🏬C/C内存分布🏬C内存管理方…

【工具】Git-码农“吃饭的碗”要拿好

汝之观览,吾之幸也!本文主要讲解的是Git的轻巧使用(创建、下载、上传、更新、回退),我们平常都是通过idea自带的git工具,或者其他工具来拉取提交代码,这里主要用命令行的方式拉取代码&#xff0…

基于springboot+vue的心理预约咨询测试交流小程序

💖💖作者:IT跃迁谷毕设展 💙💙个人简介:曾长期从事计算机专业培训教学,本人也热爱上课教学,语言擅长Java、微信小程序、Python、Golang、安卓Android等。平常会做一些项目定制化开发…

【REST系列】详解REST架构风格 —— 带你阅读Web发展史上的一个重要技术文献

文章目录REST详解词组解释论文摘要REST架构约束一、Client–server:客户端-服务器二、Stateless:无状态三、Cacheability:缓存四、⭐Uniform Interface:统一接口 (RESTful API)五、Layered System:分层系统六、Code-On…

荧光生物标记物510758-19-7,5-羧基荧光素-炔烃,5-FAM alkyne

5-FAM-Alkyne 是一种高选择性和灵敏的荧光生物标记物,可用于标记碱性磷酸酶 (ALP)。炔烃可以通过铜催化的点击化学与多种叠氮化合物共轭。(西安凯新生物科技有限公司​所有的试剂仅用于科研实验,不可用于人体试验) 5-FAM Alkyne …

【Hadoop】P2 Hadoop简介

Hadoop是什么 Hadoop为分布式系统基础框架。主要解决海量数据的存储和海量数据的分析计算问题。 大数据解决的是海量数据的采集、存储和计算。 Hadoop三大发行版本 Apache 最原始最基础的版本,2006年诞生,开源; Cloudera 内部封装Apache&am…