PDL парное сравнение строк - PullRequest
0 голосов
/ 21 декабря 2011

Я создал матрицу PDL. Мне нужно сделать попарное сравнение между каждой строкой. В настоящее время я использую команды 'where' и 'cov', чтобы вернуть попарное сравнение для двух срезов (созданных в цикле perl).

Мой вопрос: как я могу использовать «диапазон» и «срез» для циклического перебора строк? Как я могу вернуть свою позицию индекса? Я перебрал матрицу, используя perl. Я читал, что зацикливание на perl действительно наносит вред мощности PDL.

Желаемый вывод:

indexA indexB Value
pos1   pos5   1
pos1   pos6   5
pos1   pos0   7 

Чтобы было ясно, я хочу использовать только функциональность PDL.

Вот некоторый псевдокод, который (надеюсь) лучше проиллюстрирует мою точку зрения.

p $b

[
 [1 0 3 0]
 [0 1 0 1]
 [1 3 1 3]   <- example piddle y
 [0 1 0 1]   <- example piddle z
]

my concept function{


slice $b (grab row z) - works fine
slice $b (grab row y) - works fine


($a, $b) = where($a,$b, $a < 3 && $b < 3 ) - works fine

p $a [1 1] 
p $b [0  0] 

cov($a $b) - works just fine.

}

Мне просто нужен способ выполнить попарно во всех строках. Мне нужно будет сделать факторные сравнения (n строк).

Ответы [ 2 ]

1 голос
/ 21 апреля 2012

PDL Threading - это концепция, которую вы ищете здесь. Общий метод зацикливания вдоль измерений состоит в добавлении фиктивных измерений в соответствующих местах, чтобы при вычислении генерировались неявные необходимые петли потоков. Для многомерной задачи может быть несколько разных способов добавить dim и, следовательно, создать петли потока.

Для расчета парных строк вы можете выбрать два вложенных цикла по индексам срезов, которые имеют циклы perl по двум индексам и будут генерировать потоки PDL вдоль строк. Вы можете использовать только один цикл perl над индексами, но воспользоваться неявным зацикливанием потоков для вычисления всех строк одновременно.

Полностью вычисление PDL-threadloop должно было бы добавить фиктивное измерение для цикла по строкам для каждого из аргументов, чтобы можно было рассчитать все N ** 2 вычисления строки одновременно. Вот пример массива shape [4,3] с вычислением, являющимся оператором ==:

pdl> $b = floor(random(4,3)*5)

pdl> p $b

[
 [0 4 3 3]
 [3 3 4 2]
 [4 0 1 4]
]

pdl> p $b(,*3)==$b(,,*3)

[
 [
  [1 1 1 1]
  [0 0 0 0]
  [0 0 0 0]
 ]
 [
  [0 0 0 0]
  [1 1 1 1]
  [0 0 0 0]
 ]
 [
  [0 0 0 0]
  [0 0 0 0]
  [1 1 1 1]
 ]
]

Результатом является форма [4,3,3] piddle с 0-м измерением, соответствующим строкам, полученным в результате парного вычисления, а 1-е и 2-е значения соответствуют индексам строк, участвующим в операции ==.

Если вам нужно значение индекса из или для одного из этих вычислений петли потока, используйте xvals , yvals , zvals или axisvals для генерации piddle со значениями индекса, соответствующими оси этого массива.

pdl> p $b->xvals

[
 [0 1 2 3]
 [0 1 2 3]
 [0 1 2 3]
]


pdl> p $b->yvals

[
 [0 0 0 0]
 [1 1 1 1]
 [2 2 2 2]
]

Существует множество деталей, касающихся реализации потоков PDL (не совпадающих с потоками perl или posix). Я рекомендую список рассылки perldl для ознакомления и обсуждения с другими пользователями и разработчиками PDL. Также см. Первый черновой вариант Книги PDL , в котором более подробно описываются вычисления и многопоточность PDL.

0 голосов
/ 02 марта 2012

Я думаю, что вы ищете способ найти все разные пары строк в массиве и затем обработать каждую пару, используя cov? Если это правильно, то я не слышал о cov, и быстрый поиск в документации не помогает. Однако я могу сказать несколько вещей, которые могут помочь.

Я думаю, что вы слишком осторожно относитесь к добавлению PDL в код Perl, что будет хорошо, если все, что вы делаете, это зацикливание на индексах всех пар строк и вытягивание этих строк с помощью slice. Это показано в следующем примере кода.

Также вы не можете назвать where подобным образом, поскольку $a < 3 и т. Д. Сами по себе являются пиддлами, и логический оператор не будет делать с ними то, что вы хотите. Вместо этого используйте оператор & и добавьте несколько скобок, чтобы выражение выполнялось в правильном порядке.

Кроме того, я не смогу помочь, если вы не исправите мое понимание вашего вопроса или не направите меня к какой-либо документации подпрограммы cov.

use strict;
use warnings;

use PDL;

my $dat = pdl <<END;
[
 [1 0 3 0]
 [0 1 0 1]
 [1 3 1 3]
 [0 1 0 1]
]
END

my $max2 = $dat->dim(1) - 1;

for my $i (0 .. $max2 - 1) {
  for my $j ($i + 1 .. $max2) {

    my $row1 = $dat->slice(",($i)");
    my $row2 = $dat->slice(",($j)");

    ($row1, $row2) = where($row1, $row2, ($row1 < 3) & ($row2 < 3));

    cov($row1, $row2);
  }
}
...