我目前正在matlab中实现一种算法,该算法搜索购买某些文章的客户数据库。该数据库如下所示:
[ 0 1 2 3 4 5 NaN NaN;
4 6 7 8 NaN NaN NaN NaN;
...]
那个东西的大小就是大小(数据)= [90810 30]。现在我想在该数据库中找到频繁的项目集(不过多使用工具箱)。我将在这里提供一个示例:
toyset = [
0, 1, 2, 3, 4, 5, 6, 7, 8, 9;
5, 6, 7,NaN,NaN,NaN,NaN,NaN,NaN,NaN;
5, 6, 7,NaN,NaN,NaN,NaN,NaN,NaN,NaN;
1, 6, 7, 9, 10, 11,NaN,NaN,NaN,NaN;
2, 4, 8, 11, 12,NaN,NaN,NaN,NaN,NaN];
当应用0.5 [support =(occurences_of_set)/(all_sets)]的最小支持时,这会产生以下项目集:
frequent_itemsets = [
7,NaN,NaN;
6,NaN,NaN;
5,NaN,NaN;
6, 7,NaN;
5, 7,NaN;
5, 6,NaN;
5, 6, 7];
我现在的问题是找到项目集在数据集中的频率。目前我使用以下算法(btw工作得很好):
function list = preprocess(subjectArray, combinations, progressBar)
% =========================================================================
%
% Creates a list which indicates how often an article-combination given by
% combinations is present in the array of Customers
%
% =========================================================================
%
% preprocesses the array; Finds the frequency of articles
% subjectArray - Array that contains customer data
% combinations - The article combinations to be found
% progressBar - The progress bar to indicate the progress of the
% algorithm
%
% =========================================================================
[countCustomers,maxSizeCustomers] = size(subjectArray);
[countCombinations,sizeCombinations] = size(combinations);
list=zeros(1,countCombinations);
for i = 1:countCustomers
waitbar(i/countCustomers,progressBar,sprintf('Preprocess: %.0f/%.0f\nSet size:%.0f',i,countCustomers,sizeCombinations));
for k = 1 : countCombinations
helpArray = zeros(1,maxSizeCustomers);
help2Array = zeros(1,sizeCombinations);
for j = 1:sizeCombinations
helpArray = helpArray + (subjectArray(i,:) == combinations(k,j));
help2Array(j) = any(helpArray);
end
list(k) = list(k) + all(help2Array);
end
end
end
我唯一的问题是需要年龄!!!从字面上看!有没有简单的可能性(除了长度为1的集合,我知道通过简单的计数可以更快),以使这更快?
我认为:
helpArray = helpArray + (subjectArray(i,j) == combinations(k,:));
是瓶颈吗?但我不确定,因为我不知道matlab在某些操作上有多快。
感谢您对此进行调查,请注意_
我最终做了什么:
function list = preprocess(subjectArray, combinations)
% =========================================================================
%
% Creates a list which indicates how often an article-combination given by
% combinations is present in the array of Customers
%
% =========================================================================
%
% preprocesses the array; Finds the frequency of articles
% subjectArray - Array that contains customer data
% combinations - The article combinations to be found
%
% =========================================================================
[countCustomers,maxSizeCustomers] = size(subjectArray);
[countCombinations,sizeCombinations] = size(combinations);
list=zeros(1,countCombinations);
if sizeCombinations == 1
for i = 1 : countCustomers
for j = 1 : maxSizeCustomers
x = subjectArray(i,j) + 1;
if isnan(x), break; end
list(x+1) = list(x+1) + 1;
end
end
else
for i = 1:countCombinations
logical = zeros(size(subjectArray));
for j = 1:sizeCombinations
logical = logical + (subjectArray == combinations(i,j));
end
list(i) = sum(sum(logical,2) == sizeCombinations);
end
end
end
感谢所有支持!
答案 0 :(得分:3)
很抱歉,我无法发表评论(我的声誉太低了,我想) 频繁的项目集挖掘非常复杂。 如果你有一个庞大的数据集并且你选择一个项目(集合)的低门槛是频繁的,你的方法(apriori?)你必须准备等待很长时间:) 通常,当您使用matlab处理嵌套for循环时,您也会遇到性能低下的问题。 你选择了什么门槛?你的数据集有多大?
答案 1 :(得分:1)
我立即看到三项建议:
首先,您的等候栏会为您的搜索添加额外的三分半钟。根据这个帖子:http://www.mathworks.com/matlabcentral/newsreader/view_thread/261380如果你包括等候栏,那么代码需要经过240,000个项目额外的550秒才能执行,缩放到90,000,你还有3分半钟的额外时间。
要计算最初频繁的选项,请使用逻辑索引的总和,例如,查看数据集中7的频率。
logical7=subjectArray==7;
numOf7s=sum(sum(logical7));
为每个值执行此操作,我感觉即使会有额外的代码,也会加快初始处理速度。
为了使代码更好,您可以执行
之类的操作预分配逻辑垫,每个3d切片表示一个数字(第6个切片表示频率= 5,第7个切片表示频率= 6)
logMat=zeros([size(subjectArray) maxPossibleVal+1])
%最大可能的val在前玩具箱中为9。
然后用逻辑#matricies
填充每个切片for i=0:maxPossibleVal
logMat(:,:,i+1) = subjectArray==i;
end
再一次,您可以从每个逻辑切片中获得总和以及小于特定阈值的总和,您可以从日志中删除。 mat(我也会使用逻辑索引来删除不符合阈值的切片)
现在,对所有逻辑索引进行处理的好处是,您可以将切片与加法或乘法相结合,以获得不同的组合频率。您甚至可以旋转这些操作的结果,然后使用“sum”命令,然后使用逻辑索引来获得两个或三个数字一起出现的频率。
logM7=logMat(:,:,8)
logM8=logMat(:,:,9)
combo7and8=logical(double(logM7)+double(logM8))
%你可以用|替换它使这更简单/更快
freq7and8=sum(sum(combo7and8')==2)
默认情况下,%sum会找到列的总和,将我们的行转换为列,然后找出哪些行等于2,将所有逻辑1加在一起,然后你就得到了频率。每个数据集中的7和8个。
整篇文章可归纳为两件事:
取消等候栏
知道在代码中几乎可以使用逻辑索引,这比循环快得多