【发布时间】:2016-09-10 20:43:38
【问题描述】:
我想在 Octave 中生成一个已知维度的矩阵。问题是我不想用零初始化矩阵。矩阵将仅包含 0 或 1,但未分配任何值的元素(单元格)必须保持空白。计划在“协同过滤”算法中使用这样的矩阵。
我是 Ocatve 和“协作过滤”算法的新手。曾尝试在网上寻找解决方案,但无济于事。网络上的关键字空矩阵是指零维数组或以“”为值的字符矩阵。
【问题讨论】:
我想在 Octave 中生成一个已知维度的矩阵。问题是我不想用零初始化矩阵。矩阵将仅包含 0 或 1,但未分配任何值的元素(单元格)必须保持空白。计划在“协同过滤”算法中使用这样的矩阵。
我是 Ocatve 和“协作过滤”算法的新手。曾尝试在网上寻找解决方案,但无济于事。网络上的关键字空矩阵是指零维数组或以“”为值的字符矩阵。
【问题讨论】:
问题是我不想用零初始化矩阵。矩阵将仅包含 0 或 1,但未分配任何值的元素(单元格)必须保持空白。
你错了。您可能认为矩阵只包含值 0 或 1,但实际上它的值是 0、1 或未设置。你不能有一个空白值,你总是需要一些值。或者至少不要像你想的那样空白。把它放在一个非常低的级别,所有的咬都需要有一个值(0或1),它们不能为空。因此,如果您想要一个空白值,您需要将某个值解释为空白。
您的数据将具有 3 种状态:真、假和空白。因此,每个点至少需要 2 位(请注意,即使是逻辑/布尔数据类型,也只需要 1 位,actually take up 8 bits (1 byte))。
这可能看起来像简单的解决方案,但实际上非常糟糕。这将浪费大量内存(如果您进行协同过滤,您将拥有非常大的矩阵)。
原因是如果你使用NaN,你的数据需要是单或双类型的。那分别是至少 32 位或 64 位。请记住,您实际上只需要 2 位。当然,您可以创建自己的具有NaN 值的数据类型。
octave> vals = NaN (3, 3) # 3x3 matrix of type double (default)
vals =
NaN NaN NaN
NaN NaN NaN
NaN NaN NaN
octave> vals = NaN (3, 3, "single") # 3x3 matrix of type single
vals =
NaN NaN NaN
NaN NaN NaN
NaN NaN NaN
cell array 是一种数据类型,其中每个单元格都可以是任何 Octave 值。这包括另一个元胞数组、任意维度的矩阵,甚至是一个空数组。您可以将空数组用作空白,但这对于内存和速度来说效率都非常低,并且您将无法使用大多数函数,因为它们将适用于数值数组,而不是元胞数组。
octave> vals = cell (3, 3); # create 3x3 cell matrix
octave> vals{2,3} = true; # set value
octave> vals{2,3} = false; # set value
octave> vals{2,3} = []; # unset value
octave> cumsum (vals)
error: cumsum: wrong type argument 'cell'
octave> nnz (vals)
error: nnz: wrong type argument 'cell array'
octave> find (vals)
error: find: wrong type argument 'cell'
这是我看到最常用的。使用带符号的 8 位,您可以使用 0 表示空白,-1 表示假,1 表示真(或任何对您最有意义的)。
octave> vals = zeros (3, 3, "int8");
如果您真的想要一个 0 和 1 的矩阵,那么您需要一个单独的矩阵来跟踪已设置的值。在这种情况下,两个矩阵都可以是逻辑类型,因此每个数据点占用 8 位,每个数据点总计 16 位。它还有一个问题是你需要让两个矩阵保持同步。
octave> vals = false (3, 3);
octave> set_vals = false (size (vals));
使用old @class type 的新classdef(需要Octave 4.0.0),您可以将上述任何策略(我个人会使用8 位整数)封装在它自己的类中。如果您使用带符号的 8 位,这会移动知道哪个值(-1 或 0)表示空白的逻辑。或者,如果您更喜欢对空白值使用单独的矩阵,则将保持值同步的逻辑移至 setter 方法。
【讨论】:
数值数组不能保存空值。通常在这种情况下,人们会使用NaN 作为占位符值。
%// Initialize a 3D matrix of NaN values
data = nan(2, 3, 4);
size(data)
%// 2 3 4
然后很容易将占位符值与真实数据区分开来。您可以使用isnan 检测它们。
创建空值数组的唯一方法是使用元胞数组(由于性能下降,强烈建议不要这样做)。
data = cell(2, 3, 4);
【讨论】: