Как перебрать список и передать результат функции на следующую итерацию - PullRequest
0 голосов
/ 27 июля 2011

Я новичок в 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, вычисляя newMatrix для каждого 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...
...

В сторону: я реализую алгоритм Кохонена СОМ из этой книги.

Ответы [ 2 ]

5 голосов
/ 27 июля 2011

Если вы только начали изучать F #, то может быть полезно попытаться реализовать это явно, используя сначала рекурсию.Как указывает Анкур, этот конкретный рекурсивный паттерн фиксируется 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скрывает рекурсивную обработку, поэтому лямбда-функция, используемая в качестве аргумента, является просто функцией, которая вычисляет новые веса).

Кроме того, я не совсем понимаю вашу newMatrix функцию.Можете ли вы дать более подробную информацию об этом?Как правило, при работе со списками вам не нужно использовать индексацию, и кажется, что вы делаете что-то, что требует доступа к элементам по определенному индексу.Там может быть лучший способ написать это ....

3 голосов
/ 27 июля 2011

Я думаю, вы ищете 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...