因此,我和我的团队创建了一个函数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)
答案 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)
这可能使您更接近所需。相反,可以使用递归函数来完成此操作,但是我通常更喜欢使用内置的高阶函数,例如fold
或fold2
来完成任务。参见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