翻譯:用R實現序列模式挖掘進行商業推薦指南

      在這份指南中,Allison Koenecke 揭示了當客戶增加Azure雲的服務時,微軟如何通過延伸傳統購物籃分析實現對消費者潛在服務需求的推薦。
     問題聲明:
       Market Basket Analysis (MBA)購物籃分析回答了一個標準的商業問題:通過一組超市的小票,我們可以發現經常一起購買的商品嗎(比如花生醬和果凍)? 假設我們想要提高客戶服務體驗進行挖掘, 比如,確定過去買過花生醬,是否就意味着未來購買麪包的可能性更高。基於此,我們應用了購物籃分析的序列模式,因爲在分析中引入了時間變量,所以有時候又叫 “順序項集挖掘”或“順序模式挖掘”。
序列模式挖掘已經被很多企業應用,從確定病人的醫療處方順序到檢測入侵,如應用層攻擊等方面。在這篇指南中,通過分析一段時間內購買的產品,我們想要明確是否可以找到適合捆綁並樂於被消費者購買的產品,同時也可以檢測這些捆綁產品是如何隨着時間演變的。
 
     在下面的教程中,我們將講解使用 SPADE 算法的R包  arulesSequences ,具體的,根據一個包含歷史用戶購買服務數據的Excel表格,我們產生兩個獨立的Excel表格,一個是服務捆綁名單,一個通過序列模式演示了服務組合是如何隨着時間變化的。通過演示如何使用序列模式做銷售推薦來解釋後一個Excel
 我們下面跑的例子是爲了解決微軟Azure 服務 的銷售人員去跟消費者推薦哪個額外產品的問題, 考慮到客戶目前的雲產品消費服務組合,我們更想知道,那些購買了網絡服務的消費者是否也會在接下來的幾個月購買網站分析, 出於保密原因,實際的Azure服務名稱已經被刪除。
 

第一步:將數據格式化爲事務矩陣

         首先,讓我們導入標準的事務數據然後轉化成如圖一那種示例矩陣,如果交易 是跨列列出的,而不是跨行列出的,只需要使用 R 中的reshape2, data.table, 或者tidyr之一去重新轉置數據即可。
注意轉換爲正確的矩陣格式,最簡單的方式是導出序列到一個臨時txt中,使用 read_baskets中的 arulesSequences  包功能重新導入。
 
 
 
圖1:數據轉化成事務矩陣示例,ServiceLevel 中的字母表示Azure的服務,比如電腦,網路,數據存儲,網站和客戶端等。
# Import relevant packages
library(dplyr)
library(tidyverse)
library(arulesSequences)

#Import standard transaction data
transactions = read.csv("transactions.csv")
# Start time of data to be considered
start_month <- "2015-07-01"
# Create list of Azure services by customer ID and CleanMonth (formatted dates)
trans_sequence <- transactions %>%
    group_by(CustomerID, CleanMonth) %>%
    summarize(
        SIZE = n(),
        ServiceLevel = paste(as.character(ServiceLevel), collapse = ';')
        )

# Make event and sequence IDs into factors
elapsed_months <- function(end_date, start_date) {
    ed <- as.POSIXlt(end_date)
    sd <- as.POSIXlt(start_date)
    12 * (ed$year - sd$year) + (ed$mon - sd$mon)
}
trans_sequence$eventID <- elapsed_months(trans_sequence$CleanMonth, start_month)
trans_sequence = trans_sequence[,c(1,5,3,4)]
names(trans_sequence) = c("sequenceID", "eventID", "SIZE", "items")
trans_sequence <- data.frame(lapply(trans_sequence, as.factor))
trans_sequence <- trans_sequence[order(trans_sequence$sequenceID, trans_sequence$eventID),]

# Convert to transaction matrix data type
write.table(trans_sequence, "mytxtout.txt", sep=";", row.names = FALSE, col.names = FALSE, quote = FALSE)
trans_matrix <- read_baskets("mytxtout.txt", sep = ";", info = c("sequenceID","eventID","SIZE"))

 

第二步 運行spade算法

      我們將使用SPADE(使用等價類的順序模式發現)算法進行序列模式購物籃分析,它由cspade函數調用, 下面的圖2詳細介紹了這種按序列長度遞歸的方法。舉個例子,首先,我們尋找長度爲1的序列(我們需要找到那個獨立出現在我們的交易數據中的Azure 服務)。在完成單長度序列後(比如A 比D出現的頻繁)。我們觀察兩種類型的雙元素序列。
首先,我們觀察雙元素的時間序列(‘B’-> “A”需要B要先於A被購買)然後,我們觀察雙元素的組合(‘AB’要求A和B在某個時間同時存在)然後,基於最頻繁的長度爲2的組合,我們接着尋找3個元素的序列(例如D->B->A)和三元素的組合(比如 ABF).這樣繼續直到我們到達一個用戶定義的最大長度或者達到一個沒有辦法發現更多組合的長度。
接下來,我們將把術語“itemset”稱爲客戶購買的任何產品集合,因此產品集合可以由產品組合(可以是單個產品)或時間序列組成。
圖2:SPADE 算法頻繁序列生成(譯者注:根據客戶id來統計出現頻次,一個用戶多次出現相同組合算1次)
 
 
        我們在描述SPADE算法時多次用了“頻繁”這個詞,這到底意味着什麼?通常有三個不同的術語來衡量 購物籃的頻繁度,這最好的三個衡量指標是:支持度、置信度和提升度。下面是它們的定義:
Support(}): 
     a的支持度:總交易中包含a物品的佔比。高支持度值意味着那些可以在很多交易中應用的常見組合。
support({a})=4/4=1
 
Confidence(} → }): 
       a->b的置信度:a->b的序列組合滿足在a先於b發生這個約束條件下,包含a的集合的子集,置信度可以理解爲條件概率 在給定一個預發生的包含a集合的交易中,越高的置信度意味着在未來購買b的可能性越高,嚴格來說,a->b的置信度=包含a和b的支持度/包含a的支持度  Support({ɑ} and {b}) / Support({ɑ}).
confidence({a}->{b})=Support({ɑ} and {b}) / Support({ɑ})=(3/4)/1=3/4=0.75
 
Lift({ɑ} → {β})
       a->b的提升度:應用序列規則a->b比a和b單獨出現提高購買的程度 。
a->b的提升度=同時包含a和b的支持度/(a的支持度*b的支持度)。Support({ɑ} and {β}) / (Support({ɑ}) * Support({β}))
注意:如果a和b在事件中獨立存在,那麼分母就等於分子,提升度就等於1,當提升度大於1時,意味着現存的a可以增加b在未來的交易中出現的概率。這可以理解爲啊和b之間有強相關。相反的,當提升度小於1時,意味着a和b是負相關關係, 這個指標不僅告訴你什麼是受所有客戶歡迎的,而且告訴你根據客戶的歷史,什麼對他是最有用的(例如:一個低提升度的值可以理解爲b是a的好的替代品)。
 
Lift({ɑ} → {β})=Support({ɑ} and {β})/ (Support({ɑ}) * Support({β})) =(3/4)/(1*1)=0.75
 
 
    回到我們的案例中,回想一下我們的(在第一步創建的trans_matrix)輸入是按月購買Azure服務的順序,只用一行代碼,cspade函數返回按支持程度降序挖掘的頻繁序列。進一步的,爲了減少運行時間,我們可以定義最小支持度限制輸出,在指南的第三部分,下面的代碼中,我們使用0.3這個最小支持度在18個不同序列的案例中應用,我們將明白置信度和提升度是怎樣起作用的。
#Get frequent sequences and corresponding support values
s1 <- cspade(trans_matrix, parameter = list(support = 0.3), control = list(verbose = TRUE))
s1.df <- as(s1, "data.frame")
summary(s1)
 
我們可以在s1.df中查看結果,通過在s1上調用summary函數,進行接下來的分析,特別的,我們關注:
(1)最頻繁的產品集(A,B)
(2)在事件中出現的頻繁產品集(考慮元素)
(3)集合中組合長度的分佈
(4)在序列集合中的產品個數的分佈(考慮序列長度)
(5)最小值,最大值,平均值和中位數
(6)最頻繁序列挖掘,按照支持度排序。
 
 
圖3:cspade算法輸出的樣例展示了18個頻繁的項目集,以及對這些值進行的分析
(例如: 項目A作爲各個項目集的一部分出現了18次中的11次,但是在一個交易中單獨出現只有8次),
注意: 每個序列中集合之間的逗號分隔符意味着時間序列,如圖2所示。

第三步:找到並解釋序列規則

     只需多一行代碼就可以將這組序列轉換爲一組規則。特別的,強關聯規則通常滿足最小支持度和置信度,左項必須在右項之前發生。在這個例子中我們已經設置了最低置信度爲0.5,通常意義上的默認值爲0.8。
# Get induced temporal rules from frequent itemsets
r1 <- as(ruleInduction(s1, confidence = 0.5, control = list(verbose = TRUE)), "data.frame")

返回的數據見圖4.我們可以將rule列解釋爲在接下來的幾個月內,哪些Azure服務包會需要額外的服務。此外,對於所有規則來說,我們可以通過3個維度去比較:支持度,置信度和提升度。

 
圖4 ruleInduction 方法輸出示例
         我們如何理解這個?舉例,當我們看到一個客戶購買服務D之後每一次總會同時購買B和F。這就是圖4的第二行置信度值的含義。回頭看圖1,我們看到會員卡號爲1和4的顧客就是這種情況,同時,提升度爲1.0意味着D被購買的可能性,和B和F稍後被購買的可能性是完全獨立的。所以,我們不能得出購買B和F 是依賴先購買D的基礎之上的。但是這些事件也沒有出現負面的依賴(換句話說, 也不是說用戶之前購買了D,以後就沒有必要再購買B和F了,雖然這個輸出相當簡單,但我們可以做一些簡單的處理,以解析規則的“before”和“after”步驟,並根據特定用例的最重要的度量進行排序。
 
# Separate LHS and RHS rules
r1$rulecount <- as.character(r1$rule)
max_col <- max(sapply(strsplit(r1$rulecount,' => '),length))
r_sep <- separate(data = r1, col = rule, into = paste0("Time",1:max_col), sep = " => ")
r_sep$Time2 <- substring(r_sep$Time2,3,nchar(r_sep$Time2)-2)

# Strip LHS baskets
max_time1 <- max(sapply(strsplit(r_sep$Time1,'},'),length))
r_sep$TimeClean <- substring(r_sep$Time1,3,nchar(r_sep$Time1)-2)
r_sep$TimeClean <- gsub("\\},\\{", "zzz", r_sep$TimeClean)
r_sep_items <- separate(data = r_sep, col = TimeClean, into = paste0("Previous_Items",1:max_time1), sep = "zzz")

# Get cleaned temporal rules: time reads sequentially from left to right

r_shift_na <- r_sep_items
for (i in seq(1, nrow(r_shift_na))){
    for (col in seq(8, (6+max_time1))){
        if (is.na(r_shift_na[i,col])==TRUE){
        r_shift_na[i,col] <- r_shift_na[i,col-1]
        r_shift_na[i,col-1] <- NA
        }
    }
}
names(r_shift_na)[2] <- "Predicted_Items"
cols <- c(7:(6+max_time1), 2:5)
temporal_rules <- r_shift_na[,cols]
temporal_rules <- temporal_rules[order(-temporal_rules$lift, -temporal_rules$confidence,-temporal_rules$support, temporal_rules$Predicted_Items),]
write.csv(as.data.frame(temporal_rules), file = "TemporalRules.csv", row.names = FALSE, na="")
# Get unique frequent itemsets existing in rules (subset of those in s1.df)
baskets_only <- temporal_rules[,1:(ncol(temporal_rules)-3)]
basket_mat <- as.vector(as.matrix(baskets_only))
freq_itemsets_in_rules <- unique(basket_mat[!is.na(basket_mat)])
write.csv(as.data.frame(freq_itemsets_in_rules), file = "FreqItemsetsInRules.csv", row.names = FALSE)

 

 
 
 
圖5:輸出可讀的文件TemporalRules.csv,
FreqItemGroupingsInRules.csv中用列表的形式存儲項集的值     
       現在,我們兩個主要的結果都存在csv文件中, FreqItemGroupingsInRules.csv 和TemporalRules.csv. 總之,我們所關心的所有項目集都將由頻繁的項目分組或時間序列規則來定義。但是,我們如何將這些應用到我們的商業環境中呢?
 
        首先,頻繁項集的分組本身對行業是有價值的,即使忽略B和F的下單順序,知道B 和F經常被一起購買就可以促成很多商業機會,有什麼理由把它們分開銷售? 客戶是否對兩種產品都有需求,把它們揉成一種產品會更好?
       其次,隨着時間的積累, 時間序列規則可以幫我們實現更明確的推薦目標,比如,假設我們看到高置信度和合理的提升度的規則D->{BF}(在我們例子中分數都是1),對於一個購買了D產品的顧客來說,我們可以推薦他們現在購買包含B和F的組合。在未來時間的積累下,假設我們的顧客喜歡這個推薦並且同時購買了B和F.現在,我們可以再考慮時間規則並且發現{BF}->A的規則(我們根據產品被購買的匹配左項和高置信度來選擇右項)現在,我們可以更進一步的在未來某個時間推薦我們的顧客購買A產品。事實上,我們使用圖5被處理過的Excel輸出文件可以更容易的理解這些規則-具體的推薦路徑可以看第四行。這種個性化目標推薦的風格既對我們的顧客有利又對我們的銷售有幫助,隨着收集更多的數據用於置信度和提升度的計算,下一步的推薦將變得越來越精準。
 
 

考慮的事情:

 
        以上步驟顯示了查找實現序列模式的一種高效計算方法;這比使用arules包在每個時間點中查找頻繁項目集,然後在事件維度上手動的比較它們,然後,依靠支持度、置信度和提升度去否決預期的暴力方法快很多, 即使是arulesSequences方法也可能花費大量的計算時間,因此,如果關注的預期是輸出最高分數的規則,那麼在測試低值之前,從高閾值開始可能是更謹慎的做法。
除了頻繁度的界限參數, 產品可測量的聚合程度也值得考慮 ,讓我們假設我們的產品或服務按照層次來銷售,在最少層級上運行SPADE算法將花費更少的時間,因爲該算法將識別更多的重複服務出售給不同的客戶。如果在你想要的特定產品級別上有一個需要很長時間運行的最小界限的需求,考慮在一個更高,產品層次更聚合的級別上運行上面的代碼,然後通過向下鑽取明確在未來哪些是最好的推薦產品。舉個例子,在Azure服務中更高級的產品上(比如分析產品,電腦產品,網頁加移動端產品等等),假設我們發現我們應該推薦分析產品給一個特定的客戶,在進一步驗證之前,可能我們發現基於分析產品的序列規則在更細粒度上推薦機器學習工具包而不是數據湖的產品。因此,我們仍然可以對底層產品提出合理的建議, 而不需要在整個數據集上花費過多的計算時間。
最後,以上的序列模型挖掘代碼有可能不能直接適用,如果你
(1)關心 在任意給定的時間點被購買的項目集的質量( 因爲在本教程中我們只觀察項目集的存在或不存在)或者
(2) 擁有隨時間變化的無規律的數據,但目標是對未來特定時間間隔的預測。在前者中,用單獨的項目名稱對重複項目集進行重新編碼(比如:爲每一個購買集起一個名字)可以提高質量
。在後者中, 最好的做法是使用有規律的時間間隔;這個可以通過對購買產品的分箱來實現,比如按月(如果是在月時間維度上做預測),在銷售系統基礎上,支持修改和反饋0購買是必須的。
         綜上所述, 考慮到財務團隊廣泛使用Excel跟蹤歷史採購, 這種方法提供了一種有效的工具,可以對產品或服務的採用情況進行深入瞭解。 這裏實現的順序模式挖掘可以用來向公司的銷售人員推薦產品,發現顧客接下來會購買什麼,洞察哪些產品組合隨着時間可以持續流行。

參考文獻:

  1. Srikant, R., Agrawal, R., Apers, P., Bouzeghoub, M., Gardarin, G. (1996) "Mining sequential patterns: Generalizations and performance improvements", Advances in Database Technology — EDBT '96 vol. 1 no. 17.
  2. Aileen P. Wright, Adam T. Wright, Allison B. McCoy, Dean F. Sittig, The use of sequential pattern mining to predict next prescribed medications, Journal of Biomedical Informatics, Volume 53, 2015, Pages 73-80, ISSN 1532-0464, https://doi.org/10.1016/j.jbi.2014.09.003.
  3. Song SJ., Huang Z., Hu HP., Jin SY. (2004) A Sequential Pattern Mining Algorithm for Misuse Intrusion Detection. In: Jin H., Pan Y., Xiao N., Sun J. (eds) Grid and Cooperative Computing - GCC 2004 Workshops. GCC 2004. Lecture Notes in Computer Science, vol 3252. Springer, Berlin, Heidelberg.
  4. J. Zaki. (2001). SPADE: An Efficient Algorithm for Mining Frequent Sequences. Machine Learning Journal, 42, 31–60.
  5. Analyzing Transaction Data like a Data Scientist: https://rpubs.com/Mahsa_A/Part4_AnalyzeTransactionData.
原文地址:
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章