微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

c# – 计算函数/蒙特卡罗方法合理性的算法

我正在编写一个试图复制本文开头讨论的算法的程序,

http://www-stat.stanford.edu/~cgates/PERSI/papers/MCMCRev.pdf

F是从char到char的函数.假设P1(f)是该函数的“合理性”度量.算法是:

从对函数的初步猜测开始,比如f,然后是新的函数f * –

>计算Pl(f).
>通过对值f进行随机转置来更改为f *,将其分配给两个符号.
>计算Pl(f *);如果这大于Pl(f),则接受f *.
>如果没有,翻转一个Pl(f)/ Pl(f *)硬币;如果它出现在头上,接受f *.
>如果硬币抛出尾巴,请留在f.

我正在使用以下代码实现此功能.我正在使用c#,但试图让每个人都更加简化.如果有更好的论坛,请告诉我.

var current_f = Initial();    // current accepted function f
 var current_Pl_f = InitialPl();  // current plausibility of accepted function f

 for (int i = 0; i < 10000; i++)
        {
            var candidate_f = Transpose(current_f); // create a candidate function

            var candidate_Pl_f = ComputePl(candidate_f);  // compute its plausibility

            if (candidate_Pl_f > current_Pl_f)            // candidate Pl has improved
            {
                current_f = candidate_f;            // accept the candidate
                current_Pl_f = candidate_Pl_f; 
            }
            else                                    // otherwise flip a coin
            {
                int flip = Flip(); 

                if (flip == 1)                      // heads
                {
                    current_f = candidate_f;        // accept it anyway
                    current_Pl_f = candidate_Pl_f; 
                }
                else if (flip == 0)                 // tails
                {
                    // what to do here ?
                }
            }
        }

我的问题基本上是否看起来像是实现该算法的最佳方法.尽管实施了这种方法,我似乎可能会陷入一些局部最大值/局部最小值.

编辑 – 这是Transpose()方法背后的本质问题.我使用类型<<的字典/哈希表char,char>>候选函数用于查看任何给定的char – > char变换.因此,转置方法只是在字典中交换两个指示函数行为的值.

private Dictionary<char,char> Transpose(Dictionary<char,char> map,params int[] indices)
    {
        foreach (var index in indices)
        {
            char target_val = map.ElementAt(index).Value;   // get the value at the index

            char target_key = map.ElementAt(index).Key;     // get the key at the index

            int _rand = _random.Next(map.Count);   // get a random key (char) to swap with

            char rand_key = map.ElementAt(_rand).Key;

            char source_val = map[rand_key]; // the value that currently is used by the source of the swap

            map[target_key] = source_val; // make the swap

            map[rand_key] = target_val;
        }

        return map; 
    }

请记住,使用基础字典的候选函数基本上只是:

public char GetChar(char in,Dictionary<char,char> theMap)
{
     return theMap[char]; 
}

这是计算Pl(f)的函数

public decimal ComputePl(Func<char,char> candidate,string encrypted,decimal[][] _matrix)
    {
        decimal product = default(decimal);

        for (int i = 0; i < encrypted.Length; i++)
        {
            int j = i + 1;

            if (j >= encrypted.Length)
            {
                break;
            }

            char a = candidate(encrypted[i]);
            char b = candidate(encrypted[j]);

            int _a = GetIndex(_alphabet,a); // _alphabet is just a string/char[] of all avl chars 
            int _b = GetIndex(_alphabet,b);

            decimal _freq = _matrix[_a][_b]; 

            if (product == default(decimal))
            {
                product = _freq;
            }
            else
            {
                product = product * _freq;
            }
        }

        return product;
    }

解决方法

暂时,codereview.stackexchange.com可能是“更好的论坛”.
从来没有,我会快速刺伤它:

>一目了然,显示代码段是算法的正确实现.
>算法是否会在局部最小值中“卡住”是一个与算法无关的问题. (见下面的讨论)
>您对“最佳方法”的追求似乎是针对算法中的调整(偏离原始算法)而不是实施中的调整(使其更快和/或消除一些可能的缺陷).有关算法的注意事项,请参阅下面的讨论;关于实施的讨论考虑以下内容

>确保Flip()方法公平
>确保ComputePl()是正确的:由于值函数中的算术精度问题,通常会出现一些错误.
>使用Transpose()方法确保公平性(等概率).
>性能改进可能来自ComputePl()方法(未显示)中的优化,而不是主循环中的优化.

关于算法本身及其对不同问题的适用性的讨论.
简而言之,该算法是一种引导随机搜索,其中[巨大的]解空间采用两个随机设备进行采样:Transpose()方法(每次非常轻微地修改当前候选函数)和Flip()方法决定是否[局部]次优解决方案应该存活下来.搜索由目标函数ComputePl()引导,ComputePl()本身基于某些参考语料库中的一阶转换矩阵.
在这种情况下,可以通过增加选择“次优”功能的概率来避免局部最小“焦油坑”:而不是公平的50-50翻转(),可能尝试保留66%的“次优”解决方案或甚至75%.这种方法通常会延长收敛到最佳解决方案所需的代数,但是,正如所述,可以避免陷入局部最小值.

确保算法适用性的另一种方法是确保更好地评估给定函数的合理性.对算法的相对成功和一般性的可能解释是

>英语中一阶转换的分布不是很均匀(因此模型很好地模拟了给定函数的合理性,通过奖励它的匹配并惩罚它的不匹配).与给定语言/语料库中的字符的“0阶”分布相比,这种多维统计更偏离参考语料库.
>特定于语言的一阶转换的分布在不同语言和/或行话词汇[基于所述语言]的背景下通常是相似的.在短手的情况下,事情确实会崩溃,因此通常会省略诸如誓言之类的字母.

因此,为了提高算法对给定问题的适用性,请确保使用的分布矩阵尽可能地匹配基础文本的语言和域.

原文地址:https://www.jb51.cc/csharp/101161.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐