matlab

时间:2016-01-23 14:17:11

标签: matlab linear-regression multivariate-testing

我正在尝试将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   

2 个答案:

答案 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

解释

我假设你有:

  • nsampdim大小的数据矩阵X
  • nsampny大小的结果变量矩阵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在数值上是等价的。它们是等价的,即使西格玛与零非常不同。