如何创建一个可以测试另一个函数的随机单词共现的函数?

时间:2019-11-12 10:43:59

标签: f#

因此,我和我的团队创建了一个函数wordMarkovChain,该函数生成一个包含nWords个单词的随机字符串,其单词对根据并发直方图wCooc分布。 现在我们想创建一个函数来测试新创建的wordMarkovChain,因此我可以确认它是否可以正常工作。 函数diffw2将两个同现直方图作为差的平方和的平均值进行比较,需要输入wordCooccurrences类型的两个参数c1和c2并返回一个double,其中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#的广泛知识,尤其是不具备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)

2 个答案:

答案 0 :(得分:0)

我认为您正在尝试执行以下操作

let diffw2_  (c1 : wordCooccurrences) (c2 : wordCooccurrences) = 
    List.zip c1 c2
    |> List.sumBy (fun ((_, w1), (_, w2)) ->
        List.zip w1 w2
        |> List.sumBy (fun ((_,i1), (_,i2)) ->
            (float (i1 - i2)) ** 2.0
        )
    ) |> (fun totalSumOfSquares -> totalSumOfSquares / (c1 |> List.length |> float))

这仅返回c1和c2的相应元素之间的平均平方差。假定c1和c2具有相同的结构。

使用F#(通常是函数式编程),您通常避免使用可变变量和for循环,而建议使用纯函数。

答案 1 :(得分:0)

这可能使您更接近所需。相反,可以使用递归函数来完成此操作,但是我通常更喜欢使用内置的高阶函数,例如foldfold2来完成任务。参见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