具有自定义负对数似然函数的 mle 内存错误
mle memory error with custom negative log-likelihood function
我正在尝试将 'mle' 与自定义负对数似然函数一起使用,但出现以下错误:
Requested 1200000x1200000 (10728.8GB) array exceeds maximum array size preference (15.6GB). This might cause MATLAB to become unresponsive.
我使用的数据是一个 1x1200000 二进制数组(我必须将其转换为双精度数组),该函数有 10 个参数:一个用于数据,3 个已知参数,6 个待优化。我尝试将 'OptimFun' 设置为 'fminsearch' 和 'fmincon'。此外,使用 'fminsearch' 和 'fminunc' 而不是 'mle' 优化参数效果很好。
问题发生在 'checkFunErrs' 函数中,在 'mlecustom.m' 文件中(在第 173 行调用,在第 705 行实际出错)。
使用 'fminunc' 我可以计算出最佳参数,但它没有给我置信区间。有没有办法规避这个?还是我做错了什么?
感谢您的帮助。
T_1 = 50000;
T_2 = 100000;
npast = 10000;
start = [0 0 0 0 0 0];
func = @(x, data, cens, freq)loglike(data, [x(1) x(2) x(3) x(4) x(5) x(6)],...
T_1, T_2, npast);
params = mle(data, 'nloglf', func, 'Start', start, 'OptimFun', 'fmincon');
% Computes the negative log likehood
function out = loglike(data, params, T_1, T_2, npast)
size = length(data);
if npast == 0
past = 0;
else
past = zeros(1, size);
past(npast+1:end) = movmean(data(npast:end-1),[npast-1, 0]); % Average number of events in the previous n years
end
lambda = params(1) + ...
(params(2)*cos(2*pi*(1:size)/T_1)) + ...
(params(3)*sin(2*pi*(1:size)/T_1)) + ...
(params(4)*cos(2*pi*(1:size)/T_2)) + ...
(params(5)*sin(2*pi*(1:size)/T_2)) + ...
params(6)*past;
out = sum(log(1+exp(lambda))-data.*lambda);
end
您的问题是内置 mle
函数的第 228 行(从 MATLAB R2017b 开始),它发生在调用自定义函数之前:
data = data(:);
输入变量data
在没有警告的情况下转换为列数组。这通常是为了确保所有进一步的计算对输入向量的方向都是稳健的。
但是,这会给您带来问题,因为您的自定义函数假定 data
是一个行向量,特别是这一行:
out = sum(log(1+exp(lambda))-data.*lambda);
由于 implicit expansion,当行向量 lambda
和列向量 data
相互作用时,根据错误消息,您会得到一个巨大的方阵。
添加这两行以明确表明两者都是列向量解决了这个问题,避免了隐式扩展,并按照您的预期逐元素应用计算。
lambda = lambda(:);
data = data(:);
所以你的函数变成了
function out = loglike(data, params, T_1, T_2, npast)
N = length(data);
if npast == 0
past = 0;
else
past = zeros(1,N);
past(npast+1:end) = movmean(data(npast:end-1),[npast-1, 0]); % Average number of events in the previous n years
end
lambda = params(1) + ...
(params(2)*cos(2*pi*(1:N)/T_1)) + ...
(params(3)*sin(2*pi*(1:N)/T_1)) + ...
(params(4)*cos(2*pi*(1:N)/T_2)) + ...
(params(5)*sin(2*pi*(1:N)/T_2)) + ...
params(6)*past;
lambda = lambda(:);
data = data(:);
out = sum(log(1+exp(lambda))-data.*lambda);
end
另一种方法是重写您的函数,使其使用列向量,但您使用 (1:N)
步骤和 movmean
中的串联创建新的行向量。建议的方法可以说是“更懒惰”,但对行或列输入也很稳健。
另请注意,我已将您的变量名称从 size
更改为 N
,因为 size
是一个内置函数,您应该避免隐藏。
我正在尝试将 'mle' 与自定义负对数似然函数一起使用,但出现以下错误:
Requested 1200000x1200000 (10728.8GB) array exceeds maximum array size preference (15.6GB). This might cause MATLAB to become unresponsive.
我使用的数据是一个 1x1200000 二进制数组(我必须将其转换为双精度数组),该函数有 10 个参数:一个用于数据,3 个已知参数,6 个待优化。我尝试将 'OptimFun' 设置为 'fminsearch' 和 'fmincon'。此外,使用 'fminsearch' 和 'fminunc' 而不是 'mle' 优化参数效果很好。
问题发生在 'checkFunErrs' 函数中,在 'mlecustom.m' 文件中(在第 173 行调用,在第 705 行实际出错)。
使用 'fminunc' 我可以计算出最佳参数,但它没有给我置信区间。有没有办法规避这个?还是我做错了什么?
感谢您的帮助。
T_1 = 50000;
T_2 = 100000;
npast = 10000;
start = [0 0 0 0 0 0];
func = @(x, data, cens, freq)loglike(data, [x(1) x(2) x(3) x(4) x(5) x(6)],...
T_1, T_2, npast);
params = mle(data, 'nloglf', func, 'Start', start, 'OptimFun', 'fmincon');
% Computes the negative log likehood
function out = loglike(data, params, T_1, T_2, npast)
size = length(data);
if npast == 0
past = 0;
else
past = zeros(1, size);
past(npast+1:end) = movmean(data(npast:end-1),[npast-1, 0]); % Average number of events in the previous n years
end
lambda = params(1) + ...
(params(2)*cos(2*pi*(1:size)/T_1)) + ...
(params(3)*sin(2*pi*(1:size)/T_1)) + ...
(params(4)*cos(2*pi*(1:size)/T_2)) + ...
(params(5)*sin(2*pi*(1:size)/T_2)) + ...
params(6)*past;
out = sum(log(1+exp(lambda))-data.*lambda);
end
您的问题是内置 mle
函数的第 228 行(从 MATLAB R2017b 开始),它发生在调用自定义函数之前:
data = data(:);
输入变量data
在没有警告的情况下转换为列数组。这通常是为了确保所有进一步的计算对输入向量的方向都是稳健的。
但是,这会给您带来问题,因为您的自定义函数假定 data
是一个行向量,特别是这一行:
out = sum(log(1+exp(lambda))-data.*lambda);
由于 implicit expansion,当行向量 lambda
和列向量 data
相互作用时,根据错误消息,您会得到一个巨大的方阵。
添加这两行以明确表明两者都是列向量解决了这个问题,避免了隐式扩展,并按照您的预期逐元素应用计算。
lambda = lambda(:);
data = data(:);
所以你的函数变成了
function out = loglike(data, params, T_1, T_2, npast)
N = length(data);
if npast == 0
past = 0;
else
past = zeros(1,N);
past(npast+1:end) = movmean(data(npast:end-1),[npast-1, 0]); % Average number of events in the previous n years
end
lambda = params(1) + ...
(params(2)*cos(2*pi*(1:N)/T_1)) + ...
(params(3)*sin(2*pi*(1:N)/T_1)) + ...
(params(4)*cos(2*pi*(1:N)/T_2)) + ...
(params(5)*sin(2*pi*(1:N)/T_2)) + ...
params(6)*past;
lambda = lambda(:);
data = data(:);
out = sum(log(1+exp(lambda))-data.*lambda);
end
另一种方法是重写您的函数,使其使用列向量,但您使用 (1:N)
步骤和 movmean
中的串联创建新的行向量。建议的方法可以说是“更懒惰”,但对行或列输入也很稳健。
另请注意,我已将您的变量名称从 size
更改为 N
,因为 size
是一个内置函数,您应该避免隐藏。