在张量内推导出值的均值

时间:2011-12-06 00:04:19

标签: wolfram-mathematica

我有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,派生值可能不是我需要的。另外,如果我试图做Mean [tensor],Mathematica会耗尽内存。请提供一些帮助或建议。谢谢。

6 个答案:

答案 0 :(得分:5)

如有疑问,请删除尺寸。 (您仍然可以将它们区分开来,以便轻松查看最终结果。)

(* 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}

答案 1 :(得分:3)

  

如果我试图做[张量]

,Mathematica会耗尽内存

这可能是因为中间结果大于最终结果。如果元素不是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 :(得分:2)

为了详细说明其他答案,没有理由期望Mathematica函数在张量上的运算方式与矩阵不同,因为Mathemetica认为它们都是嵌套List s,只是嵌套深度不同。函数与列表的行为方式取决于它们是Listable,您可以使用Attributes[f]进行检查,其中f是您感兴趣的函数。

您的数据列表的维度在事物计划中实际上并不是那么大。没有看到你的实际数据很难确定,但我怀疑你的内存不足的原因是你的一些数据是非数字的。

答案 3 :(得分:1)

我不知道你做错了什么(你的代码会有所帮助)。但是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默认使用均匀分布的平均值的预期值。

答案 4 :(得分:1)

假设您有以下数据:

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

答案 5 :(得分:0)

要扩展Brett的答案,当你在n维张量上调用Mean时,它会在第一个索引上平均并返回一个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个参数求平均值,您必须首先转置数据。例如,假设您想平均5维中的第3维。首先需要第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默认不支持此功能。您并不总是想要对列表的第一级进行平均。