精华内容
下载资源
问答
  • gampmatlab 最新的压缩感知算法:Generalized Approximate Message Passing及其衍生算法 - 下载 - 搜珍网
    2021-05-06 08:06:27

    code/

    code/BiGAMP/

    code/BiGAMP/BiGAMP.m

    code/BiGAMP/BiGAMPOpt.m

    code/BiGAMP/BiGAMPProblem.m

    code/BiGAMP/BiGAMP_Lite.m

    code/BiGAMP/BiGAMP_X2.m

    code/BiGAMP/checkOptions.m

    code/BiGAMP/coding_error.m

    code/BiGAMP/comparison_codes/

    code/BiGAMP/comparison_codes/grasta/

    code/BiGAMP/comparison_codes/grasta/admm_srp.m

    code/BiGAMP/comparison_codes/grasta/bgfg_seperation_grasta.m

    code/BiGAMP/comparison_codes/grasta/bgtraining.m

    code/BiGAMP/comparison_codes/grasta/column.pdf

    code/BiGAMP/comparison_codes/grasta/GPL.txt

    code/BiGAMP/comparison_codes/grasta/grasta_mc.m

    code/BiGAMP/comparison_codes/grasta/grasta_mc_timing.m

    code/BiGAMP/comparison_codes/grasta/grasta_path.m

    code/BiGAMP/comparison_codes/grasta/grasta_RobustMC_demo.m

    code/BiGAMP/comparison_codes/grasta/grasta_stream.m

    code/BiGAMP/comparison_codes/grasta/LGPL.txt

    code/BiGAMP/comparison_codes/grasta/LICENSE.txt

    code/BiGAMP/comparison_codes/grasta/make_video/

    code/BiGAMP/comparison_codes/grasta/make_video/bgfg_seperation_mf.m

    code/BiGAMP/comparison_codes/grasta/make_video/bgfg_seperation_ReProCSmod.m

    code/BiGAMP/comparison_codes/grasta/make_video/frames2matrix.m

    code/BiGAMP/comparison_codes/grasta/make_video/inexact_alm_rpca/

    code/BiGAMP/comparison_codes/grasta/make_video/inexact_alm_rpca/choosvd.m

    code/BiGAMP/comparison_codes/grasta/make_video/inexact_alm_rpca/ialm_demo.m

    code/BiGAMP/comparison_codes/grasta/make_video/inexact_alm_rpca/inexact_alm_rpca.m

    code/BiGAMP/comparison_codes/grasta/make_video/inexact_alm_rpca/PROPACK/

    code/BiGAMP/comparison_codes/grasta/make_video/inexact_alm_rpca/PROPACK/Afunc.m

    code/BiGAMP/comparison_codes/grasta/make_video/inexact_alm_rpca/PROPACK/AtAfunc.m

    code/BiGAMP/comparison_codes/grasta/make_video/inexact_alm_rpca/PROPACK/Atransfunc.m

    code/BiGAMP/comparison_codes/grasta/make_video/inexact_alm_rpca/PROPACK/bdsqr.m

    code/BiGAMP/comparison_codes/grasta/make_video/inexact_alm_rpca/PROPACK/bdsqr.mexglx

    code/BiGAMP/comparison_codes/grasta/make_video/inexact_alm_rpca/PROPACK/bdsqr.mexsg

    code/BiGAMP/comparison_codes/grasta/make_video/inexact_alm_rpca/PROPACK/bdsqr.mexsg64

    code/BiGAMP/comparison_codes/grasta/make_video/inexact_alm_rpca/PROPACK/bdsqr.mexsol

    code/BiGAMP/comparison_codes/grasta/make_video/inexact_alm_rpca/PROPACK/bdsqr.mexw32

    code/BiGAMP/comparison_codes/grasta/make_video/inexact_alm_rpca/PROPACK/bdsqr_mex.c

    code/BiGAMP/comparison_codes/grasta/make_video/inexact_alm_rpca/PROPACK/Cfunc.m

    code/BiGAMP/comparison_codes/grasta/make_video/inexact_alm_rpca/PROPACK/compute_int.m

    code/BiGAMP/comparison_codes/grasta/make_video/inexact_alm_rpca/PROPACK/dbdqr.f

    code/BiGAMP/comparison_codes/grasta/make_video/inexact_alm_rpca/PROPACK/helio.mat

    code/BiGAMP/comparison_codes/grasta/make_video/inexact_alm_rpca/PROPACK/lanbpro.doc

    code/BiGAMP/comparison_codes/grasta/make_video/inexact_alm_rpca/PROPACK/lanbpro.m

    code/BiGAMP/comparison_codes/grasta/make_video/inexact_alm_rpca/PROPACK/lanbpro.txt

    code/BiGAMP/comparison_codes/grasta/make_video/inexact_alm_rpca/PROPACK/laneig.doc

    code/BiGAMP/comparison_codes/grasta/make_video/inexact_alm_rpca/PROPACK/laneig.m

    code/BiGAMP/comparison_codes/grasta/make_video/inexact_alm_rpca/PROPACK/laneig.txt

    code/BiGAMP/comparison_codes/grasta/make_video/inexact_alm_rpca/PROPACK/lanpro.doc

    code/BiGAMP/comparison_codes/grasta/make_video/inexact_alm_rpca/PROPACK/lanpro.m

    code/BiGAMP/comparison_codes/grasta/make_video/inexact_alm_rpca/PROPACK/lanpro.txt

    code/BiGAMP/comparison_codes/grasta/make_video/inexact_alm_rpca/PROPACK/lansvd.doc

    code/BiGAMP/comparison_codes/grasta/make_video/inexact_alm_rpca/PROPACK/lansvd.m

    code/BiGAMP/comparison_codes/grasta/make_video/inexact_alm_rpca/PROPACK/lansvd.txt

    code/BiGAMP/comparison_codes/grasta/make_video/inexact_alm_rpca/PROPACK/mminfo.m

    code/BiGAMP/comparison_codes/grasta/make_video/inexact_alm_rpca/PROPACK/mmread.m

    code/BiGAMP/comparison_codes/grasta/make_video/inexact_alm_rpca/PROPACK/mmwrite.m

    code/BiGAMP/comparison_codes/grasta/make_video/inexact_alm_rpca/PROPACK/pythag.m

    code/BiGAMP/comparison_codes/grasta/make_video/inexact_alm_rpca/PROPACK/refinebounds.m

    code/BiGAMP/comparison_codes/grasta/make_video/inexact_alm_rpca/PROPACK/reorth.f

    code/BiGAMP/comparison_codes/grasta/make_video/inexact_alm_rpca/PROPACK/reorth.m

    code/BiGAMP/comparison_codes/grasta/make_video/inexact_alm_rpca/PROPACK/reorth.mexglx

    code/BiGAMP/comparison_codes/grasta/make_video/inexact_alm_rpca/PROPACK/reorth.mexsg

    code/BiGAMP/comparison_codes/grasta/make_video/inexact_alm_rpca/PROPACK/reorth.mexsg64

    code/BiGAMP/comparison_codes/grasta/make_video/inexact_alm_rpca/PROPACK/reorth.mexsol

    code/BiGAMP/comparison_codes/grasta/make_video/inexact_alm_rpca/PROPACK/reorth_mex.c

    code/BiGAMP/comparison_codes/grasta/make_video/inexact_alm_rpca/PROPACK/test.m

    code/BiGAMP/comparison_codes/grasta/make_video/inexact_alm_rpca/PROPACK/testtqlb.m

    code/BiGAMP/comparison_codes/grasta/make_video/inexact_alm_rpca/PROPACK/tqlb.f

    code/BiGAMP/comparison_codes/grasta/make_video/inexact_alm_rpca/PROPACK/tqlb.m

    code/BiGAMP/comparison_codes/grasta/make_video/inexact_alm_rpca/PROPACK/tqlb.mexglx

    code/BiGAMP/comparison_codes/grasta/make_video/inexact_alm_rpca/

    更多相关内容
  • Message Passing Introduction 我们前面介绍了概率论的基础和基本的贝叶斯网络的基础。这一节我们会给你一个黑盒子,它能在你提供一些信息的情况下回答你的问题。而这个黑盒子就是参数确定了的贝叶斯网络啦,而...

    ​Message Passing

    Introduction

    我们前面介绍了概率论的基础和基本的贝叶斯网络的基础。这一节我们会给你一个黑盒子,它能在你提供一些信息的情况下回答你的问题。而这个黑盒子就是参数确定了的贝叶斯网络啦,而这个根据事实回答文题的功能被称为 Inference

    Inference

    定义:计算事件 Si 在定义一些结点 Sj 的信息后的概率 P(Si | {Sj = x}),其中 {sj=x} 这个集合被称为证据 (evidence),Sj 就是被观测的变量.

    Inference 分类

    所有的 inference 方法可以分成大的两类:

    1. 确定性推断

      Message Passing (1988)

      Junction Tree (1990)

      Shafer-Shenoy (1990)

    2. 近似推断

      Sampling (包括MCMC, Gibbis, Slice)

      Variational methods

    今天我们就来介绍一下最简单的 Message Passing 啦

    Message Passing

    先给严肃正儿八经的定义

    基本的规则

    1. 该算法只适用于 Polytree (有向无环图),当所有的方向去掉后就是一个树结构
    2. 每个节点都会给自己的父节点和子节点发信息


    基本定义

    1. 证据节点 ε = Nx  Dx,其中 Nx 是 X 的非子孙节点 (绿色虚框中的所有节点),Dx 是 X 的子孙节点 (蓝色虚框中的所有节点)

    2. 对于 X 而言有两种信息与它相关,从自身传到子孙节点的 λ 信息,从非子孙节点传过来的 π 信息,我们可以证明 P(X|ε=e) ∝ λ(X)π(X),此时 λ(X) ∝ P(Dx|X) π(X) ∝ P(X|Nx).

      证明

      由于 P(X) 和 P(Dx) 是贝叶斯网络中的参数,所以已知,我们可以把红框内的概率当做常数,从而P(X|ε=e) ∝ P(X|Nx) P(Dx|X), 然后结论得证

      由此我们可以计算出 P(X|ε=e) 在每个取值 Xi 关于 λ(Xi)π(Xi) 成比例的值,然后根据这些值做归一化就得到 P(X|ε=e)

      那么我下一步就具体讲讲怎么求传递到我们的 X 节点的 λ(X) 和 π(X) 信息啦~ ~ ~


    从子孙节点传递过来的 λ信息 λ(X)∝ P(Dx|X )

    1. 初始节点的λ信息

      如果 X 是没有被观测到的叶子节点:λ(X) = [1 . . . 1]

      如果 X 是被观测了的节点:λ(X) = [001 . . . 0]

      λ(X) 的维度是 X 所有可能取值的大小

      EXP:比如X是天气,假定我们有阴天,晴天,雨天,下雪天。

      如果 X 是第一种情况 λ(X) = [1, 1, 1, 1];若 X 是第二种情况比如 X=雨天 λ(X) = 0, 0, 1, 0

    2. λ信息的传递和收集

      从孩子节点 Y 传递到当前节点 X 的 λ信息:

      收集所有孩子节点 Y 传递到 **X ** 的 λ信息:


    从非子孙节点传递过来的 π信息 π(X) ∝ P(X|Nx )

    1. 初始节点的π信息

      如果 X 是没有被观测到的根节点:π(X) = P(X)

      如果 X 是被观测了的节点:π(X) = [001 . . . 0]

    2. π信息的传递和收集

      从父节点 Z 传递到当前节点 X 的 π信息

      收集所有父节点 Z 传递到 X 的 π信息

      注意:从某一父节点传递过来的信息是从 Z 的除 X 外的子节点传递过来的 λ 信息

    Inference Example

    新版踢猫效应

    如图是踢猫效应的贝叶斯模型和初始参数,假设只有儿子会踢猫 (Message Passage 只适用于有向无环图)

    F 节点代表爸爸今天上班有没有被批评,F=0 代表没有被批评;F=1 代表被批评

    被批评的概率为0.2,没有被批评的概率为0.8.

    S 节点表示儿子是否被骂,S=0 代表儿子没有被骂,S=1 代表儿子被骂

    当 F=0 时,儿子被骂可能性为0.8,没被骂的可能性为 0.2;当F=1时,儿子被骂可能性为0.5,没被骂的可能性为0.5. 有 P(S=0|F=0)=0.5, P(S=1|F=0)=0.5, P(S=0|F=1)=0.2, P(S=1|F=1)=0.8

    D 节点代表女儿是否被骂,D=0 代表女儿没有被骂,D=1 代表女儿被骂

    类似的,P(D=0|F=0)=1, P(D=1|F=0)=0, P(D=0|F=1)=0.5, P(D=1|F=1)=0.5

    (对比两组数量来看,整体来看爸爸对儿子没那么友好 ~ ~ ~)

    C 节点代表猫是否被踢,C=0 (猫没事儿),C=1(猫挨踢了)

    P(C=0|S=0)=0.8, P(C=1|S=0)=0.2,P(C=0|S=1)=0.2,P(C=1|S=1)=0.8

    基于以上贝叶斯模型,我们来提两个问题:

    1. 当爸爸今天上班挨批了,猫咪挨踢的概率是多少?

    2. 这种情况下,女儿挨骂的概率是多少?

    OK,run起我们的 Message Passing Reference,看看这两个事件发生的概率

    λ信息

     

    π信息

    最终根据爸爸上班挨批的信息,所有的 λ信息和 π信息如下图所示:

    根据此前的 P(X|ε=e) ∝ λ(X)π(X)

    P(猫咪挨踢|爸爸上班挨批) = P(C=1|F=1) ∝  λ(C=1)π(C=1) = 1*0.68

    P(猫咪没事儿|爸爸上班挨批) = P(C=0|F=1) ∝  λ(C=0)π(C=0) = 1*0.32

    所以 P(猫咪挨踢|爸爸上班挨批) = 0.68/(.68+0.32) = 0.68

    P(女儿挨骂|爸爸上班挨批) = P(D=1|F=1)  ∝  λ(D=1)π(D=1) = 1*0.5

    P(女儿没事儿|爸爸上班挨批) = P(D=0|F=1)  ∝  λ(D=0)π(D=0) = 1*0.5

    所以 P(女儿挨骂|爸爸上班挨批) = 0.5 / (0.5+0.5) = 0.5

    大家感兴趣的话,可以自己推一下女儿挨批的情况下,猫咪被踢的概率,以及儿子被骂的概率是怎么样的,这个问题可能会更有趣!

    Reference

    [南特大学概率图模型] by Philippe LERAY & Hoel LE CAPITAINE

    因为微信限制 gif 大小,如果感情趣的同学留言,我可以把完整的动画PPT分享给你,那各位今天就是这样啦,假期快乐!

    展开全文
  • 用于广义近似消息传递 (GAMP) 的 MATLAB 代码。 GAMP 是循环置信传播的高斯近似,用于压缩感知中的估计问题和其他具有线性混合的非高斯问题。
  • 用于LDPC的译码程序,使用message passing 算法,可以选择迭代次数, 调整信噪比,用LLR计算
  • 将人脸识别和近似消息传递算法结合起来,实现了算法更好的鲁棒性,对于算法研究比较有意义
  • message passing algorithm,解释消息传递算法原理,有具体例子(Message Passing Algorithms for Compressed Sensing: I. Motivation and Construction.pdf)
  • Approximate Message Passing vs. Sparse Bayesian Learning? 2012-8-7 05:19 |个人分类:我的论文|系统分类:科研笔记|关键词:稀疏贝叶斯学习,压缩传感,稀疏信号恢复| 压缩传感, 稀疏贝叶斯学习, 稀疏信号恢复 ...

    Approximate Message Passing vs. Sparse Bayesian Learning?

    2012-8-7 05:19

    |个人分类:我的论文|系统分类:科研笔记|关键词:稀疏贝叶斯学习,压缩传感,稀疏信号恢复|
    压缩传感, 稀疏贝叶斯学习, 稀疏信号恢复

    上周Nuit Blanche发了一篇博文《More intra-block correlation and sparse sensing matrices》,内容是The Ohio State University的Phil写给他的一封邮件,其中介绍了Phil组里最近投出的基于Approximate Message Passing (AMP)的压缩传感(Compressed Sensing, CS)算法。信中最后说道,“ we get performance that meets or exceeds that of Bayesian or variational techniques, but with orders-of-magnitude reduction in complexity”,也就是说,AMP算法比稀疏贝叶斯学习(Sparse Bayesian Learning, SBL)算法性能要好,同时速度快了一个档次。但是这句话是值得商酌的,不正确的。我猜想Phil的意思是, 在他们的文章中给出的试验条件和应用场合里(比如video/image coding),AMP比 目前的SBL既好又快。

    其实在很多情况下和实际应用中,SBL都比AMP性能远远优越。 第一个情况就是,当传感矩阵(sensing matrix)或者字典矩阵(dictionary matrix)的列与列之间非常相关时,决大多数算法包括AMP算法性能都非常差。而SBL算法的性能却保持良好。这种情况多见于source localization and tracking (比如波达方向估计,脑源定位,雷达探测……),生物医学数据分析(比如基因表达中的特征提取,神经成像数据中的特征提取),以及计算视觉(比如基于稀疏表达的人脸识别,表情识别,视觉追踪等等)。实际上,SBL在这种情况下的优势已经部分的被我们实验室的师兄David Wipf证明过了。他在2011年的NIPS文章《 Sparse Estimation with Structured Dictionaries》里,从数学上证明了在这种sensing matrix (or dictionary matrix)非常coherent的情况下,为什么SBL比Lasso性能要好。

    为了让读者对这种情况下的各个压缩传感算法的性能有多差有个感性认识,我在提供了一个Matlab仿真程序供下载: http://dsp.ucsd.edu/~zhilin/papers/Localization.zip. 这个仿真程序模拟了一个简单的基于multiple snapshots的脑电源定位的试验,其中的sensing matrix(在EEG领域,叫做lead-field matrix)来自于由一个大脑模型构建的lead-field matrix(通常是100 x 10000维,但是我把它缩小成了50x400维,这样可以在1秒左右的时间里就可以获得结果)。这个sensing matrix的列与列之间的相关性可达0.99以上。我比较了我们实验室的三种成名算法,分别是M-FOCUSS,M-SBL和我的T-MSBL。读者可以看到SBL算法远远比M-FOCUSS算法好。读者也可以利用这个程序使用自己喜好的熟悉的算法,可以看到在这种情况下其它算法的性能非常差。

    另外,在这里http://dsp.ucsd.edu/~zhilin/papers/Experiment.rar 我提供了一个基于single snapshot的源定位试验仿真程序。这里比较了14个算法的性能,可以看到SBL算法性能最好,尤其是T-MSBL。这个试验还有一个note,可以在这里下载:http://dsp.ucsd.edu/~zhilin/papers/comparison.pdf

    除了上面这个情况外, 当信号不是特别稀疏甚至根本不稀疏的时候,SBL算法也表现出很好的优势。在我的关于生理信号远程监控的文章《 Low Energy Wireless Body-Area Networks for Fetal ECG Telemonitoring via the Framework of Block Sparse Bayesian Learning》中,大量的试验显示了BSBL能够以很高的质量 直接恢复非稀疏的信号(i.e.,不借助于其它技术)。另外在我的文章《 Extension of SBL Algorithms for the Recovery of Block Sparse Signals with Intra-Block Correlation》中,也显示了BSBL在无噪条件下并且已知Block Structure的情况下,可以仅仅只用M个测量值精确恢复一个有M个非零元素的长度为N的信号(N远远大于M,比如N=10M,非零元素的位置未知)。所以,大量的试验显示了SBL对于非稀疏,或者不是特别稀疏的信号有明显的优势。要知道,在绝大多数实际问题中,信号并不是特别稀疏的。在compressed sensing领域中,传统上大家通过寻找dictionary matrix来获得信号的稀疏表示。但是目前这个方向还正在发展,对很多非稀疏信号并不能找到有效的稀疏表示。而SBL从另外一个方向获得了突破。关于BSBL能够只用M个测量值精确恢复一个有M个非零元素的长度为N的信号,其实可以用我的文章《 Sparse Signal Recovery with Temporally Correlated Source Vectors Using Sparse Bayesian Learning》中的定理1来证明。所以这里就不过多展开了。

    正因为在实际问题中,通常sensing matrix(或者dictonary matrix)列与列之间相关性很大,信号又并不很稀疏,导致了绝大多数已有的算法并不能达到特别理想的效果(或者效果还有很大的提升空间),而SBL则显示出了很大的优势。所以SBL作为压缩传感/稀疏信号处理的一个分支,越来越多的应用在很多实际问题中。我们实验室,作为开发SBL算法的主要实验室之一,已经和国内,美国,欧洲不少学校/研究机构开始了合作。相信明年会有大批应用的文章涌现。

    当然,SBL的速度不快。但是这种情况正在转变。一个原因是,SBL可以转换成一个加权迭代的算法。比如,在我的文章《 Extension of SBL Algorithms for the Recovery of Block Sparse Signals with Intra-Block Correlation》中,BSBL算法可以用group Lasso算法迭代3-4次实现。每年都有不少的更快的group Lasso算法提出来,所以可以预见BSBL算法也会越来越快。另外,现在也有不少比较快的SBL算法了。比如我上面这篇文章中的BSBL-BO算法,以及我们最近的CVPR 2012文章《 Sparse Bayesian Multi-Task Learning for Predicting Cognitive Outcomes from Neuroimaging Measures in Alzheimer's Disease》中的基于固定点的快速算法。我现在还有几个更快的算法,大概下个月就要投出去了。
     
    综上,基于Phil的那句可能会引起误会的话,我在这里把SBL的几个优势稍微讲解了一下。有兴趣的朋友可以去我网页http://dsp.ucsd.edu/~zhilin/ 或者https://sites.google.com/site/researchbyzhang/ 详细了解SBL算法,最近的发展和下载这篇博文中提到的文章(以及代码)。另外,我和武汉大学的孙洪老师,余磊朋友有一篇中文的邀请综述:《 从稀疏到结构化稀疏:贝叶斯方法》(后半部分是我们实验室开发的一系列SBL算法),发表在最近的《信号处理》杂志上。网上可以下载到。

    链接地址: http://blog.sciencenet.cn/blog-765184-599713.html


    展开全文
  • 图像的压缩感知之AMP算法,相较于FISTA算法在执行效率上更加有效,迭代到30次左右可实现很小的误差。
  • 消息传递(Message Passing

    万次阅读 2014-05-16 16:22:19
    消息传递(Message Passing)   通常可用把并行程序理解为一组相互独立的、能够发关和接收消息的组件,这也称为角色模型(ActorModel),在维基百科上可找到更正式的解释 ...虽然使用消息传递的场景往往相当复杂,...

    消息传递(Message Passing)

     

    通常可用把并行程序理解为一组相互独立的、能够发关和接收消息的组件,这也称为角色模型(ActorModel),在维基百科上可找到更正式的解释 http://en.wikipedia.org/wiki/Actor_model。虽然使用消息传递的场景往往相当复杂,但是其背后的思想却相对简单,正像下面将要看到的示例一样:

    消息传递背后的基本思想是这样的,系统是由代理(agents)或角色(actors)组合面成的,它们都可以发送和接收消息。当代理接收消息时,这个消息被放在队列(queue)中,直到这个代理准备处理它;当代理处理消息时,根据消息的内部状态和内容决定做什么。代理有多种的可能性为了响应入站消息:可能发送应答给初始绷住的代理,可为不同的代理创建澵消息,可创建新代理,还可能更新一些内部数据结构。

    F# 提供了泛型类 MailboxProcessor,实现消息传递和角色模型。当MailboxProcessor 创建时,它就有(从名字可推测)一个消息队列,能够用于接收消息;MailboxProcessor 负责决定消息接收以后做什么。实现 MailboxProcessor往往要遵循一些简单的模式,下面的示例演示了 MailboxProcessor 的最简单模式:

     

    open System

     

    let mailbox =

      MailboxProcessor.Start(funmb ->

        letrec loop x =

          async { let! msg = mb.Receive()

                 let x = x + msg

                 printfn "Running total: %i - newvalue %i" x msg

                 return! loop x }

        loop0)

     

    mailbox.Post(1)

    mailbox.Post(2)

    mailbox.Post(3)

     

    Console.ReadLine() |> ignore

     

    前面代码的运行结果如下:

     

    Running total: 1 - new value 1

    Running total: 3 - new value 2

    Running total: 6 - new value 3

     

    在第一部分,我们创建一个信箱,接收整型消息。当信箱接收到消息时,就把它加到运行中的总计,然后,显示这个运行中的总计,连同接收到的值一起。我们仔细看看这是如何实现的。MailboxProcessor 有一个静态的启动(Start)方法,它接收的参数为一个函数,这个函数有一个MailboxProcessor 的新实例,它必须返回工作流;应该用这个异步工作流去读队列中的消息。它之所以能成为异步工作流,是因为消息需要以异步方式读,这保证了信箱不会依赖于一个线程,如果有大量信箱会导致扩展性问题。需要检查队列是否有新消息到达,通常,是使用一个无限循环去检查队列。这里,我们定义了一个递归函数 loop,它通过调用 Receive 函数读队列,然后处理消息,最后调用它自己再启动一个进程。这个一个无限递归,但没有栈举出的危险,是因为这个函数是尾递归(tail recursive)的。loop 函数只有一个参数,我们用它来保存信箱的状态,在这里就是一个整数,表示运行中的总计。

    还有一点值得注意的是,在示例的结尾有一句 Console.ReadLine(),这很重要,这是因为消息队列是在单独的线程中处理的,一旦我们使用 Post 方法发布消息完成之后,主线程就不再运行,直接退出,导致进程退出。在这里,进程可能会在信箱刚处理队列中的消息之前退出。调用Console.ReadLine(),提供了一种简单的方法阻塞主线程,直到用户有机会看到处理消息的信箱结果。

    关于此示例的最后细节:信箱的 Post 成员函数从任何线程调用都案例的,因为信箱的工作队列,可以保证每个消息能够依次以原子方式被处理。但是,目前的这个示例还未乃至这一点,但很快在下面的两个示例中就能见到。

    这个特定的异步工作流没什么用处,但是,它说明了工作流最简单的使用模式:接收消息,更新一些内部状态,然后响应消息。在这里,响应消息就是写到控制台,这可能过于简单化而没有太多的用处。然而,可以发现这种使用模式更实用的情形,比如,使用信箱去收集大量的值,然后,集中到图形界面线程,用来显示值。在下面两个示例中我们将学习更多有关这种方法。

    首先,我们将以更详细一点的方式来看一下我们要解决的问题。如果需要模拟生成数据,我们可能想要版实时生成的数据;当使用图形界面时,需要面对两个富有挑战性的约束。第一,图形界面必须运行在它自己的线程中,且这个线程必须不能长时间占用,否则,图形界面就会没有响应,这样,要在图形界面线程中长时间运行这个模拟程序是不可能的;第二,访问图形界面只能从创建它的线程中,即图形界面线程。如果模拟程序运行其他线程,那么就不能直接写到图形界面。好在图形界面对象提供了Invoke 方法,它可以在图形界面线程中调用函数,以安全地方式用生成的数据更新图形界面。调用 Invoke 函数,在性能方面通常也会有消极影响,因为把数据都集中到图形界面代价很大。如果模拟程序频繁地输出少量数据,指处理结果是一个好办法,在屏幕上每秒种打印 12 到 20 次,就能得到平滑的动画效果。我们先学习如何使用信箱来解决这个问题的特定案例,然后,再看第二个示例,把它整理成更为通用。

    F# 的信箱在这里,能够以优雅的方式在打印数据到屏幕之前缓冲数据。这个算法的基础相当简单。运行模拟程序的线程提交消息到信箱;当信箱接收了足够多的消息后,就通知图形界面有新更新需要绘制。这种编程网格还提供了一种整洁的方式,把生成数据的逻辑与图形界面中表示数据的逻辑分开来。我们来看一下完整的代码,然后,再分步解释它是如何工作的。运行这个程序需要引用System.Drawing.dll 和 System.Windows.Forms.dll:

     

    open System

    open System.Threading

    open System.Windows.Forms

    open System.Drawing.Imaging

    open System.Drawing

     

    // the width & height for thesimulation

    let width, height = 500, 600

     

    // the bitmap that will hold the outputdata

    let bitmap = new Bitmap(width, height,PixelFormat.Format24bppRgb)

     

    // a form to display the bitmap

    let form = new Form(Width = width, Height =height,

                        BackgroundImage = bitmap)

     

    // the function which recieves that pointsto be plotted

    // and marshals to the GUI thread to plotthem

    let printPoints points =

      form.Invoke(newAction(fun () ->

        List.iterbitmap.SetPixel points

        form.Invalidate()))

      |>ignore

     

    // the mailbox that will be used to collectthe data

    let mailbox =

      MailboxProcessor.Start(funmb ->

        //main loop to read from the message queue

        //the parameter "points" holds the working data

        letrec loop points =

         async { // read a message

                  let! msg = mb.Receive()

                  // if we have over 100 messageswrite

                  // message to the GUI

                 if List.length points > 100then

                    printPoints points

                    return! loop []

                  // otherwise append message andloop

                  return! loop (msg :: points) }

        loop[])

     

    // start a worker thread running our fake simulation

    let startWorkerThread() =

      //function that loops infinitely generating random

      //"simulation" data

      letfakeSimulation() =

        letrand = new Random()

        letcolors = [| Color.Red; Color.Green; Color.Blue |]

        whiletrue do

         // post the random data to the mailbox

         // then sleep to simulate work being done

         mailbox.Post(rand.Next(width),

           rand.Next(height),

           colors.[rand.Next(colors.Length)])

         Thread.Sleep(rand.Next(100))

      //start the thread as a background thread, so it won't stop

      //the program exiting

      letthread = new Thread(fakeSimulation, IsBackground = true)

      thread.Start()

     

    // start 6 instances of our simulation

    for _ in 0 .. 5 do startWorkerThread()

     

    // run the form

    Application.Run form

     

    这个示例有三个关键部分:模拟程序如何把数据发到信箱,信箱如何缓存需要发送到图形界面上的点,图形界面如何接收这些点。我们就分别看一看。把数据发到信箱仍然很简单,继续调用信箱的 Post 方法,但这个示例与前面一个有两点重要不同:第一,传递的数据结构不同,但是,因为 Post 方法是泛型的,故仍保持强类型;第二,从六个不同的线程中调用 Post 方法。消息队列使它工作的很好,因此,每一个都能工作。使用一种简单的方法缓存数据,这样就能名统计接收到的消息数,当接收到 100 个消息时,就把它们发送到图形界面:

     

    async { // read a message

           let! msg = mb.Receive()

           // if we have over 100 messages write

           // message to the GUI

           if List.length points > 100 then

             printPoints points

             return! loop []

           // otherwise append message and loop

           return! loop (msg :: points) }

     

    数字 100 是随意定的,尤其是对于这种模拟程序,似乎是更好的选择。还有一点值得注意,统计每次循环接收到的消息数,使用List.length 函数,从性能 的角度来看,这不是最理想的,因为 List.length函数在我们每次调用时,都要遍历整个列表。这对于我们目前的示例算不上什么,因为这个列表相当小;然而,如果增加缓冲的大小,这种方法就会变成瓶颈了。更好的方法可以是把函数每次迭代期间的增量,作为参数单独保存;然而,这个示例没有这样做,是为了保持简单。还有一种方法是保存上次更新的时间,如果前一次更新的时间超过了二十分之一秒,才再次更新。这个方法效果不错,因为它可以让我们只关注为了达到平滑的动画效果而需要的每秒多少帧数。另外,本书的示例没有使用这种方法,因为何用这种方法会增加使示例复杂化的不必要元素。这个示例还有一点值得说一下,即如何把数据写到屏幕:

     

    let printPoints points =

      form.Invoke(newAction(fun () ->

        List.iterbitmap.SetPixel points

        form.Invalidate()))

      |>ignore

     

    这个函数 printPoints 很简单, 它有一个参数 points,调用窗体上下文中的委托,把点写成位图,最后,调用窗体的 Invalidate函数保证点的正确显示。

    前一个示例很好地演示了如何使用信箱,但它有一主要的问题是代码不能重用,如果能把信箱包装成一个可重用的组件就更好了,F# 面向对象的功能提供了很好的解决途径。下面的示例还演示了两个重要的概念,比如,如何在同一个信箱中支持不同类型的消息,以及如何把消息返回给信箱客户端。另外,运行这个示例需要引用System.Drawing.dll 和System.Windows.Forms.dll:

     

    open System

    open System.Threading

    open System.ComponentModel

    open System.Windows.Forms

    open System.Drawing.Imaging

    open System.Drawing

     

    // type that defines the messages types ourupdater can handle

    type Updates<'a> =

      |AddValue of 'a

      |GetValues of AsyncReplyChannel<list<'a>>

      |Stop

     

    // a generic collecter that recieves anumber of post items and

    // once a configurable limit is reachedfires the update even

    type Collector<'a>(?updatesCount) =

      //the number of updates to cound to before firing the update even

      letupdatesCount = match updatesCount with Some x -> x | None -> 100

     

      // Capture the synchronization context of thethread that creates this object. This

      //allows us to send messages back to the GUI thread painlessly.

      letcontext = AsyncOperationManager.SynchronizationContext

      letrunInGuiContext f =

        context.Post(newSendOrPostCallback(fun _ -> f()), null)

     

      // This events are fired in thesynchronization context of the GUI (i.e. the thread

      //that created this object)

      letevent = new Event<list<'a>>()

      letmailboxWorkflow (inbox: MailboxProcessor<_>) =

        //main loop to read from the message queue

        //the parameter "curr" holds the working data

        //the parameter "master" holds all values received

        letrec loop curr master =

         async { // read a message

                  let! msg = inbox.Receive()

                  match msg with

                  | AddValue x ->

                    let curr, master = x :: curr, x:: master

                    // if we have over 100 messages write

                    //message to the GUI

                    if List.length curr > updatesCount then

                      do runInGuiContext(fun () ->event.Trigger(curr))

                      return! loop [] master

                    return! loop curr master

                  | GetValues channel ->

                    // send all data received back

                    channel.Reply master

                    return! loop curr master

                  | Stop -> () } // stop by notcalling "loop"

        loop[] []

     

      //the mailbox that will be used to collect the data

      letmailbox = new MailboxProcessor<Updates<'a>>(mailboxWorkflow)

     

      //the API of the collector

     

      //add a value to the queue

      memberw.AddValue (x) = mailbox.Post(AddValue(x))

      //get all the values the mailbox stores

      memberw.GetValues() = mailbox.PostAndReply(fun x -> GetValues x)

      //publish the updates event

      [<CLIEvent>]

      memberw.Updates = event.Publish

      //start the collector

      memberw.Start() = mailbox.Start()

      //stop the collector

      memberw.Stop() = mailbox.Post(Stop)

     

    // create a new instance of the collector

    let collector = newCollector<int*int*Color>()

     

    // the width & height for thesimulation

    let width, height = 500, 600

     

    // a form to display the updates

    let form =

      //the bitmap that will hold the output data

      letbitmap = new Bitmap(width, height, PixelFormat.Format24bppRgb)

      letform = new Form(Width = width, Height = height, BackgroundImage = bitmap)

      //handle the collectors updates even and use it to post

      collector.Updates.Add(funpoints ->

        List.iterbitmap.SetPixel points

        form.Invalidate())

      //start the collector when the form loads

      form.Load.Add(fun_ -> collector.Start())

      //when the form closes get all the values that were processed

      form.Closed.Add(fun_ ->

        letvals = collector.GetValues()

        MessageBox.Show(sprintf"Values processed: %i" (List.length vals))

        |>ignore

        collector.Stop())

      form

     

    // start a worker thread running our fakesimulation

    let startWorkerThread() =

      //function that loops infinitely generating random

      //"simulation" data

      letfakeSimulation() =

        letrand = new Random()

        letcolors = [| Color.Red; Color.Green; Color.Blue |]

        whiletrue do

         // post the random data to the collector

         // then sleep to simulate work being done

         collector.AddValue(rand.Next(width),

           rand.Next(height),

           colors.[rand.Next(colors.Length)])

         Thread.Sleep(rand.Next(100))

      //start the thread as a background thread, so it won't stop

      //the program exiting

      letthread = new Thread(fakeSimulation, IsBackground = true)

      thread.Start()

     

    // start 6 instances of our simulation

    for _ in 0 .. 5 do startWorkerThread()

     

    // run the form

    Application.Run form

     

    这个示例的输出与前一个示例完全相同,基础代码很大程度上也遵循了相同的模式;然而,两者之间也有一些重要的差别。最明显的可能是现在的信箱被包装在一个提供了强类型接口的对象中,我们已经创建了类Collector<'a>,它的接口像这样:

     

    type Collector<'a> =

      class

        new: ?updatesCount:int -> Collector<'a>

        memberAddValue : x:'a -> unit

        memberGetValues : unit -> 'a list

        memberStart : unit -> unit

        memberStop : unit -> unit

        memberUpdates : IEvent<'a list>

    end

     

    这个类是泛型,依据它所收集数据的类型,它的 AddValue 方法用于发送到内部信箱,GetValues 获得到目前为止信箱中的所有消息;采集器(collector)现在必须由它的Start 和 Stop 方法显式启动、停止;最后,采集器(collector)的更新(Updates)事件,当收集到足够的消息时触发。使用事件是一个重要的设计细节,通过事件通知客户端已有更新,这样,采集器(Collector<'a>)不需要知道它的客户端的使用情况,极大地改进了可用性。

    现在使用联合(union)类型表示消息,这样,就可以不同类型消息的灵活性。采集器(Collector<'a>)的客户端并不直接处理消息,而是使用它提供的成员方法。这个成员方法具有创建不同类型消息的任务,能够为消息队列提供一个值,还可以发送一个消息以读取所有当前消息,以及从读到的新消息中停止信箱[a message to stop the mailbox from reading new messages,真的搞不懂谁停止谁]:

     

    type Updates<'a> =

      |AddValue of 'a

      |GetValues of AsyncReplyChannel<list<'a>>

      |Stop

     

    接下来,对接收到的消息通过模式匹配实现峭同类型的消息:

     

    let! msg = inbox.Receive()

    match msg with

    | AddValue x ->

      letcurr, master = x :: curr, x :: master

      //if we have over 100 messages write

      //message to the GUI

      ifList.length curr > updatesCount then

        dorunInGuiCtxt(fun () -> fireUpdates(curr))

        return!loop [] master

      return!loop curr master

    | GetValues channel ->

      //send all data received back

      channel.Replymaster

      return!loop curr master

    | Stop -> ()

     

    AddValue 联合的情况是前一个示例主要做的工作,除了这次把值添加到 curr 和 master 列表以外,curr列表保存了将要传递给图形界面的、在下一次需要更新的值,而 master 列表中保存了所有接收到的值;master    列表可以容纳任何客户端请求的所有值。

    对于 GetValues 联合的情况是值得花时间看一下的,表示图记端如何返回值。通过调用信箱的PostAndReply 方法,而不是 Post 方法启动这个过程的,可以看到GetValues 成员方法的实现:

     

    // get all the values the mailbox stores

    member w.GetValues() =mailbox.PostAndReply(fun x -> GetValues x)

     

    PostAndReply 方法接受一个函数,传递 AsyncReplyChannel<'a>类型,能够使用这个 AsyncReplyChannel<'a> 类型把消息发送回调用者,通过它的Reply 成员,这就是我们在联合的 GetValues 情况所见到的。使用这个方法需要小心,因为在消息返回之前会被阻塞,就是说,直到消息到达队列的前端才会被处理,如果队列很长,花的时间可能也会很长。这样,用户更多地会使用AsyncPostAndReply 方法,因为它可以在等待应答期间避免阻塞线程;然而,这个示例并没有这样做,主要是为了保持示例的简单。

    Stop 联合的情况最简单,即停止从队列中读消息;所要做的就是避免递归地调用loop 方法。在这里,这不是问题,但,仍然要返回一个值,我们返回了一个空(unit)类型,用空的括号表示。在这里唯一需要注意的问题是,调用停止(Stop)方法后,不会立即停止信箱,即,只有当要停止的消息到达队列的前端时,才停止信箱。

    我们已经看到如何用采集器(Collector<'a>)类型处理消息,现在来看一下采集器是如何触发更新事件,以便运行在图形界面进程。使用New Event 创建更新事件,就像在 F# 中创建所有其他事件一样。使用runInGuiContext 函数使这个事件运行在图形界面的上下文中:

     

    let context =AsyncOperationManager.SynchronizationContext

    let runInGuiContext f =

      context.Post(newSendOrPostCallback(fun _ -> f()), null)

     

    首先,保存创建这个对象的线程的 SynchronizationContext,使用System.ComponentModel 命名空间中的 AsyncOperationManager的静态属性实现。SynchronizationContext 能够收集到使用它的 Post 成员方法创建的线程,唯一需要小心的事情就是创建采集器对象的线程会成为图形界面线程;然而,我们通常使用主程序线程来做这两件事,因此,这就不成为问题了。这种收集同步上下文的方法也用在BackgroundWorker 类中,见本章的“响应式编程”一节。

    现在,窗体的定义就有点简单了,因为我们不再需要为调用信箱而提供函数,而只要简单地处理更新(Updates)事件:

     

    // handle the collectors updates even anduse it to post

    collector.Updates.Add(fun points ->

      List.iterbitmap.SetPixel points

      form.Invalidate())

     

    我们现在还能利用窗体的关闭(Closed)事件来停止信箱处理程序,并获得在用户关闭窗体时忆处理的所有消息的列表:

     

    // when the form closes get all the valuesthat were processed

    form.Closed.Add(fun _ ->

      letvals = collector.GetValues()

      MessageBox.Show(sprintf"Values processed: %i" (List.length vals))

      |>ignore

      collector.Stop())

     

    我们没有改变示例的行为,但这些增加的部分极大地改进了代码了设计,减少了信箱代码与图形界面代码的耦合,极大地提高了采集器类的重用性。

     

     

    第十章 小结

     

    在这一章,我们讨论了大量的基础知识,也看到了五种不同并发技术,在特定的应用程序中都有它们的位置。

    在下一章,我们将学习如何使用其中的一些方法,特别是异步工作流,能使开发分布式应用程序(DistributedApplications)更容易。

     

    展开全文
  • GNN中的Message Passing方法解析 一、GNN中是如何实现特征学习的? 深度学习方法的兴起是从计算图像处理(Computer Vision)领域开始的。以卷积神经网络(CNN)为代表的方法会从邻近的像素中获取信息。这种方式对于...
  • 消息传递图神经网络 一、引言 在开篇中我们介绍了,为节点生成节点表征(Node Representation)是图计算任务成功的关键,...首先我们将学习图神经网络生成节点表征的范式–消息传递(Message Passing)范式。 接着我
  • message passing neural network——MPNN

    千次阅读 2020-07-25 10:09:05
    message passing neural network 》 这篇工作是2017 年的工作《Neural Message Passing for Quantum Chemistry》,消息传递神经网络(Message Passing Neural Network,MPNN) 分为以下几个部分介绍: ...
  • 近似信息传递稀疏约束算法用来进行稀疏约束重建以及方程求解
  • 还提供了一个独立的 MATLAB LDPC 解码器 mpdec,以清楚地了解算法的工作原理。 不涉及 C/C++。 请从文档文件“readme.txt”开始。 演示 C/C++ MPDecoder 类使用的 MSVC++ 项目可在此处获得: ...
  • MPNN(message passing neural networks)

    千次阅读 2020-04-12 18:55:38
    Neural Message Passing for Quantum Chemistry阅读笔记1. 摘要2. 贡献3. 信息传递网络3.1卷积网络的分子指纹学习 ( Convolutional net-works on graphs for learning molecular fingerprints)3.2 门图神经网络...
  • 对于消息传递阶段(Message Passing):消息函数定义为 MtM_tMt​,定点更新函数定义为 UtU_tUt​, ttt为运行的时间步,更新过程如下: mvt+1=∑w∈N(v)Mt(hvt,hwt,evw)m_v^{t+1}=\sum_{w \in N(v)}M_t(h_v^t,h_w^t,e...
  • CS224W-图神经网络 笔记6.2:Message Passing and Node Classification - 三类主要的节点分类算法介绍 本文总结之日CS224W Winter 2021只更新到了第四节,所以下文会参考2021年课程的PPT并结合2019年秋季课程进行...
  • matlab代码仿真 Reduced-Complexity-Message-Passing-Detection [] 说明 关于MIMO MPD 算法的Matlab仿真代码 以及改进的算法 代码。
  • 其中共有7个类别(num_classes:基于案例、遗传算法、 神经网络、概率方法、强化学习 、规则学习、理论。整个数据集中共有2708篇论文,在词干堵塞和去除词尾后,只剩下1433个独特的单词(num_node_features),文档...
  • Message PassingIntroductionMessage Passing APIMessage Handler Functions三级目录 Introduction GNU Radio was originally a streaming system with no other mechanism to pass data between blocks. Streams of...
  • 基于PyG Message Passing 的 GCN 实现解析

    千次阅读 2022-01-19 15:10:04
    基于PyG Message Passing 的 GCN 实现解析 GCN算法 PyG 中GCN的实现 Message Passing 实现 欢迎联系我 GCN算法 GCN 算法通过图上的卷积定义,简化的GCN算法可以表示为节点与其近邻节点的消息传递、聚合,公式可以...
  • pytorch geometric:消息传递原理详解(MESSAGE PASSING)+实例pytorch geometric中的消息传递原理(MESSAGE PASSING)+实例卷积原理回顾MessagePassing基类MessagePassing初始化MessagePassing.propagate(edge_...
  • 【CVPR2018】A Bi-directional Message Passing Model for Salient Object Detection 一种用于显著性目标检测的双向消息传递模型
  • 容错分布式计算思路和算法:This book presents the most important fault-tolerant distributed programming abstractions and their associated distributed algorithms
  • cs224w(图机器学习)2021冬季课程学习笔记6 Message Passing and Node Classification 1. Message Passing and Node Classification 2. Relational Classification / Probabilistic Relational Classifier 3. ...
  • HDOJ 4661: Message Passing

    千次阅读 2013-08-16 01:23:02
    题目大意: 有n个人,每个人知道一个独特的信息。 每一次操作,我们可以让一个人把自己知道的所有信息告诉另一个人。...算法: 显然最好的方法是所有人把消息先告诉同一个人,然后再由这个人把这个消息传给所有人。
  • 【CVPR2018】A Bi-directional Message Passing Model ...
  • 接着讲了第二种算法,iterative classification。第一种方案 relational classifiers 仅仅根据标签进行迭代,完全浪费了节点的属性信息,显然如果节...
  • 《Scene Graph Generation by Iterative Message Passing》 针对问题 前人的工作大多是local prediction,未利用丰富的上下文信息,因此会造成关系类别预测出现模糊和歧义 图的表示 把node(目标)和各个node之间的...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 4,275
精华内容 1,710
关键字:

message passing算法