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

2024-04-17

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

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

F 是一个从 char 到 char 的函数。假设 Pl(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 ?
                }
            }
        }

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

EDIT- 这是 Transpose() 方法背后的本质。我使用 > 类型的字典/哈希表,候选函数使用它来查找任何给定的 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 https://codereview.stackexchange.com/可能是一个“更好的论坛".
不管怎样,我会快速尝试一下:

  • 乍一看,显示的片段是correct算法的实现。
  • 算法是否会“陷入”局部极小值是一个与算法不至执行。 (见下面的讨论)
  • Your quest for an "optimal approach" seems to be directed at tweaks in the algorithm (deviation from the original algorithm) rather than at tweaks in the implementation (to make it faster and/or to eradicate some possible flaws). For considerations regarding the algorithm, see discussion below; for discussion regarding the implementation consider the following:
    • 确保 Flip() 方法是公平的
    • 确保 ComputePl() 正确:由于值函数中的算术精度问题,经常会出现一些错误。
    • 使用 Transpose() 方法确保公平性(等概率)。
    • 性能改进可能来自 ComputePl() 方法(未显示)中的优化,而不是主循环中的优化。

关于算法的讨论per-se及其对不同问题的适用性。
简而言之,该算法是一种引导随机搜索,其中使用两个随机设备对[巨大]解空间进行采样:Transpose() 方法(每次非常轻微地修改)当前候选函数和 Flip() 方法决定[局部]次优解决方案是否应该生存。搜索由目标函数 ComputePl() 引导,该函数本身基于某个参考语料库中的一阶转换矩阵。

在这种情况下,可以通过增加选择“次优”函数的概率来避免局部最小值“焦油坑”:而不是公平的 50-50 Flip(),可以尝试保留 66% 的“次优”解决方案的概率或甚至75%。这种方法通常会延长收敛到最佳解决方案所需的代数,但是,如上所述,可以避免陷入局部最小值。

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

  • 英语中一阶转换的分布不是很均匀(因此通过奖励匹配的函数和惩罚不匹配的函数,可以很好地模拟给定函数的合理性)。这种多维统计数据比给定语言/语料库中字符的“0 阶”分布更能适应偏离参考语料库的情况。
  • 一阶转换的分布虽然是特定于语言的,但在不同语言和/或行话词汇的上下文中通常是相似的[基于所述语言]。在速记行话的情况下,事情确实会崩溃,因为元音等字母通常会被省略。

因此,为了提高算法对给定问题的适用性,请确保所使用的分布矩阵与底层文本的语言和领域尽可能匹配。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

计算函数合理性的算法/蒙特卡罗方法 的相关文章

  • switch 语句里面有 switch 语句?

    我必须评估很多条件 就我而言 我必须做这样的事情 switch id case 5 switch some other cases here case 6 set some value 在情况 5 中再进行一次切换是个好习惯吗 如果不是 那
  • 在C#中创建对象而不使用new关键字? [关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 有没有一种方法可以在 C 中不使用
  • Windows Phone 8.1 XAML 应用程序显示奇怪的版本

    我已经为我现有的应用程序之一创建了 Windows Phone 8 1 XAML 版本 我将包版本设置为1 5 0 0 创建的文件名为SlovakApps WindowsPhone 1 5 0 1 AnyCPU bundle appxupl
  • ASP.NET MVC:DropDownListFor 未选择任何选项

    我用它来填充 ASP NET MVC 视图中的下拉列表 调试这个我可以看到Selected属性设置为true当它应该是的时候 但是当渲染视图时 列表中的任何选项都不
  • 使用 Rijndael 加密/解密文件

    我需要传输 xml 文件 并且需要对它们进行加密 我发现一些例子认为我已经接近了 但是当我解密文件时 我最终得到了尾随垃圾字符 有一些关于此的帖子 但我还没有看到任何能真正有帮助的帖子 这是加密和解密代码 private void Encr
  • linq按顺序插入元素的方法

    我有一个按元素的 Name 属性排序的元素集合 我需要在保持顺序的同时将新元素插入集合中 我正在寻找一种简洁的 LINQ 方法来做到这一点 我的代码如下 this Children 是集合 d 是我需要插入的新元素 需要两次遍历集合才能找到
  • Qt5 CMake 将所有库包含到可执行文件中

    我正在尝试使用 Qt 5 14 构建一个发布模式下的应用程序 并且 Qt Creator 内部一切正常 但是当我尝试单独运行可执行文件时 我收到如下错误 OS Windows 10 Qt 5 14 Cmake 3 5 我尝试过的 设置 CM
  • 使用 Angular 上传文件时 HttpPostedFileBase 为 null

    我将 Angular 与 MVC 结合使用 当我想上传文件时 HttpPostedFileBase一片空白 html
  • 在 C++ 中将 unix 时间戳转换为星期几?

    如何根据任意 Unix 时间戳 秒 确定加利福尼亚州的星期几 太平洋时间 我四处搜寻 但没有找到 C 的内置库 UTC 通常比 PT 早 8 小时 但只需从 Unix 时间戳中减去 8 小时并创建一个tmstruct 不起作用 因为这会折扣
  • 如何在WPF中使用Application.Exit事件?

    我需要删除一些特定文件 然后用户关闭 WPF 中的程序 所以我从这里尝试了 MDSN 代码http msdn microsoft com en us library system windows application exit aspx
  • csharp类可以像java类一样“继承”xml文档吗?

    我正在向一些csharp代码添加注释 并且我正在使用 net 或其他东西 提供的xml语言 我有一个接口和一些实现类 我在界面中有一个方法 它有一个注释 在实现类中没有对实现方法进行注释 当人们在java中这样做时 javadoc在生成文档
  • 从 Dotnet Google API 获取用户电子邮件信息

    我正在为 gData 和 Drive C API 开发两个独立的 Oauth2 实现 分别将令牌信息存储在 OAuth2Parameters 和 AuthorizationState 中 我可以刷新令牌并将其用于必要的 API 调用 我正在
  • 使用 Regex/C# 将 转换为

    奇怪的问题 但我不会浪费时间解释为什么我需要这样做 只是我需要这样做 我有以下内容
  • 理解 htonl() 和 ntohl()

    我正在尝试使用 unix 套接字来测试向本地主机发送一些 udp 数据包 据我了解 当设置 ip 地址和端口以发送数据包时 我会填写我的sockaddr in将值转换为网络字节顺序 我在 OSX 上 我很惊讶这个 printf ntohl
  • 起订量中的匹配设置问题

    我过去一周左右一直在使用 Moq 直到今天才遇到任何问题 我在获取时遇到问题VerifyAll 以正确匹配我的模拟的设置 我目前正在为我的应用程序的 API 编写单元测试 该应用程序的结构如下 API lt gt Service lt gt
  • 画笔到画笔动画

    我设法找到了如何制作 WPF 动画 两种颜色之间的过渡 它被称为 ColorAnimation 并且效果很好 ColorAnimation animation new ColorAnimation From Colors DarkGreen
  • 错误 C2601:“main”:本地函数定义非法 - MS VS 2013 编译器

    我正在用 C 编写一个小程序 当我尝试使用 MS VS 2013 编译器编译它时 出现错误 C2601 main 本地函数定义非法 这是什么意思 我的代码是 include
  • VSTS 构建失败并显示 MSB4184 路径不是合法形式

    我正在尝试使用 VSTS 中的构建系统来构建和部署 c net Web 应用程序 我创建了一个新的单项目解决方案 因为似乎没有任何方法可以指定在多项目解决方案中构建 部署哪个项目 并设置我的构建定义以指向这个新解决方案 我已将其设置为使用
  • GetWindowLong(int hWnd, GWL_STYLE) 在 C# 中返回奇怪的数字

    我使用 GetWindowLong 窗口 api 来获取 C 中窗口的当前窗口状态 DllImport user32 dll static extern int GetWindowLong IntPtr hWnd int nIndex Pr
  • 将 VBA 转换为 .NET 语言 [重复]

    这个问题在这里已经有答案了 可能的重复 是否可以将 VBA 转换为 C https stackoverflow com questions 388819 is it possible to convert vba to c 假设我有一个大型

随机推荐