天天看點

啤酒與尿布,咩叔原創基于圖論簡單到爆的實時關聯性算法

整天說資料庫有點膩歪,今天換個話題,講講關聯性算法。本文首先簡單介紹一下經典的 apriori 及其改進算法

FP

Growth

,最後介紹一下當年咩叔寫論文時候琢磨出的一個利用 圖論 實作的 線上實時計算的“圖權重算法”

 說到算法…道友請留步,請留步……

啤酒與尿布,咩叔原創基于圖論簡單到爆的實時關聯性算法
 老夫知道少俠們都很忙的,而且有時候一些東西确實令人不快,比如
啤酒與尿布,咩叔原創基于圖論簡單到爆的實時關聯性算法
講真,老夫也不喜歡那些阿爾法貝塔啥的玩意!要不是因為窮,我研究什麼算法啊。是以在此文中,我們隻講四則運算,堅決不燒腦。
啤酒與尿布,咩叔原創基于圖論簡單到爆的實時關聯性算法

本文标題“啤酒與尿布”是一個爛大街的MBA梗:沃爾瑪通過資料分析發現很多買啤酒的年輕爸爸都要買尿布,從此将啤酒與尿布放一起,balabalabala…

講真,老夫一直很懷疑這個梗的真實性,因為從沒見超市中啤酒和尿布放一起啊。“啤酒配炸雞”才是正确擺放方式,是吧。

嗯,标題雖老,但是經典,就好比一說到經典的蒼老師,我們就會想起逝去的“青春”以及E盤“學習資料“檔案夾。

這種“

蒼老師“→”青春“→”學習資料“

之間的想象關聯,展現的是人類的發散性思維(Divergent Thinking,是一種呈現擴散狀态的思維模式),是創照性思維的核心,是創照力的展現。

你們看,以上“青春”與“學習資料”是高尚而純潔的。老夫接下去就要介紹高尚而純潔的“

關聯性算法

“。

所謂關聯性算法,一句話就能表述其核心思想:

無非就是從一堆東西裡面哪幾個經常結對出現來判斷其關聯強弱

這個道理太簡單了。想想啊,這是當年高中班主任抓早戀用的算法啊,看班裡哪兩個經常膩歪在一起,一拿一個準!是以咩叔經常說,别整天以為會念個阿爾法貝塔就牛逼了,道在屎溺,算法往往隻是生活中辦法的歸納而已。

接下去正式扯算法。為免少俠關浏覽器,我們展開想象的翅膀,假設一個場景:咩叔去東京加勒比(胡亂杜撰的啊)大學留學,他的導師伊庫教授(日本人的名字好奇怪)要他使用關聯算法,從與咩叔一起結伴做作業的行為上分析一下班上哪幾位女同學之間有關聯性(日本人的研究也好奇怪)。

在開始分析之前,教授說道:“咩桑,我們日本人在研究方面是很認真的,我們要先定義好專業名詞。”

好的好的,咩桑明白日本人很專業,是以讓我們開始關聯性研究中的名詞定義:

項(Item) :指具體的一項事物。比如班級裡的波多醬,小澤醬,櫻井醬,都是項。 項集(itemset) :項的集合,由n(n>=1)個項組成的一個整體,由k個項組成的項集叫k項集。比如 {波多醬,小澤醬}就是一個2項集。 事務(transaction) :一個事務可以了解為發生的一次事件,比如一次做作業行為,用符号T表示。一般來說,T包含唯一的事務ID以及一個項集。若幹個T構成一個資料挖掘樣本庫,用符号D表示。 關聯規則( Association Rule

:實體之間的相關關系,用A⇒B表示A和B之間存在相關關系(A、B可以是項或項集)。比如  波多醬⇒沖田醬  表示這兩位同學存在關系(關系就關系了,為什麼要用 ⇒ 呢?看下去就明白了)。

關聯規則包含

支援度(support) 置信度(confidence)

兩個名額。

先說支援度。支援度分兩種:

絕對 以及 相對 支援度。 絕對支援度 :又稱支援度計數,指一個實體出現的次數,support(A) = A在全體事務資料庫D中出現的次數。比方說,咩叔與同學們做作業的總次數是10次,泷澤醬出現了2次,那麼泷澤醬的絕對支援度就是2。 相對支援度

:所有事務中,A和B同時出現的次數與總事務數的比例,稱為“相對支援度”。公式為:support(A∪B)=P(A∪B) 其中,P(A∪B)即事務中同時包含A和B的比例。比方說咩叔一共和同學做作業的次數是10次,其中與小澤醬和沖田醬一起作業的次數是8次,那麼這一對的相對支援度是0.8。

(這裡暫停,回想國内抓早戀的場景:在班主任的“抓早戀算法”中,隻需要相對支援度就夠了,瞅着名額高的那一對抓。這個算法簡單粗暴但是直接有效,給無數少男少女留下不可磨滅的心理陰影,真是好讨厭好讨厭啊。)

恩,讓我們從殘酷青春的回憶中回到現實,繼續讨論算法。

如果僅僅按“同時出現的比例“,也确實是能找到有關聯性的項集的,這個沒錯。但是我們更深入一下,就會發現,關系之間也是有”方向“的。咩叔打個比方:

有一天叔想起曾經的班主任,就去google搜尋了一下“陳老師“,結果出來這個奇怪的結果

啤酒與尿布,咩叔原創基于圖論簡單到爆的實時關聯性算法

奇怪,為什麼“陳老師“和”硬碟“之間存在關聯性?

帶着這個疑問,叔又搜尋了一下“硬碟“

啤酒與尿布,咩叔原創基于圖論簡單到爆的實時關聯性算法

唷,這回沒有“陳老師“。

雖然至今咩叔也不知道為何這個結果如此奇怪,但是這個例子告訴我們,事物的關聯之間是有方向的(

現在知道為什麼用 号了吧 。我們要搞清楚是“在買尿布的時候順帶買了啤酒“還是”在買啤酒的時候順帶買了尿布“。是以我們需要引入另一個名額: 置信度

:A⇒B的置信度指在包含A的事務中,同時也包含B的事務所占的比例。用公式為:confidence(A⇒B)=P(B|A)=support(A∪B)/support(A)。

我們用這個公式看看在

“陳老師“與”硬碟“之間誰起了”聯想主導“作用

以下是在google上查找各關鍵詞的結果:

硬碟          約66,900,000       條結果

陳老師       約5,220,000         條結果

陳老師硬碟 約4,580,000        條結果

計算一下陳老師、硬碟之間的置信度:

Confidence(陳老師⇒硬碟)=4580000/5220000=0.877

Confidence(硬碟⇒陳老師)=4580000/66900000=0.068

很明顯的是,

在陳老師與硬碟的發散聯想中,陳老師起了主導作用

嗯,以上是一些專業名詞的說明與解釋。通過這些簡單的解釋,我們可以明白,在關聯算法中:

1、

相對支援度表示幾個貨經常一起出現的比例,越高則說明關系越強。 2、 置信度說明經常出現在一起的貨中誰是帶頭大哥。

關聯性算法的目的,就是找出相對支援度(support)和置信度(confidence)滿足預定義的最小支援度門檻值(min_sup)和最小置信度門檻值(min_conf)的項集。我們稱這些項集之間存在“強規則”。而存在“強規則”的項集,必然是頻繁在事務中出現的項集,該項集出現的次數滿足最小支援度計數門檻值。

是以,

“找出所有頻繁項集”是關聯規則挖掘中最重要也是開銷最大的一步。 接下去我們看一下經典的 Apriori算法

如何解決問題。

Apriori中文意義是“先驗的、演繹的、推測的”,其核心思想歸納下來是:

任何頻繁K項集都由頻繁K−1項集組合而成,頻繁K項集的所有K−1項子集一定都是頻繁K−1項集
啤酒與尿布,咩叔原創基于圖論簡單到爆的實時關聯性算法

Emmm,好吧好吧,咩叔隻是裝一下而已。我們用以下例子說明:

假設咩叔和同學做作業的資料如下:

啤酒與尿布,咩叔原創基于圖論簡單到爆的實時關聯性算法

設最小支援度門檻值min_sup=0.4

設最小置信度門檻值min_conf=0.7

Apriori計算步驟如下:

1、把所有事務中出現的同學每一個人都作為一個1項集,組成一個集合,記為C1。這裡 

C1 = { 波多醬, 沖田醬, 小澤醬, 櫻井醬, 吉澤醬} 我們列一下表統計一下每位同學的出現次數

同學 波多醬 沖田醬 小澤醬 櫻井醬 吉澤醬
出現次數 2 3 1

2、将C1中各1項集與最小支援度計數門檻值min_sup比較,篩除小于min_sup的項集,剩下頻繁1項集組成的集合記為L1。

因為min_sup=0.4,則根據統計,櫻井醬隻出現了一次,占總事務比例為1/5=0.2,慘遭淘汰。此時的 

L1={ 波多醬,沖田醬,小澤醬,吉澤醬}

3、接下去我們嘗試根據L1生成C2。顧名思義,C2是由2項集組成的集合。

C2的生成就比較費腦了,需要經過

連接配接、篩選

才能完成。

我們先看如何連接配接。所謂連接配接,就是用兩個頻繁K−1項集,組成一個K項集,分為兩步:

判斷兩個頻繁K−1項集是否可連接配接。所謂可連接配接,指的是對于兩個頻繁K−1項集L1,L2,先對項集中的項進行排序(如字典序),若L1,L2的前K−2項都

相等則L1,L2可連接配接,用它們生成一個新的K項集。

啤酒與尿布,咩叔原創基于圖論簡單到爆的實時關聯性算法

哦哦,有點燒腦是吧,舉例解釋一下:

當K=2時,有2個1項集{A}與{B}需要連接配接。首先排序,額,1項集,沒啥好排的。然後對比前K-2=0項是否相等,這裡因為是0,是以不用比,直接連接配接,最終結果為2項集{A,B}。

當K=3時,有2個2項集{B,A}與{A,C}需要連接配接。首先排序,整理成{A,B}以及{A,C}。然後對比前K-2=1項是否相等,發現他們第一項都是A,可連接配接,最終結果為3項集{A,B,C}。

L1={波多醬,沖田醬,小澤醬,吉澤醬},經過連接配接,生成的

C2={ {波多醬, 沖田醬},{[波多醬, 小澤醬},{波多醬, 吉澤醬}, {沖田醬, 小澤醬}, {沖田醬, 吉澤醬}, {小澤醬, 吉澤醬} }

注意,定理“頻繁K項集的所有K−1項子集一定都是頻繁K−1項集”,這時就派上了大用處。這個

定理了保證用頻繁K-1項集生成的K項集才“有可能”(注意,是有可能)是頻繁的,算法在這一步直接排除了大量不可能的組合。 因為用頻繁K-1項集生成的K項集“有可能”是頻繁的,是以對K還是需要篩選的。

對C2進行統計,經過掃描資料庫,統計結果如下:

{波多醬, 沖田醬} [波多醬, 小澤醬} {波多醬, 吉澤醬} {沖田醬, 小澤醬} {沖田醬, 吉澤醬} {小澤醬, 吉澤醬}

去掉小于min_sup小于0.4的組合,

L2={ { 沖田醬},{小澤醬, 吉澤醬} 重複執行以上步驟,用L2生成C3,再篩選C3得到L3,再用L3得到C4…直到找出的K項集CK為空集。

在樣本資料中,找到L2後, L3已經是空集了。故已經找到了所有的頻繁項集,

頻繁項集= {

接下去根據置信度做篩選。我們之前定義置信度=0.7,則

confidence(波多醬⇒沖田醬)=

support(波多醬∪沖田醬)/support(波多醬)=2/2=1

confidence(沖田醬⇒波多醬)=

support(波多醬∪沖田醬)/support(沖田醬)=2/3

confidence(小澤醬⇒吉澤醬)=

support(小澤醬∪吉澤醬)/support(小澤醬)=2/3

confidence(吉澤醬⇒小澤醬)=

support(小澤醬∪吉澤醬)/support(吉澤醬)=2/2=1

是以,在以上樣本資料中,按照min_sup=0.4,min_conf=0.7的門檻值,得到 

關聯項集={ {波多醬 沖田醬},{吉澤醬 小澤醬} }。

      啊哈,聽上去唬人的算法其實也就那麼回事吧。搞定,美好的一天!

啤酒與尿布,咩叔原創基于圖論簡單到爆的實時關聯性算法

各位少俠也請休息一下補補腦子,我們一會繼續。

----------------------------------分割線-------------------------------

書接上回,我們剛用Apriori算法得到了一份純潔的同學關系,可喜可賀。不過呢,

Apriori作為一個“老”算法,在性能上是有缺陷的

。主要性能瓶頸有兩個:

1、需要多次掃描資料集。

2、雖然算法中限制候選項集,但當資料量較大時,候選集(特别是候選2項集)仍然會非常龐大,在一些資料集較大并對時序要求較高的場景下往往需要使用并行計算才能彌補性能上的缺陷。

是以,Apriori算法由于時間和空間複雜度較大,在實際使用中往往性能低下。

韓家炜等人提出了FP-Growth算法,思路是将資料集中事務映射到一棵FP-Tree上,而後根據樹找出頻繁項集,建構過程隻需要掃描兩次資料集。

算法思路這裡不再贅述,各位少俠請上度娘。

啤酒與尿布,咩叔原創基于圖論簡單到爆的實時關聯性算法

老夫這裡簡單描述一下步驟。

我們還是用純潔的同學關系樣本,并保持最小支援度門檻值min_sup=0.4

,最小置信度門檻值min_conf=0.7

啤酒與尿布,咩叔原創基于圖論簡單到爆的實時關聯性算法

我們

先來第1次純潔的掃描

統計所有一次項的出現次數,将其降序排列

{沖田醬(3次),小澤醬(3次), 波多醬(2次),吉澤醬(2次),櫻井醬(1次)}

嗯,在這裡剔除可憐的櫻井醬,最終得到 頻繁項清單 L(清單中項按照支援度計數遞減排序)

L={

沖田醬(3次),小澤醬(3次),

波多醬(2次),吉澤醬(2次)}

建構初始根節點為null的FP樹,而後

進行第2次掃描,從資料庫中逐一取出事務,按照 L 排序,把每個項逐個添加到FP-Tree的分枝上去

啊啊,說人話說人話,以下解釋:

事務1排序後為{沖田醬, 波多醬},在根節點上加一棵子樹“沖田醬-波多醬”,并設初始計數為1。

事務2中去掉已經被淘汰的櫻井醬,得到排序後的項集{沖田醬},發現樹中已經有“沖田醬“節點,嗯,這時候我們直接在“沖田醬“節點計數器上+1

事務3排序後得到{小澤醬,吉澤醬},這兩個節點是原先樹中沒有的,是以我們在root後加上新的兩個節點

事務4排序後得到{沖田醬,小澤醬,波多醬},我們發現頭部資料“沖田醬”能與現有樹中節點共用,則在樹中“沖田醬”節點上+1,而後在其後面加上子節點 “小澤醬-波多醬”

事務5排序後得到{小澤醬, 吉澤醬},這兩個節點樹中已有,直接計數器+1

步驟流程如圖:

啤酒與尿布,咩叔原創基于圖論簡單到爆的實時關聯性算法

那麼接下去,我們嘗試尋找“波多醬”的好姐妹。

1、首先需要找出

以根節點為頭,以波多醬為結尾之間的所有路徑

。我們找到兩條路徑,分别是

{null,沖田醬(3),波多醬(1)}

{null,沖田醬(3),小澤醬(1),波多醬(1)}

2、其次

掐頭去尾

,去掉根節點以及波多醬本身,得到以下兩個項集

{沖田醬(3)}

{沖田醬(3),小澤醬(1)}

3、而後

用波多醬的計數器

作為項集計數器

{沖田醬}:1    (因為此路徑結尾處波多醬計數器=1)

{沖田醬,小澤醬}:1  (因為此路徑結尾處波多醬計數器=1)

而後,對以上2個項集建立FP-Tree:

先算 L={沖田醬(2次),小澤醬(1次,淘汰)},再用L得到FP-Tree:

啤酒與尿布,咩叔原創基于圖論簡單到爆的實時關聯性算法

不斷重複以上步驟,直到空集為止。在這個例子中,已經找到波多醬的好姐妹{沖田醬(2)},她與波多醬同時出現了2次。

從以上步驟可以看出,由于FP-Growth算法隻需要對資料全集做兩次掃描,(第一次統計1項集次數,第二次建立初始的FP-TREE),故在算法性能上優于Apriori。

對Apriori和FP-Growth兩種算法進行分析,會發現它們都有一個問題,

隻能做離線計算,不能做線上計算

。原因在于:

1、這兩種算法都

需要對資料進行全掃描以完成裁剪或排序

2、因為每次計算都需要全集掃描,是以

随着資料增長,計算會越來越慢

在一個資料不斷流入的場景下,以上兩個算法是沒有辦法實時計算出事物關聯的。

實時性有多重要呢?想想看,上司來視察,問你最近下雨天流行什麼配什麼:

你指着大螢幕:“哥,看這兒,大資料實時分析的。你看你看,會動哦”。 VS 你撓着頭:“上司等兩小時我給你算算”

請問哪種更Bigger?

啤酒與尿布,咩叔原創基于圖論簡單到爆的實時關聯性算法

為了少俠們更Bigger,老夫要在此獻醜一下,介紹一個當初憋了好幾天想出的算法:“

圖權重算法

“,可以實作線上實時從通路日志中流式抽取資料計算關聯關系(啊,好繞口,但是感覺瞬間Bigger了有沒有?)。

啤酒與尿布,咩叔原創基于圖論簡單到爆的實時關聯性算法

這個算法建立在離散數學中的

上面。但是很顯然,咩叔如此清新脫俗的人物肯定不講離散數學(又不是寫論文,堅決不講那一大堆理論)。

我們還是講純潔的同學關系。

啤酒與尿布,咩叔原創基于圖論簡單到爆的實時關聯性算法

有少俠發現沒有,在介紹FP-Growth算法的時候,我們把這張二維表中的資料處理成了這個樣子:

啤酒與尿布,咩叔原創基于圖論簡單到爆的實時關聯性算法

這種形态是不是比二維表更容易讓人了解?

但是PF-Tree的形态對人不是最友好。看看,“波多醬“出現了兩個節點,假如樹上節點一多,豈不是要把人看精分了。

是以,我們要把“樹“變成”圖“。看老夫施法:

啤酒與尿布,咩叔原創基于圖論簡單到爆的實時關聯性算法

 “樹”變成了“圖”,有何不同?仔細看看:

首先,原先樹中分裂了的“波多醬”和“小澤醬”恢複了,在圖中,一個項就是一個節點。當然,每一個節點的計數器也恢複了,展現了這個節點真正的絕對支援度計數。

其次,節點間的線多了,“小澤醬”節點引出了三條線——這是實際資料的展現,在資料樣本中,小澤醬就是和另外三個女同學有關聯。

最後,節點間的線上有了數字,比如“波多醬”和“沖田醬”之間的線上,數字為2,說明波多醬與沖田醬同時出現了2次。

簡言之,

在“圖”中,真實的展現了項之間的關系

同樣的條件:最小支援度min_sup=0.4   最小置信度min_conf=0.7

讓我們試試從這張圖中找出“波多醬”的好姐妹。

1、波多醬本身的絕對支援度=2,通過驗證。

2、從波多醬引出兩條線,分别是

波多醬——沖田醬

波多醬——小澤醬

我們首先驗證沖田醬與小澤醬本身的支援度是否通過min_sup驗證。啊,耀西!通過。

再看她們之間的關系是否通過min_sup驗證。嗯,遺憾遺憾,波多與小澤之間那根線隻有弱弱的1,少女的羁絆不夠哦。

此輪驗證後隻剩下  波多醬——沖田醬

你看,從“圖”中找關聯是不是很友善,而且是不是更符合“人”的認知習慣呢?

這裡多說幾句:事實上,

這幾年社交網絡的發展,也大量使用了“圖論”的知識

。圖的以下特征:

1、圖含節點與邊;

2、節點中可以有屬性(比如上圖的支援度計數器);

3、邊可以有名字與方向,并可以有屬性(比如上圖中同時出現次數)。

可以輕松衍生出各種“關系”,不僅是社交網絡,從道路系統到電路節點,從供應鍊到組織結構,甚至更多。有興趣的少俠可以深入研究,很有趣哦。

好了,事前準備做完,接下去說說“圖權重算法”怎麼玩了。

有幾個重要思路要說明:

1、關于流式資料的問題。之前舉例的資料樣本是這樣的:

啤酒與尿布,咩叔原創基于圖論簡單到爆的實時關聯性算法

其實這份資料不是原始資料,已經經過處理歸納。

在真實的線上環境中,你不會知道一個事務(比如使用者的商品浏覽行為)何時結束

,是以根本無法基于全資料集做統計。線上環境中,我們的資料結構是這樣的:

日志流水号 事務ID
4
5
6
7
8
9
10
11

解釋一下這個資料結構:

資料是實時不斷流入的,根本不知道一個事務何時完成

,原先經過彙總的 事務1={波多醬,沖田醬} 

這種形式根本不存在。在流式資料中,每一條記錄中隻包含事務中的一個項。

2、從表中資料排列也能看出來,

現實中資料是多并發,不斷流入的

,是以不存在“一個會話中的項都排在一起”的情況,

資料是打亂無序的 要在這些不斷流入,無序的資料中實時計算出關聯規則,是以算法天生就必須做到“不對資料集做任何 統計、裁剪、排序 操作”
啤酒與尿布,咩叔原創基于圖論簡單到爆的實時關聯性算法

Mission impossible?不會的啦。事實上整個算法秉承了咩叔一貫的“簡單粗暴,直接有效”風格,簡單的不可思議呦,少俠。

接下去我們繼續用一個示例說明。

啊,等一下!在與美少女一起做作業前,難道不需要

準備一些必備的東西

麼,你懂的,對吧!

啤酒與尿布,咩叔原創基于圖論簡單到爆的實時關聯性算法

是以,我們要準備兩個資料結構,你肯定也想到了,是吧,

你想的果然也是資料結構,是吧少俠?

我們要準備的兩個資料結構,一個是圖,另一個是一張HashMap表。

圖不用多說,我們的算法就是基于圖的。

HashMap表用來做甚?做鍵值對存儲。<key=事務ID , Value=事務中項集合>,比如 <key=1,Value={波多醬,沖田醬}>。

準備以上好兩個資料結構後,說明一下資料處理流程。

資料如流水,一去不回頭啊…啊,扯遠了扯遠了。資料是一行行傳入的,每一行資料傳入為一次處理流程。

假設傳入資料為:

事務ID=TX,項=IX

  處理流程步驟為:

1、首先在HashMap表中檢查,是否有key=TX 的鍵值對存在:

若不存在,則建立鍵值對 <key=TX,Value={IX}>,轉入步驟2;

若存在,則檢查IX是否已經包含在Value中項集合内。若是,則此次處理流程結束。若否,轉入步驟2。

(注意:這裡“檢查IX包含在項集合中後即退出”,其用意在于“

一個事務中同樣的項不管出現多少次,都隻做一次計算

”。想想看,一個使用者對一個商品瘋狂點贊,難道說明所有人都喜歡這個商品?)

2、判斷項IX是否已經在圖中存在節點:

若不存在,則直接在圖中建立IX節點,并設“支援度屬性值”=1,此次處理流程結束。

若存在,則設定節點IX“支援度屬性值”+1,進入步驟3

3、在圖中,節點IX需要與事務TX項集中其他項對應的節點分别進行關系判斷,看是否已經建立了邊連接配接。假設TX中已有項IY,則需要在圖中判斷IX節點是否與IY節點之間已經建立邊:

若尚未建立邊,則建立之,并設邊的“同時出現屬性值“=1,轉入步驟4。

若已經建立邊,則設邊的“同時出現屬性值”+1,轉入步驟4。

4、将IX加入HashMap中key=TX的項集合中去。

嗯,以上步驟400字,還是加了很多解釋的。當年咩叔論文中阿爾法貝塔的,才用了200字,簡單吧,哦呵呵呵。

啤酒與尿布,咩叔原創基于圖論簡單到爆的實時關聯性算法

明白明白,老夫沒忍住…少俠請收起鐵拳,我們說人話。

恩啊,讓我們一步一步一步的分析和美少女做作業的純潔行為吧…

啤酒與尿布,咩叔原創基于圖論簡單到爆的實時關聯性算法
日志1 資料:事務ID=1,項=波多醬

處理流程如下:

步驟1

首先我們檢查HashMap,是否存在Key=1的鍵值對。

哦,沒有。是以我們建立一個<key=1,Value={波多醬}>,而後轉入步驟2

步驟2

圖中沒有“波多醬”節點,是以直接在圖中建立“波多醬”節點,并将“支援度“屬性值設定為1。

流程處理結束。

-------------------------------------------------------------------------- 日志2 資料:事務ID=2,項=沖田醬

處理步驟與日志1毛一樣,不羅嗦了。

日志1、2處理完畢後,資料結構中内容如下:

啤酒與尿布,咩叔原創基于圖論簡單到爆的實時關聯性算法
日志3 資料:事務ID=1,項=沖田醬

發現已經有key=1的鍵值對,但是項集合中沒有”沖田醬”,是以我們要轉入步驟2。

發現圖中已經存在“沖田醬”節點,是以将其“支援度“屬性值設定+1,進入步驟3。

步驟3

發現事務1項集中已經存在“波多醬”項,

同一事務中的姐妹要有羁絆哦

!是以我們在圖中的“波多醬”和“沖田醬”節點之間建立了一條邊,并設這條邊的“同時出現“屬性值為1,轉入步驟4。

步驟4

将“波多醬“加入事務1的項集中,此時鍵值為<key=1,Value={波多醬,沖田醬}>,流程處理結束。

日志3處理完畢後,資料結構中内容如下:

啤酒與尿布,咩叔原創基于圖論簡單到爆的實時關聯性算法

進行到這一步,少俠們想必已經明白處理步驟了吧。老夫就不堆字了。少俠請自行嘗試一番。

最終結果應該是這樣

啤酒與尿布,咩叔原創基于圖論簡單到爆的實時關聯性算法

各位少俠請看,在這個算法中,果然沒有全局掃描,也沒有統計和排序吧。相比它的兩位前輩,可以說在運算資源上是輕量級的,

非常适合做線上計算

以上僅僅是介紹了算法的基本思路和步驟。如果有少俠感興趣想試試,有幾個建議:

一、算法中兩處關鍵點的實作:

1、傳入一個項時需在HashMap中判斷是否已在事務中出現過

建議用鍵值對資料庫,比如Redis實作。當然直接用Java等進階語言自帶的HashMap也無不可,但

Redis的優勢在于資料可以持久化,可以有效避免在系統重新開機後對曆史資料再做一次全加載

2、需要判斷項是否在圖中存在節點,節點間是否有邊,以及從某一個節點出發尋找邊“同時出現”屬性大于門檻值的相關節點等圖操作。

可以使用

圖資料庫Neo4j

解決。這個産品是專門應對圖論而開發的,對各種“圖”相關的操作十分簡單

并且建立了類似SQL語言的Cypher語言操作資料,學習成本很低。

二、算法存在缺點以及應對方式:

1、假如存在大量頻繁度很低的項,就會在圖中生成大量沒啥毛用的節點;

2、一次事務中有K項,則在圖中K個節點間需要建立K(K-1)/2條邊,K值大的時候,想想蜘蛛網吧;

3、算法中資料處理是串行的,一旦大量日志湧入,性能瓶頸就将出現。

這些缺陷可以在實際進行中這樣靈活避免:

1、實際生活中,大多數事務中不會包含太多項(包含大量項的一般是爬蟲哦少俠),是以可以設定一個門檻值,一個事務最多存儲K個項,多餘的丢棄。

2、對圖中節點定時做清理,去掉一些長期不動的無價值低頻繁度項,去掉相對支援度太低的邊。

3、在日志流傳入的時候做一些控制,限制每秒處理數量,防止把圖處理服務給累死。

聲明:

為避免神聖的論文抽檢系統找我麻煩,在此說明,此博文作者與複旦大學16222010099學生為同一人,“圖權重算法”為作者原創,不管論文還是博文均無抄襲行為。