2013-06-21 25 views
2

我目前正在matlab中實現一個算法,通過購買某些文章的客戶數據庫進行搜索。這個數據庫看起來如下:更快地搜索一個巨大的陣列matlab

[ 0 1 2 3 4 5 NaN NaN; 
    4 6 7 8 NaN NaN NaN NaN; 
...] 

只是大小的東西是大小(數據)= [90810 30]。現在我想在該數據庫中找到頻繁的項目集(沒有太多使用工具箱)。我將提供這裏toyexample:

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的最小支持時生成以下項集[支持=(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執行某些操作的速度有多快。

感謝尋找到它,mind_

我最終什麼了這樣做的:

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

你能概念性地解釋你如何得到'頻繁_集合'嗎? – Oleg

+0

用上面的算法確定項目集在數據中的頻率,然後刪除所有不頻繁的項目集。在這個例子中,因此0-4和8-12。然後我建立剩餘的所有可能的組合並再次運行算法。在這個例子中:5,6 5,7 6,7 –

+0

噢,是的,我還做了一些事情,就是事後收縮數據,這樣我就不必一遍又一遍地查看不包含任何頻繁項目集的項目集。 –

回答

1

三點建議我看到了蝙蝠的權利:

首先,你waitbar是增加一個額外的三年半鍾到您的搜索。根據這個線程: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 

再次,你可以從每個邏輯片讓您的資金和那些低於某一閾值,您可以從日誌中刪除。墊子(我也會用邏輯索引去除不符合閾值的切片)

現在,將所有東西都邏輯索引的好處是可以將切片與加法或乘法相結合以獲得不同的組合頻率。你甚至可以旋轉這些操作的結果,然後使用「sum」命令,然後使用邏輯索引來獲得兩個或三個數字一起出現的頻率。

logM7=logMat(:,:,8) 
logM8=logMat(:,:,9) 

combo7and8=logical(double(logM7)+double(logM8))

%你也許有可能取代這個|使默認情況下這個簡單/更快

freq7and8=sum(sum(combo7and8')==2) 

%和認定列的總和,把我們的行轉換成列,然後找出行等於2,添加所有的邏輯1的在一起,你有頻率。在每個數據集中的7和8。

這整個帖子可以通過兩點來概括:

取下waitbar

知道這是可以在你的代碼,這是更快,幾乎無處不使用邏輯索引比循環

+0

非常感謝!我首先需要了解你剛寫下的每一點,但看起來非常好!謝謝你的時間!我現在喜歡保持waitbar,稍後當我包含運行時分析時,我會將其從算法中拿出來。只是在那裏安慰我,發生了一些事情。 –

+1

對於等待欄,有很多解決方法,請記住,等待欄最多隻有300個增量,您無需更新併爲300次更新渲染90,000次。使用一個mod運算符或類似的東西。另外,如果你只是想知道它的確在發展,只需在開頭顯示「嘿,我正在工作」。比waitbar快的東西也只是文字,請查看以下鏈接:。最後,真的看看邏輯索引! :) – Shaun314

+0

是的,我會的,謝謝,它加快了相當多的事情!對於第一步,我實際上做了一些其他的事情:我只是循環一次矩陣,然後每步增加向量(矩陣(i,j)+1)...至少在第一步中更快(即使邏輯索引看起來更好:D)。 –

3

對不起,但我不能評論(我的信譽太低,我想) 頻繁的項目集挖掘相當複雜。 如果你有一個龐大的數據集,並選擇一個項目(集)頻繁的低門檻,你的方法(apriori?),你必須準備好等待很長時間:) 通常當你處理嵌套與matlab循環你也體驗低性能。 你選擇了哪個門檻?你的數據集有多大?

+0

感謝您回答......如上所述,我的數據集的大小是[90810 30]。你猜對了,它確實是先驗的。在試圖在MATLAB中實現樹之前,我想要獲得Matrixpart。所以我有一些控制。我的門檻現在是5%。我的問題是有51%的支持的特定項目......這使得計算相當緩慢,因爲我無法輕鬆擺脫49%以上的客戶。 –

+1

好吧,正如我所說的apriori是最天真的方法。如果您在第一階段(項目計數)中獲得的頻率過高,並且達到此閾值,我建議您增加它,直到執行時間變得合理。 提高代碼速度的解決方案可以嘗試將操作放在「矩陣操作」形式中:matlab以矩陣形式執行相同的矩陣操作,比在for循環中執行的操作快得多。 – DrunkenDuck

+0

好的,那將值得一試......謝謝!因此,不是對所有組合進行迭代,而是將它作爲矩陣進行「一次」計算,而不是作爲vektor進行計算?好吧,我會嘗試! –