Получение среднего значения в тензоре - PullRequest
3 голосов
/ 06 декабря 2011

У меня есть тензор 20000 x 185 x 5, который выглядит как

{{{a1_1,a2_1,a3_1,a4_1,a5_1},{b1_1,b2_1,b3_1,b4_1,b5_1}... 
(continue for 185 times)}
 {{a1_2,a2_2,a3_2,a4_2,a5_2},{b1_2,b2_2,b3_2,b4_2,b5_2}...

 ...    
 ... 
 ...

{{a1_20000,a2_20000,a3_20000,a4_20000,a5_20000},
{b1_20000,b2_20000,b3_20000,b4_20000,b5_20000}... }}

20000 представляет номер итерации, 185 представляет индивидуумов, и у каждого индивидуума есть 5 атрибутов. Мне нужно построить матрицу 185 x 5, которая хранит среднее значение для 5 атрибутов каждого человека, усредненное по 20000 итерациям.

Не уверен, что лучший способ сделать это. Я знаю, Mean[ ] работает с матрицами, но с Tensor производные значения могут быть не тем, что мне нужно. Кроме того, Mathematica не хватило памяти, если я попытался сделать Mean [тензор]. Пожалуйста, предоставьте некоторую помощь или совет. Спасибо.

Ответы [ 6 ]

5 голосов
/ 06 декабря 2011

Если сомневаетесь, уменьшите размер. (Вы по-прежнему можете различать их, чтобы легко видеть, где все заканчивается.)

(* In[1]:= *) data = Array[a, {4, 3, 2}]

(* Out[1]= *) {{{a[1, 1, 1], a[1, 1, 2]}, {a[1, 2, 1], 
   a[1, 2, 2]}, {a[1, 3, 1], a[1, 3, 2]}}, {{a[2, 1, 1], 
   a[2, 1, 2]}, {a[2, 2, 1], a[2, 2, 2]}, {a[2, 3, 1], 
   a[2, 3, 2]}}, {{a[3, 1, 1], a[3, 1, 2]}, {a[3, 2, 1], 
   a[3, 2, 2]}, {a[3, 3, 1], a[3, 3, 2]}}, {{a[4, 1, 1], 
   a[4, 1, 2]}, {a[4, 2, 1], a[4, 2, 2]}, {a[4, 3, 1], a[4, 3, 2]}}}

(* In[2]:= *) Dimensions[data]

(* Out[2]= *) {4, 3, 2}

(* In[3]:= *) means = Mean[data]

(* Out[3]= *) {
  {1/4 (a[1, 1, 1] + a[2, 1, 1] + a[3, 1, 1] + a[4, 1, 1]), 
   1/4 (a[1, 1, 2] + a[2, 1, 2] + a[3, 1, 2] + a[4, 1, 2])}, 
  {1/4 (a[1, 2, 1] + a[2, 2, 1] + a[3, 2, 1] + a[4, 2, 1]), 
   1/4 (a[1, 2, 2] + a[2, 2, 2] + a[3, 2, 2] + a[4, 2, 2])}, 
  {1/4 (a[1, 3, 1] + a[2, 3, 1] + a[3, 3, 1] + a[4, 3, 1]), 
   1/4 (a[1, 3, 2] + a[2, 3, 2] + a[3, 3, 2] + a[4, 3, 2])}
  }

(* In[4]:= *) Dimensions[means]

(* Out[4]= *) {3, 2}
3 голосов
/ 06 декабря 2011

Mathematica исчерпал память, если я попытался сделать Mean [тензор]

Это, вероятно, потому что промежуточные результаты больше, чем конечный результат. Это вероятно, если элементы не имеют тип Real или Integer. Пример:

a = Tuples[{x, Sqrt[y], z^x, q/2, Mod[r, 1], Sin[s]}, {2, 4}];
{MemoryInUse[], MaxMemoryUsed[]}
b = Mean[a];
{MemoryInUse[], MaxMemoryUsed[]}
{109125576, 124244808}
{269465456, 376960648}

Если они есть и находятся в форме упакованного массива, возможно, элементы таковы, что массив распаковывается во время обработки.

Вот пример, где тензор является упакованным массивом небольших чисел, и распаковка не происходит.

a = RandomReal[99, {20000, 185, 5}];
PackedArrayQ[a]
{MemoryInUse[], MaxMemoryUsed[]}
b = Mean[a];
{MemoryInUse[], MaxMemoryUsed[]}
True
{163012808, 163016952}
{163018944, 163026688}

Здесь тензор того же размера с очень большими числами.

a = RandomReal[$MaxMachineNumber, {20000, 185, 5}];
Developer`PackedArrayQ[a]
{MemoryInUse[], MaxMemoryUsed[]}
b = Mean[a];
{MemoryInUse[], MaxMemoryUsed[]}
True
{163010680, 458982088}
{163122608, 786958080}
2 голосов
/ 06 декабря 2011

Чтобы немного подробнее остановиться на других ответах, нет оснований ожидать, что функции Mathematica будут работать по-разному на тензорах по сравнению с матрицами, потому что Mathemetica считает, что они оба вложены List s, которые имеют разную глубину вложенности. Как функции работают со списками, зависит от того, являются ли они Listable, что можно проверить с помощью Attributes[f], где f - интересующая вас функция.

Размерность вашего списка данных на самом деле не так уж велика. Не видя ваших реальных данных, трудно быть уверенным, но я подозреваю, что причина того, что вам не хватает памяти, заключается в том, что некоторые из ваших данных не являются числовыми.

1 голос
/ 06 декабря 2011

Предположим, у вас есть следующие данные:

a = Table[RandomInteger[100], {i, 20000}, {j, 185}, {k, 5}];

Прямым способом Вы можете найти таблицу, в которой хранятся средства a[[1,j,k]],a[[2,j,k]],...a[[20000,j,k]]:

c = Table[Sum[a[[i, j, k]], {i, Length[a]}], {j, 185}, {k, 5}]/
 Length[a] // N; // Timing
{37.487, Null}

или просто:

d = Total[a]/Length[a] // N; // Timing
{0.702, Null}

Второй способ примерно в 50 раз быстрее.

c == d
True
1 голос
/ 06 декабря 2011

Я не знаю, что вы делаете неправильно (ваш код поможет). Но Mean[] уже работает так, как вы хотите.

a = RandomReal[1, {20000, 185, 5}];
b = Mean@a;

Dimensions@b
Out[1]= {185, 5}

Вы даже можете проверить, что это правильно:

{Max@b, Min@b}
Out[2]={0.506445, 0.494061}

, которое является ожидаемым значением среднего значения, учитывая, что RandomReal использует равномерное распределение по умолчанию.

0 голосов
/ 08 декабря 2011

Чтобы немного расширить ответ Бретта, когда вы вызываете Mean для n-мерного тензора, он усредняется по первому индексу и возвращает n-1-мерный тензор:

a = RandomReal[1, {a1, a2, a3, ... an}];
Dimensions[a] (* This would have n entries in it *)
b = Mean[a];
Dimensions[b] (* Has n-1 entries, where averaging was done over the first index *)

В более общем случае, когда вам может потребоваться усреднить значение по i-му аргументу, вам придется сначала перенести данные вокруг. Например, скажем, вы хотите усреднить 3-е из 5 измерений. Сначала вам понадобится 3-й элемент, затем 1-й, 2-й, 4-й, 5-й.

a = RandomReal[1, {5, 10, 2, 40, 10}];
b = Transpose[a, {2, 3, 4, 1, 5}];
c = Mean[b]; (* Now of dimensions {5, 10, 40, 10} *)

Другими словами, вы должны были бы вызвать Transpose, где вы поместили i-й индекс в качестве первого тензорного индекса и переместили все перед ним на единицу. Все, что идет после i-го индекса, остается прежним.

Это может пригодиться, когда ваши данные поступают в нечетных форматах, где первый индекс не всегда представляет различные реализации выборки данных. Например, когда мне приходилось делать усреднение по времени для больших наборов данных о ветре, где временной ряд занял третье (!) Место по доступному тензорному представлению.

Вы можете себе представить, что generalizedTenorMean будет выглядеть примерно так:

Clear[generalizedTensorMean];
generalizedTensorMean[A_, i_] := 
 Module[{n = Length@Dimensions@A, ordering},
  ordering = 
   Join[Table[x, {x, 2, i}], {1}, Table[x, {x, i + 1, n}]];
  Mean@Transpose[A, ordering]]

Это сводится к простому среднему значению, когда i == 1. Попробуйте:

A = RandomReal[1, {2, 4, 6, 8, 10, 12, 14}];
Dimensions@A   (* {2, 4, 6, 8, 10, 12, 14} *)
Dimensions@generalizedTensorMean[A, 1]  (* {4, 6, 8, 10, 12, 14} *)
Dimensions@generalizedTensorMean[A, 7]  (* {2, 4, 6, 8, 10, 12} *)

Кстати, я удивлен, что Mathematica не поддерживает это по умолчанию. Вы не всегда хотите усреднить по первому уровню списка.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...