如何迭代列表并将函数结果传递给下一次迭代

时间:2011-07-27 15:41:39

标签: f#

我是F#的新手并且努力学习,认为实现聚类算法会很有趣。 我有一个列表的输入列表,我需要迭代。对于这些输入向量中的每一个,我需要应用更新权重的函数并返回列表列表(权重矩阵)。我可以通过newMatrix函数完成该部分。问题是,我需要在下一次迭代中使用更新的权重矩阵,而我却失去了如何做到这一点。这是重要的部分,为简洁起见,遗漏了一些功能。

let inputList = [[1; 1; 0; 0]; [0; 0; 0; 1]; [1; 0; 0; 0]; [0; 0; 1; 1;]]
let weights = [[.2; .6; .5; .9]; [.8; .4; .7; .3]]
let newMatrix xi matrix =
    List.map2( fun w wi ->
        if wi = (yiIndex xi) then (newWeights xi)
        else w) matrix [0..matrix.Length-1]
 printfn "%A" (newMatrix inputList.Head weights)
 > >
 [[0.2; 0.6; 0.5; 0.9]; [0.92; 0.76; 0.28; 0.32]]

所以我的问题是,如何使用之前的inputList结果为每个inputVector迭代newMatrix计算newMatrix

编辑:添加了伪造算法

for input vector 1
    given weight matrix calculate new weight matrix
    return weight matirx prime
for input vector 2
    given weight matrix prime calculate new weight matrix
and so on...
...

除此之外:我正在实施Kohonen SOM算法this本书。

2 个答案:

答案 0 :(得分:5)

如果你刚刚开始学习F#,那么首先尝试使用递归显式实现它可能是有用的。正如Ankur指出的那样,List.fold捕获了这个特定的递归模式,但理解List.fold实际上是如何工作的非常有用。因此,显式版本如下所示:

// Takes vectors to be processed and an initial list of weights.
// The result is an adapted list of weights.
let rec processVectors weights vectors = 
  match vectors with
  | [] -> 
      // If 'vectors' is empty list, we're done and we just return current weights
      weights
  | head::tail -> 
      // We got a vector 'head' and remaining vectors 'tail'
      // Adapt the weights using the current vector...
      let weights2 = newweights weights head
      // and then adapt weights using the remaining vectors (recursively)
      processVectors weights2 tail

这基本上是List.fold的作用,但是如果你看到这样编写的代码可能更容易理解它(List.fold函数隐藏了递归处理,所以lambda函数用作参数只是计算新权重的函数。)

除此之外,我不太了解您的newMatrix功能。你能提供更多细节吗?通常,在使用列表时,您不需要使用索引,并且您似乎正在执行需要访问特定索引处的元素的操作。可能有更好的方法来写这个....

答案 1 :(得分:3)

我猜你正在寻找List.fold。 类似的东西:

let inputList = [[1; 1; 0; 0]; [0; 0; 0; 1]; [1; 0; 0; 0]; [0; 0; 1; 1;]]
let weights = [[0.2; 0.6; 0.5; 0.9]; [0.8; 0.4; 0.7; 0.3]]
let newWeights w values = w //Fake method which returns old weight as it is
inputList |> List.fold (newWeights) weights

注意:在这种情况下,newWeights函数采用权重和输入向量并返回新权重

如果您还需要中间计算权重

,则可能是List.scan
let inputList = [[1; 1; 0; 0]; [0; 0; 0; 1]; [1; 0; 0; 0]; [0; 0; 1; 1;]]
let weights = [[0.2; 0.6; 0.5; 0.9]; [0.8; 0.4; 0.7; 0.3]]
let newWeights w values = w
inputList |> List.scan (newWeights) weights