我正在尝试将mvregress与我拥有的数据一起使用,维数为几百。 (3〜4)。使用32 GB的RAM,我无法计算beta,我得到“内存不足”的消息。我找不到mvregress的任何使用限制,阻止我将它应用于具有这种维度的矢量,我做错了吗?有没有办法通过我的数据使用多元线性回归?
这是一个出错的例子:
dim=400;
nsamp=1000;
dataVariance = .10;
noiseVariance = .05;
mixtureCenters=randn(dim,1);
X=randn(dim, nsamp)*sqrt(dataVariance ) + repmat(mixtureCenters,1,nsamp);
N=randn(dim, nsamp)*sqrt(noiseVariance ) + repmat(mixtureCenters,1,nsamp);
A=2*eye(dim);
Y=A*X+N;
%without residual term:
A_hat=mvregress(X',Y');
%wit residual term:
[B, y_hat]=mlrtrain(X,Y)
,其中
function [B, y_hat]=mlrtrain(X,Y)
[n,d] = size(Y);
Xmat = [ones(n,1) X];
Xmat_sz=size(Xmat);
Xcell = cell(1,n);
for i = 1:n
Xcell{i} = [kron([Xmat(i,:)],eye(d))];
end
[beta,sigma,E,V] = mvregress(Xcell,Y);
B = reshape(beta,d,Xmat_sz(2))';
y_hat=Xmat * B ;
end
<小时/> 错误是:
Error using bsxfun
Out of memory. Type HELP MEMORY for your options.
Error in kron (line 36)
K = reshape(bsxfun(@times,A,B),[ma*mb na*nb]);
Error in mvregress (line 319)
c{j} = kron(eye(NumSeries),Design(j,:));
这是whos命令的结果:
whos
Name Size Bytes Class Attributes
A 400x400 1280000 double
N 400x1000 3200000 double
X 400x1000 3200000 double
Y 400x1000 3200000 double
dataVariance 1x1 8 double
dim 1x1 8 double
mixtureCenters 400x1 3200 double
noiseVariance 1x1 8 double
nsamp 1x1 8 double
答案 0 :(得分:3)
好的,我想我有一个解决方案,首先是短版本:
dim=400;
nsamp=1000;
dataVariance = .10;
noiseVariance = .05;
mixtureCenters=randn(dim,1);
X=randn(dim, nsamp)*sqrt(dataVariance ) + repmat(mixtureCenters,1,nsamp);
N=randn(dim, nsamp)*sqrt(noiseVariance ) + repmat(mixtureCenters,1,nsamp);
A=2*eye(dim);
Y=A*X+N;
[n,d] = size(Y);
Xmat = [ones(n,1) X];
Xmat_sz=size(Xmat);
Xcell = cell(1,n);
for i = 1:n
Xcell{i} = kron(Xmat(i,:),speye(d));
end
[beta,sigma,E,V] = mvregress(Xcell,Y);
B = reshape(beta,d,Xmat_sz(2))';
y_hat=Xmat * B ;
奇怪的是,我无法访问函数的工作区,它没有出现在调用堆栈中。这就是为什么我把这个函数放在脚本之后。
以下解释也可能对您有所帮助:
查看kron
定义,插入m by n和ap by q矩阵的结果的大小为mxp乘以nxq,在您的情况下为400乘1001和1000乘1000,这使得400000乘1001000矩阵,其中4 * 10 ^ 11个元素。现在你有四百个,每个元素占用8个字节以获得双倍精度,总大小约为1.281PB内存(或1.138 Pebibytes,如果你愿意的话),即使你的32位Gibibyte也远远不够
看到你的一个矩阵,即眼睛一个,主要包含零,结果矩阵包含所有可能的元素产品组合,其中大多数也将为零。具体来说,对于这种情况,MATLAB提供稀疏矩阵格式,通过仅存储非零元素,可以节省大量内存,具体取决于矩阵中零元素的数量。您可以使用sparse(X)
将完整矩阵转换为稀疏表示,或者使用speye(n)
直接获得眼图矩阵,这就是我上面所做的。稀疏属性传播到结果,你现在应该有足够的内存(我有1/4的内存可用,并且它可以工作)。
然而,马克·冈恩在评论中提到的问题仍然存在。我收到一个错误说:
使用mvregress时出错(第260行) 数据不足以估计完整或最小二乘模型。
答案 1 :(得分:2)
如果每个回归方程中的回归量都相同且您对OLS估计感兴趣,则可以通过简单调用\
来替换对mvregress的调用。
在mlrtrain
的调用中,您出现了矩阵转置错误(自更正后)。在mvregress的语言中,n是观察的数量,d是结果变量的数量。您生成一个d乘以n的矩阵Y.但那么你应该调用mlrtrain(X',Y')而不是mlrtrain(X,Y)。
如果以下不是具体的,您正在寻找什么,我建议您准确定义您想要估算的内容。
如果我是你的话,我在这里说的话已经完全偏离基础,我正在发布我会写的代码。我已经减少了维度,以便在您的特殊情况下显示等同于简单地调用\
。我还以更标准的方式编写了一些东西(即观察到了行,而没有产生矩阵转置错误)。
dim=5; % These can go way higher but only if you use my code
nsamp=20; % rather than call mvregress
dataVariance = .10;
noiseVariance = .05;
mixtureCenters=randn(dim,1);
X = randn(nsamp, dim)*sqrt(dataVariance ) + repmat(mixtureCenters', nsamp, 1); %'
E = randn(nsamp, dim)*sqrt(noiseVariance); %noise should be mean zero
B = 2*eye(dim);
Y = X*B+E;
% without constant:
B_hat = mvregress(X,Y); %<-------- slow, blows up with high dimension
B_hat2 = X \ Y; %<-------- fast, fine with higher dimensions
norm(B_hat - B_hat2) % show numerical equivalent if basically 0
% with constant:
B_constant_hat = mlrtrain(X,Y) %<-------- slow, blows up with high dimension
B_constant_hat2 = [ones(nsamp, 1), X] \ Y; % <-- fast, and fine with higher dimensions
norm(B_constant_hat - B_constant_hat2) % show numerical equivalent if basically 0
我假设你有:
nsamp
个dim
大小的数据矩阵X
。nsamp
个ny
大小的结果变量矩阵Y
Y
上回归X
的每一列。也就是说,我们正在进行多元回归,但是有一个共同的数据矩阵X. 也就是说,我们正在估算:
y_{ij} = \sum_k b_k * x_{ik} + e_{ijk} for i=1...nsamp, j = 1...ny, k=1...dim
如果您尝试做的不同于此,您需要清楚说明您要做的事情!
要对Y
X
进行回归,您可以执行以下操作:
[beta_mvr, sigma_mvr, resid_mvr] = mvregress(X, Y);
这看起来非常缓慢。对于每个回归使用相同数据矩阵的情况,以下内容应与mvregress匹配。
beta_hat = X \ Y; % estimate beta using least squares
resid = Y - X * beta_hat; % calculate residual
如果你想用一个矢量构造一个新的数据矩阵,你可以这样做:
X_withones = [ones(nsamp, 1), X];
假设我们想要运行回归
y_i = \sum_j x_{ij} + e_i i=1...n, j=1...k
我们可以通过k datamatrix X和n乘1结果向量y构造数据矩阵n。 OLS估计值为bhat = pinv(X' * X) * X' * y
,也可以在MATLAB中使用bhat = X \ y
计算。
如果要多次执行此操作(即在同一数据矩阵X上运行多元回归),则可以构造结果矩阵Y,其中EACH列表示单独的结果变量。 Y = [ya,yb,yc,...]。简而言之,OLS解决方案是B = pinv(X'*X)*X'*Y
,可以计算为B = X \ Y
。 B的第一列是在X上回归Y(:,1)的结果.B的第二列是在X等上回归Y(:,2)的结果......在这些条件下,这相当于调用B = mvregress(X,Y)
如果回归量相同并且估计是通过简单的OLS进行的,则多元回归与等式普通最小二乘法之间存在等价。
d = 10;
k = 15;
n = 100;
C = RandomCorr(d + k, 1); %Use any method you like to generate a random correlation matrix
s = randn(d+k , 1) * 10;
S = (s * s') .* C; % generate covariance matrix
mu = randn(d+k,1);
data = mvnrnd(ones(n, 1) * mu', S);
Y = data(:,1:d);
X = data(:,d+1:end);
[b1, sigma] = mvregress(X, Y);
b2 = X \ Y;
norm(b1 - b2)
您会注意到b1和b2在数值上是等价的。它们是等价的,即使西格玛与零非常不同。