【问题标题】:Is there an equivalent of Python's list and append feature in Matlab?Matlab 中是否有相当于 Python 的列表和附加功能?
【发布时间】:2015-08-21 05:52:04
【问题描述】:

这更像是一个 Matlab 编程问题,而不是一个数学问题。

我想在不同的学习率上运行多次梯度下降。我有一套学习率

alpha = [0.3, 0.1, 0.03, 0.01, 0.003, 0.001];

每次运行梯度下降时,我都会得到一个向量 J_vals 作为输出。但是,除了执行以下操作之外,我对 Matlab 的了解还不够,不知道如何实现:

[theta, J_vals] = gradientDescent(...., alpha(1),...);
J1 = J_vals;
[theta, J_vals] = gradientDescent(...., alpha(2),...);
J2 = J_vals;

等等。

我考虑过使用 for 循环,但后来我不知道如何处理 J_vals 的(不知道如何将 for 循环应用于 J1J2 等等)。也许它看起来像这样:

for i = len(alpha)
     [theta, J_vals] = gradientDescent(..., alpha(i),...);
     J(i) = J_vals;
end

然后我会有一个向量的向量。

在 Python 中,我只需运行一个 for 循环并将每个新结果附加到列表的末尾。如何在 Matlab 中实现这样的功能?还是有更有效的方法?

【问题讨论】:

    标签: python arrays matlab


    【解决方案1】:

    如果您知道要进行多少循环以及 J_vals 的大小(或至少是合理的上限),我建议您预先分配容器数组的大小

    J = zeros(n,1);
    

    然后在每个循环中插入新值

    J(start:start+n) = J_vals
    

    这样你就不会重新分配内存。如果您不知道,可以将值附加到数组中。例如,

    J = []; % initialize
    for i = len(alpha)
         [theta, J_vals] = gradientDescent(..., alpha(i),...);
        J = [J; J_vals]; % Append column row
    end
    

    但这是在每个循环中重新分配数组的大小。如果不是太多循环应该没问题。

    【讨论】:

    • 在 python 中,列表可以接受任何类型的元素,但在 Matlab 的数组中是否适用?
    • 对于不同的类型使用cell arrays
    【解决方案2】:

    Matlab 的"cell arrays" 有点像 Python 中的列表。它们的相似之处在于您可以将变量数据类型放入其中。似乎没有人太确定,但是most likely the cell array is implemented as an array of object pointers. 这意味着附加到它仍然有些昂贵(cell_array{length(cell_array) + 1} = new_data),但至少你只是附加一个指针而不是整个列。之后,您仍然需要使用 cell2mat 将元胞数组转换为普通矩阵。

    最惯用的 Matlab 解决方案是预分配(如 @dpmcmlxxvi 建议的那样)。

    我认为您所描述的是一个非常常见的用例,不幸的是,Matlab 为此需要如此冗长的习语。此外,令人沮丧的是,文档对于如何实现元胞数组以及附加到元胞数组是否昂贵是不透明的。

    【讨论】:

      【解决方案3】:

      只要为行下标添加:(假设J_vals 是列向量),您的解决方案就可以正常工作:

      for i = len(alpha)
           [theta, J_vals] = gradientDescent(..., alpha(i),...);
           J(:, i) = J_vals;
        %//  ^... all rows, column 'i'
      end
      

      你甚至可以把它作为返回值:

      for i = len(alpha)
           [theta, J(:, i)] = gradientDescent(..., alpha(i),...);
           %//       ^... add returned value directly to our list
      end
      

      这两种方法都允许您预先分配矩阵以获得潜在的速度增益。

      如果你想建立你的列表,你可以使用@dpmcmlxxvi 的答案中的方法,或者你可以使用特殊的下标end。不过,这两种方法都不兼容预分配。

      for i = len(alpha)
           [theta, J(:, end+1)] = gradientDescent(..., alpha(i),...);
           %//          ^... add new vector after the current end of list
      end
      

      我还想建议你不要在 Matlab 中使用i 作为变量名。我知道这对于其他语言来说很自然,但在 Matlab 中它会覆盖内置的虚数常量 i
      见:https://stackoverflow.com/a/14790765/1377097

      【讨论】:

      • J_vals 是一个列向量。这会改变你的反应吗?
      • @AlanH 你只需要交换下标。我会更新我的答案。
      猜你喜欢
      • 2019-11-29
      • 1970-01-01
      • 2014-04-02
      • 2012-06-18
      • 2023-03-31
      • 1970-01-01
      • 2016-12-16
      • 1970-01-01
      • 2020-11-23
      相关资源
      最近更新 更多