自定义负对数似然函数的mle内存错误



我试图将'mle'与自定义的负对数似然函数一起使用,但我得到了以下错误:

请求的120000x1200000(10728.8GB(数组超过了最大数组大小首选项(15.6GB(。这可能会导致MATLAB没有响应。

我使用的数据是一个1x1200000二进制数组(我必须将其转换为双精度(,该函数有10个参数:一个用于数据,3个已知参数,6个待优化。我试着将"OptimFun"设置为"fminsearch"one_answers"fmincon"。此外,使用"fminsearch"one_answers"fminunc"而不是"mle"优化参数效果良好
问题发生在'mlecustom.m'文件内的'checkFunErrs'函数中(第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);

由于隐式展开,当行向量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中的串联来创建新行向量。所建议的方法可以说是";lazier";,而且对行或列输入也是鲁棒的。

另外请注意,我已经将您的变量名从size更改为N,因为size是一个内置函数,您应该避免隐藏它。

相关内容

  • 没有找到相关文章

最新更新