Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/matlab/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Matlab 如何使一个函数根据不断变化的分布进行选择,而不需要反复传递?_Matlab_Math_Random - Fatal编程技术网

Matlab 如何使一个函数根据不断变化的分布进行选择,而不需要反复传递?

Matlab 如何使一个函数根据不断变化的分布进行选择,而不需要反复传递?,matlab,math,random,Matlab,Math,Random,这不是一个关于MatLab的问题,而是一个当您使用一种不太复杂的语言时,如何实现在面向对象编程中容易实现的功能的问题 我是一名数学家,正在编写一些MatLab代码来测试线性代数中的一个算法(我不会用细节来加重您的负担)。程序的开始是生成一个随机的500乘50的浮点矩阵(称为a)。在运行我的程序的过程中,我希望随机选取A的行,不是均匀随机的,而是根据一个分布,其中选取行I的可能性不同,这取决于生成的特定矩阵 我想编写一个名为“pickRandomRow”的函数,在需要时可以反复调用它。在程序的每个

这不是一个关于MatLab的问题,而是一个当您使用一种不太复杂的语言时,如何实现在面向对象编程中容易实现的功能的问题

我是一名数学家,正在编写一些MatLab代码来测试线性代数中的一个算法(我不会用细节来加重您的负担)。程序的开始是生成一个随机的500乘50的浮点矩阵(称为a)。在运行我的程序的过程中,我希望随机选取A的行,不是均匀随机的,而是根据一个分布,其中选取行I的可能性不同,这取决于生成的特定矩阵

我想编写一个名为“pickRandomRow”的函数,在需要时可以反复调用它。在程序的每个单独运行期间,它将在行上使用相同的概率分布,但该分布将在程序运行期间发生变化(因为随机矩阵将不同)

如果我使用的是比MatLab更面向对象的语言,我会创建一个名为“rowPicker”的类,该类可以使用我在这次运行中使用的特定随机矩阵的信息进行初始化。但在这里,我不知道如何在MatLab中创建一个函数,使其能够一劳永逸地知道它需要知道的关于随机矩阵a的信息,而不必在函数不变的情况下反复(昂贵地)将a传递给函数

可能的选择

  • pickRandomRow
    设置为脚本而不是函数,以便它可以查看工作区。那么我就不能给出任何参数,但到目前为止我不明白为什么我需要这样做
  • 开始用MatLab中的类来搞乱

为了完成此任务,您可以使用,确切地说,它的四个参数重载:

y=随机抽样(n,k,真,w)或y=随机抽样(总体,k,真,w) 返回带替换的加权样本,使用的向量为 正权重w,其长度为n。发生以下情况的概率: 为y为w(i)/sum(w)的条目选择整数i。通常,w是 概率向量。randsample不支持加权 取样而不更换

例如:

M = [
  1 1 1;
  2 2 2;
  3 3 3;
  4 4 4;
  5 5 5
];

idx = randsample(1:5,1,true,[0.2 0.2 0.1 0.1 0.4]);
row = M(idx,:);
如果每次运行脚本时都必须拾取多行,并且不支持不带替换的加权采样,则可以使用:

关于类和脚本之间的选择,我真的认为您的问题有点过于复杂了。在这种情况下,OOP类对我来说似乎是一种过度使用。如果希望在不向脚本传递任何参数的情况下使用脚本(实际上是函数),可以在内部定义的矩阵和表示其行概率的变量上使用。假设我提出的第一个解决方案符合您的需要,那么:

a = pickRandomRow();
b = pickRandomRow();
c = pickRandomRow();

function row = pickRandomRow()
    persistent M;
    persistent W;

    if (isempty(M))
        M = [
          1 1 1;
          2 2 2;
          3 3 3;
          4 4 4;
          5 5 5
        ];

        W = [
          0.2
          0.2
          0.1
          0.1
          0.4
        ];
    end

    idx = randsample(1:size(M,1),1,true,W);
    row = M(idx,:);
end
如果要根据以前的计算提供不同的权重,可以按如下方式更改上述代码:

w1 = WeightsFromDistributionX();
w2 = WeightsFromDistributionY();

a = pickRandomRow(w1);
b = pickRandomRow(w2);
c = pickRandomRow(w2);

function row = pickRandomRow(W)
    persistent M;

    if (isempty(M))
        M = [
          1 1 1;
          2 2 2;
          3 3 3;
          4 4 4;
          5 5 5
        ];
    end

    M_size = size(M,1);
    W_size = numel(W);

    if (M_size ~= W_size)
        error('The weights vector must have the same length of matrix rows.');
    end

    idx = randsample(1:M_size,1,true,W);
    row = M(idx,:);
end

就我所记得的,MATLAB支持闭包。 闭包类似于一个对象,有一堆私有成员变量和一个方法。 所以,你可以这样做:

function rowPicker = createRowPicker(matrix, param)
  expensivePreparations = ... (use 'matrix' and 'param' here) ...
  function pickedRow = someComplicatedSamplingFunction
    ... (use 'matrix', 'expensivePreparations' and 'param' here) ...
  end 
  rowPicker = @someComplicatedSamplingFunction
end
for p = [p1, p2, p3]
  matrix = generateMatrix()
  picker = createRowPicker(matrix, p)
  ... (run expensive simulation, reuse 'picker')
end
然后,您可以在循环中生成一组不同参数化的
rowPicker
s,如下所示:

function rowPicker = createRowPicker(matrix, param)
  expensivePreparations = ... (use 'matrix' and 'param' here) ...
  function pickedRow = someComplicatedSamplingFunction
    ... (use 'matrix', 'expensivePreparations' and 'param' here) ...
  end 
  rowPicker = @someComplicatedSamplingFunction
end
for p = [p1, p2, p3]
  matrix = generateMatrix()
  picker = createRowPicker(matrix, p)
  ... (run expensive simulation, reuse 'picker')
end
这样,昂贵的中间结果
expensivepreparements
将保存在闭包中,您不必在
昂贵模拟的每个步骤中重新计算它


警告:以上所有内容都是伪代码,未经测试。

如果创建一个类的工作量太大(您将使用第一个类,它与其他语言有很大不同),您可以选择几种方法

当时的单一发行版

您可以使用函数中的
持久变量来实现这一点。函数将成为某种独特的对象

function out = func(arg)
persistent M; % matrix to pick rows from
persistent S; % status
if nargin == 1
  M = randn(...);
  S = ...;
else
  % use M, S
  return ...;
end
第一次使用
func('init')
调用它,然后使用
data=func()
调用它

多种不同的发行版

您可以重写上述内容,但在使用
'init'
调用时,将返回一个包含内部数据的单元格数组。其他情况下,将该单元格数组作为输入传递:

function out = func(arg)
if ischar(arg)
  M = randn(...);
  S = ...;
  return {M,S};
else % iscell(arg)
  % use M=arg{1}, S=arg{2}
  return ...;
end

当然,它可以是结构而不是单元数组。我认为这是“穷人的目标”。无法控制用户修改对象的状态,但如果您是自己的用户,这可能没什么大不了的。

MATLAB现在是面向对象的。C也可以。这个主意很有趣。我从未在MATLAB中以这种方式使用过lambdas,但我认为它可以工作。我喜欢这个建议。使矩阵持久化与全局化之间的优缺点?顺便说一下,我已经在使用datasample了。英雄所见略同…嘿嘿,谢谢!实际上,persistent只允许变量在声明它的范围内持久化。除非您想显示矩阵或对其进行任何控制,否则我认为在这种情况下,persistent更合适。此外,global还有一个性能缺陷(每次调用函数时都必须找到变量在内存中的位置)。。。但是我认为在这种情况下它会有一个小的影响,我想我想要的是主函数来生成矩阵,而不是行选择器。当然,我想让主函数看到矩阵。实际上,我想将矩阵的必要信息一次性地传达给rowPicker,然后在需要时让它将行号返回给我。也许只是让全球了解矩阵的相关信息?是的,你完全可以这样做。但在这一点上,如果你不介意的话,最好将矩阵作为参数传递。正如我之前指定的,global关键字有一个问题:每次调用它时(在本例中,每次您的行选择f时)