【问题标题】:How do I iterate over a list and pass the funciton result to the next iteration如何迭代列表并将函数结果传递给下一次迭代
【发布时间】:2011-07-27 15:41:38
【问题描述】:

我是 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]]

所以我的问题是,如何使用之前的 newMatrix 结果迭代 inputList 为每个 inputVector 计算 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 书。

【问题讨论】:

  • @Ankur & @Tomas 我的问题中有一个错字,让你们望而却步。我在描述中引用了newWeights,我应该引用newMatrix。道歉。

标签: f#


【解决方案1】:

如果您刚开始学习 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 功能。你能提供更多细节吗?通常,在使用列表时,您不需要使用索引,而且您似乎正在做一些需要访问特定索引处的元素的事情。可能有更好的写法....

【讨论】:

  • newMatrix 函数是 Kohonen 算法的核心,它本质上是基于欧几里得距离最小的权重计算一个新的权重矩阵。最小的向量替换了权重矩阵中的原始向量,因此进行了索引。我确信有更好的方法,但正如我所说,我仍然是菜鸟:D
  • 这帮助我理解了如何将算法置于递归上下文中。谢谢。
【解决方案2】:

我猜你正在寻找 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

【讨论】:

  • 原谅我,我想弄清楚如何让我的问题更清楚,但这很复杂。我确实需要中间计算的权重。然后这些中间权重需要作为下一次迭代的输入。
  • @Nathan,这就是 Fold 函数的用途,即为列表中的每个项目(在您的情况下为列表中的每个向量)计算权重,然后使用此计算的权重计算下一个向量的权重在列表中等等..最后你将有一个最终的单一重量
猜你喜欢
  • 2021-11-08
  • 2015-04-15
  • 1970-01-01
  • 2021-12-16
  • 1970-01-01
  • 2021-07-08
  • 1970-01-01
  • 1970-01-01
  • 2013-06-03
相关资源
最近更新 更多