首页 > 解决方案 > 如何创建一个可以测试另一个函数的随机单词共现的函数?

问题描述

所以我和我的团队创建了一个函数 wordMarkovChain,它生成一个包含 nWords 个单词的随机字符串,其单词对根据共现直方图 wCooc 分布。现在我们想创建一个函数来测试新创建的 wordMarkovChain,所以我可以确认它正在正常工作。函数 diffw2 将两个同现直方图作为平均平方差的和进行比较,需要接受两个 wordCooccurrences 类型的参数 c1 和 c2 并返回一个双精度值,其中 c1 和 c2 是 M 个元素的两个同现直方图,使得c1(i, j) 是在单词 j 之后找到单词 i 的次数。

函数背后的数学应该如下所示: 1/M^2 * 从 i=0 到 M-1 的总和 从 i=0 到 M-1 的总和 (c1(i, j) - c2(i, j))^ 2.

抱歉,我无法发布图片:( 我们创建的两种类型似乎是问题所在。c1 和 c2 可以有不同的长度,但是 wordCoocurence 类型中的 wordHistogram 类型也可以有不同的长度。
问题是, 我们如何创建这样的函数?我们尝试了 for 循环,但我们认为它需要是一个递归函数。我们对整个编程概念还很陌生,正在寻找一些指导。请记住,我们这样做没有丰富的 F# 知识,尤其是它们的构建功能。

代码

// Types  
type wordHistogram = (string * int) list
type wordCooccurrences = (string * wordHistogram) list

let diffw2 (c1 : wordCooccurrences) (c2 : wordCooccurrences) : double = 
  let mutable res = 0 
  let z1, z2 = c1 |> List.unzip
  let z3, z4 = c2 |> List.unzip 
  let m1 = c1 |> List.length
  let m2 = c2 |> List.length
  let m = m1 + m2

  for i in 0 .. (m - 1) do
    for j in 0 .. (m - 1) do
      for k in 0 .. ((z2.[j] |> List.length) - 1) do
        res <- res + (snd z2.[j].[k] - snd z4.[j].[k]) * (snd z2.[j].[k] - snd z4.[j].[k])
  (1.0 / (float(m * m))) * float(res)

标签: f#

解决方案


这可能会让你更接近你需要的东西。这可以使用递归函数来完成,但我通常更喜欢使用内置的高阶函数,比如foldor fold2when they can do the job。请参阅https://msdn.microsoft.com/en-us/visualfsharpdocs/conceptual/list.fold2%5B 't1%2C't2%2C'state%5D-function-%5Bfsharp%5D

每次调用List.fold2都会收到一个初始值(或“状态”)为 0.0 的“累加器”。这个累加器在名为“acc”的参数中传递给 lambda 函数。当 lambda 应用于两个输入列表的每个元素时,它将中间结果添加到该acc值,然后作为List.fold2调用的结果返回。

type wordHistogram = (string * int) list
type wordCooccurrences = (string * wordHistogram) list

let diffw2 (c1 : wordCooccurrences) (c2 : wordCooccurrences) = 
  let m1 = c1 |> List.length
  let m2 = c2 |> List.length
  let m = m1 + m2

  let res =
      (0.0, c1, c2) |||>
      List.fold2 (fun acc (_str1, hist1) (_str2, hist2) ->
        let intermedRes =
            (0.0, hist1, hist2) |||>
            List.fold2 (fun acc (_str1, freq1) (_str2, freq2) ->
                let diff = float (freq1 - freq2)
                acc + diff * diff
            )
        acc + intermedRes
      )

  (1.0 / float(m * m)) * res

推荐阅读