天天看點

翻譯:用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   包功能重新導入。      

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

圖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”稱為客戶購買的任何産品集合,是以産品集合可以由産品組合(可以是單個産品)或時間序列組成。

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

圖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)最頻繁序列挖掘,按照支援度排序。  

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

  圖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個次元去比較:支援度,置信度和提升度。

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

  圖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)
           
翻譯:用R實作序列模式挖掘進行商業推薦指南

圖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. Package ‘arulesSequences’ documentation:  https://cran.r-project.org/web/packages/arulesSequences/arulesSequences.pdf.
  5. J. Zaki. (2001). SPADE: An Efficient Algorithm for Mining Frequent Sequences. Machine Learning Journal, 42, 31–60.
  6. Data Mining Algorithms in R:  https://en.wikibooks.org/wiki/Data_Mining_Algorithms_In_R/Sequence_Mining/SPADE.
  7. Analyzing Transaction Data like a Data Scientist:  https://rpubs.com/Mahsa_A/Part4_AnalyzeTransactionData.

原文位址: https://blog.revolutionanalytics.com/2019/02/sequential-pattern-mining-in-r.html

繼續閱讀