我有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会耗尽内存。请提供一些帮助或建议。谢谢。
答案 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默认不支持此功能。您并不总是想要对列表的第一级进行平均。