【问题标题】:Handling a very big and sparse matrix in Matlab在 Matlab 中处理一个非常大且稀疏的矩阵
【发布时间】:2014-09-07 12:02:48
【问题描述】:

我有一个非常大且稀疏的矩阵,表示为 CSV 文件 (67 GB)。

是否可以在 Matlab 中加载和使用该矩阵?我可以在 MAC OS 计算机上使用 64 位版本,8GB RAM。

我已经阅读了一些关于这个主题的帖子,但我仍然不确定 Mac OS 上的 Matlab 64 位是否可以使用磁盘空间来分配矩阵或需要 RAM 中的所有内容,无论如何,如果使用这么大的部分磁盘空间的占用可能会使东西几乎无法使用。

【问题讨论】:

  • 67 GB 是否包括所有零?有多少个非零元素?矩阵的整体维度是多少?在 100,000 X 100,000 范围内的某个地方?
  • 是的,67GB 是 CSV 文件的大小,包括空元素;为了节省空间,我把 0 去掉了,所以 4,0,0,7,8 变成了 4,,,7,8。行 x col 的大小为 230k x 290k。少于 1/1000 的矩阵 (0.1%) 是非空的。单元格值是整数,通常

标签: macos matlab matrix sparse-matrix


【解决方案1】:

听起来内存映射是适合您的解决方案!

http://www.mathworks.nl/help/matlab/memory-mapping.html

本质上,您映射文件的位置,以便您可以按部分访问它(一种索引,但我想是在您的硬盘驱动器上)。完成此操作后,根据矩阵的稀疏性(稀疏性?),您可能希望切换到希望适合您的 RAM 的稀疏矩阵,这样您就可以利用 RAM 的速度而不再局限于 HDD 速度。

另一种解决方案是逐行(或其他定界数量)读取文件并仅将非零值放入稀疏矩阵中。

http://www.mathworks.nl/help/matlab/ref/fgetl.html

http://www.mathworks.nl/help/matlab/ref/sparse.html

亲切的问候,

恩斯特·扬

好的,所以当使用 fgetl 解决方案时,我得到了合理的性能。大约。在我的笔记本电脑上每 100 行 10 秒。

% Start with a clean slate.
clear all
% Create a data file, large!
m = 100; % Rows
n = 230000; % Columns
max_x = 10000;
X=randi(max_x,m,n); 
% Create lots of zeros by setting everything smaller 0.999 x_max to 0;
X(X<0.999*max_x)=0;
% Write data file
csvwrite('csvlist.dat',X);

% Now create a sparse matrix to put the csv file in:
P = sparse(m,n);

% Open data file
FID=fopen('csvlist.dat','r');
% Set line number counter to 0
line_number = 0;
% Get the first line of the data file (230K numbers)
text_line = fgetl(FID);
    % If a text line has been retrieved from the line keep looping!
    tic
    while ischar(text_line)
        % Increase to line_number with 1 (MATLAB index starts at 1..)
        line_number = line_number+1;
        % Analyse the first text line (I assume all integers, otherwise change the format %d to %f)
        C = textscan(text_line,'%d','delimiter',',','EmptyValue', 0);
        % Now the number are stored in cell C. Which we should put in the
        % sparse matrix:
        P(line_number,:)=C{1}; % Can be optimized but forgot how but fast enough for now!
        % And let's get the next line!
        text_line = fgetl(FID);
    end
    toc
    fclose(FID);

所以 230k 行大约需要 5 到 10 个小时。

亲切的问候,

恩斯特·扬

【讨论】:

  • 我添加了一些细节作为我的问题的 cmets。
  • 我怀疑稀疏矩阵有几百 MB。通过适当的数据管理完全没有问题。只需使用 fgetl 并解析行(字符串类型,即字符数组)来填充稀疏矩阵。我建议编写脚本并让它运行一整夜,然后将表示稀疏矩阵的变量保存为 .mat 文件以供将来使用。
  • 非常感谢!我遇到的问题是 Matlab 返回“下标分配维度不匹配”。 C = textscan(text_line,'%d','delimiter',',','EmptyValue', 0) 行出错,除非我将 n 设置为 (n-1)。我猜这样它会忽略最后一个字符(一行的最后一个单元格的缺失值,所以,\n)。有什么线索吗?
  • 嗯,我认为问题将在此后的行中 (P(line_number,:)=C{1}。尝试检查 C 的长度是否确实是 230K,或者它是 229 999 . 一行中的值的数量必须等于 n 并且在每一行都保持不变。因此,只需检查 C 的长度( n_numbers = length(C) ),然后再将其分配给 P 以识别问题。
  • 是的 C 是 229999,但我不明白为什么 matlab 在行的中间正确地获取 EmptyValue 而不是在行尾。所以 5,,5,3 是 4 个单元格,而 5,2,4, 是 3 个单元格,为什么?
【解决方案2】:

基于this link 我会说matlab绝对可以保存大多数计算机上存储在矩阵中的数据量。 (我猜你描述的矩阵甚至应该适合 RAM)。要查找计算机的限制,请使用memory 命令。

话虽如此,创建此矩阵的难点在于读取文件。正如@EJG89 的回答中提到的,您可能需要对fgetl 使用逐行方法,因为我不希望像dlmread 这样的更高级别的命令能够以合理的方式处理如此巨大的文件。

如果一切都失败了,只需在处理之前找到一种方法来拆分文件。

【讨论】:

  • 感谢您的回答和评论:内存命令在 MAC OS 上似乎不可用。
  • memory 仅适用于 Windows。
  • 没错,这个话题在这里解决:stackoverflow.com/q/4762044
猜你喜欢
  • 2013-03-02
  • 2021-02-02
  • 1970-01-01
  • 2023-03-05
  • 1970-01-01
  • 2011-03-11
  • 1970-01-01
  • 2018-05-12
  • 1970-01-01
相关资源
最近更新 更多