【问题标题】:How to vectorize searching function and Intersection in Matlab?如何在 Matlab 中矢量化搜索函数和交集?
【发布时间】:2015-04-08 04:58:20
【问题描述】:

这是一个 Matlab 编码问题(与 setdiff 略有不同的版本不相交here):

一个有3列的评分矩阵A,第1列是可能重复的用户ID,第2列是可能重复的项目ID,第3列是用户对项目的评分,范围从1到5。

现在,我有一个用户 ID 子集 smallUserIDList 和一个项目 ID 子集 smallItemIDList,然后我想在 smallUserIDList 中找到 A 中用户评分的行,并收集用户评分的项目,并进行一些计算,例如与 smallItemIDList 并计算结果,如下代码所示:

userStat = zeros(length(smallUserIDList), 1);
for i = 1:length(smallUserIDList)
    A2= A(A(:,1) == smallUserIDList(i), :);
    itemIDList_each = unique(A2(:,2));

    setIntersect = intersect(itemIDList_each , smallItemIDList);
    userStat(i) = length(setIntersect);
end
userStat

最后,我发现配置文件查看器显示上面的循环效率低下,问题是如何通过矢量化而不是 for 循环的帮助来改进这段代码?

例如:

输入

A = [
1 11 1
2 22 2
2 66 4
4 44 5
6 66 5
7 11 5
7 77 5
8 11 2
8 22 3
8 44 3
8 66 4
8 77 5    
]

smallUserIDList = [1 2 7 8]
smallItemIDList = [11 22 33 55 77]

输出

userStat =

 1
 1
 2
 3

【问题讨论】:

  • 我给你的第一个建议是学习/使用 Python 和 Pandas,joins 会非常快速和轻松地完成我认为你所描述的事情。这里最大的问题是你的数据结构不好。但是,matlab 函数 find 确实可以很好且快速地找到。您可能还想使用 intersect。这对你有帮助吗?
  • 其实matlab中也有joins
  • @HjörturJónasson,嗨!谢谢你的建议!!这对我来说是一个新的数据结构,感谢您的提及!!不得不说matlab中的稀疏矩阵是我以前学习的主要数据结构,现在不知道学习table是不是更好的选择,主要关心的是table的规模,因为连bsxfun都会给我一个内存泄漏的错误,你想给我介绍一下性能比较吗?谢谢!!

标签: matlab optimization matrix vectorization


【解决方案1】:

啊!您需要对上一个问题的已接受解决方案进行微小的编辑。这是解决方案-

[R,C] = find(bsxfun(@eq,A(:,1),smallUserIDList(:).')); %//'
mask = ismember(A(R,2),smallItemIDList(:).'); %//'# The edit was needed here

ARm = A(R,2);
Cm = C(mask);
ARm = ARm(mask);

userStat = zeros(numel(smallUserIDList),1);
if ~isempty(Cm)
    dup_counts = accumarray(Cm,ARm,[],@(x) numel(x)-numel(unique(x)));
    accums = accumarray(C,mask);
    userStat(1:numel(accums)) = accums;
    userStat(1:numel(dup_counts)) = userStat(1:numel(dup_counts)) - dup_counts;
end

作为奖励,您可以编辑预分配步骤 -

userStat = zeros(numel(smallUserIDList),1);

使用这种更快的预分配方案 -

userStat(1,numel(smallUserIDList)) = 0;

MATLAB Undocumented post on Pre-allocation 中了解更多信息。

【讨论】:

  • 感谢您的帮助!!我真的是matlab的新手。我要问最后一个问题,你有时间看看吗?如果我们更改代码“setIntersect = intersect(itemIDList_each, smallItemIDList); userStat(i) = length(setIntersect);”到“userStat(i) = length(itemIDList_each);”,如何在这段代码中修改?再次感谢!!
  • @archenoo 在第一步之后当你有RC,使用这个userStat = accumarray(C,A(R,2),[],@(x) numel(unique(x)))。因此,在这种情况下,一切都分两步完成。
  • 非常感谢您的细心和善意的帮助!
猜你喜欢
  • 1970-01-01
  • 2014-09-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多