==22基于Spark機(jī)器學(xué)習(xí)跟實時流計算的智能推薦系統(tǒng)

基于Spark機(jī)器學(xué)習(xí)和實時流計算的智能推薦系統(tǒng) - 小黑 - 博客頻道 - CSDN.NET
http://blog.csdn.net/qq1010885678/article/details/46675501

概要:
隨著電子商務(wù)的高速發(fā)展和普及應(yīng)用,個性化推薦的推薦系統(tǒng)已成為一個重要研究領(lǐng)域。 個性化推薦算法是推薦系統(tǒng)中最核心的技術(shù),在很大程度上決定了電子商務(wù)推薦系統(tǒng)性能的優(yōu)劣,決定著是否能夠推薦用戶真正感興趣的信息,而面對用戶的不斷提升的需求,推薦系統(tǒng)不僅需要正確的推薦,還要實時地根據(jù)用戶的行為進(jìn)行分析并推薦最新的 結(jié)果。 實時推薦系統(tǒng)的任務(wù)就是為每個用戶,不斷地、精準(zhǔn)地推送個性化的服務(wù),甚至到達(dá)讓用戶體會到推薦系統(tǒng)比他們更了解自己的感覺。
本文主要研究的是基于模型的協(xié)同過濾算法—ALS以及實時推薦系統(tǒng)的可行性并詳細(xì)講解ALS(交替最小二乘法)的思想 然后在Spark Streaming框架上運用ALS算法進(jìn)行測試,評估實時推薦中算法的可靠性 最后,在Spark Mllib和Streaming框架上構(gòu)建了實時推薦引擎,將推薦數(shù)據(jù)保存在Hbase中,WebApp通過讀取Hbase中的推薦數(shù)據(jù)來向用戶展示推薦結(jié)果
關(guān)于其他類別的推薦算法就不細(xì)說了,網(wǎng)上有很多的資料查看,推薦幾篇文章: IBM-探索推薦引擎內(nèi)部的秘密系列
以及向亮的《推薦系統(tǒng)實踐》 下載地址
下面進(jìn)入正文
基于矩陣分解的協(xié)同過濾算法–ALS:
基于模型的協(xié)同過濾推薦就是基于樣本的用戶喜好信息,訓(xùn)練一個推薦模型,然后根據(jù)實時的用戶喜好的信息進(jìn)行預(yù)測,計算推薦。
對于一個users-products-rating的評分?jǐn)?shù)據(jù)集,ALS會建立一個userproduct的mn的矩陣(其中,m為users的數(shù)量,n為products的數(shù)量),如下圖:

這里寫圖片描述

這個矩陣的每一行代表一個用戶 (u1,u2,…,u9)、每一列代表一個產(chǎn)品 (v1,v2,…,v9)。用戶隔天產(chǎn)品的打分在 1-9 之間。 但是在這個數(shù)據(jù)集中,并不是每個用戶都對每個產(chǎn)品進(jìn)行過評分,所以這個矩陣往往是稀疏的,用戶i對產(chǎn)品j的評分往往是空的 ALS所做的事情就是將這個稀疏矩陣通過一定的規(guī)律填滿,這樣就可以從矩陣中得到任意一個user對任意一個product的評分,ALS填充的評分項也稱為用戶i對產(chǎn)品j的預(yù)測得分 所以說,ALS算法的核心就是通過什么樣子的規(guī)律來填滿(預(yù)測)這個稀疏矩陣 它是這么做的: 假設(shè)mn的評分矩陣R,可以被近似分解成U(V)T U為md的用戶特征向量矩陣 V為nd的產(chǎn)品特征向量矩陣((V)T代表V的轉(zhuǎn)置) d為user/product的特征值的數(shù)量
關(guān)于d這個值的理解,大概可以是這樣的: 對于每個產(chǎn)品,可以從d個角度進(jìn)行評價,以電影為例,可以從主演,導(dǎo)演,特效,劇情4個角度來評價一部電影,那么d就等于4 可以認(rèn)為,每部電影在這4個角度上都有一個固定的基準(zhǔn)評分值 例如《末日崩塌》這部電影是一個產(chǎn)品,它的特征向量是由d個特征值組成的 d=4,有4個特征值,分別是主演,導(dǎo)演,特效,劇情 每個特征值的基準(zhǔn)評分值分別為(滿分為1.0): 主演:0.9 導(dǎo)演:0.7 特效:0.8 劇情:0.6 矩陣V由n個productd個特征值組成
對于矩陣U,假設(shè)對于任意的用戶A,該用戶對一部電影的綜合評分和電影的特征值存在一定的線性關(guān)系,即電影的綜合評分=(a1
d1+a2d2+a3d3+a4d4) 其中a1-4為用戶A的特征值,d1-4為之前所說的電影的特征值
那么對于之前ALS算法的這個假設(shè) m
n的評分矩陣R,可以被近似分解成U(V)T 就是成立的,某個用戶對某個產(chǎn)品的評分可以通過矩陣U某行和矩陣V(轉(zhuǎn)置)的某列相乘得到
那么現(xiàn)在的問題是,如何確定用戶和產(chǎn)品的特征值?(之前僅僅是舉例子,實際中這兩個都是未知的變量) 采用的是交替的最小二乘法
這里寫圖片描述

在上面的公式中,a表示評分?jǐn)?shù)據(jù)集中用戶i對產(chǎn)品j的真實評分,另外一部分表示用戶i的特征向量(轉(zhuǎn)置)
產(chǎn)品j的特征向量(這里可以得到預(yù)測的i對j的評分) 用真實評分減去預(yù)測評分然后求平方,對下一個用戶,下一個產(chǎn)品進(jìn)行相同的計算,將所有結(jié)果累加起來(其中,數(shù)據(jù)集構(gòu)成的矩陣是存在大量的空打分,并沒有實際的評分,解決的方法是就只看對已知打分的項)
但是這里之前問題還是存在,就是用戶和產(chǎn)品的特征向量都是未知的,這個式子存在兩個未知變量
解決的辦法是交替的最小二乘法 首先對于上面的公式,以下面的形式顯示:
這里寫圖片描述
為了防止過度擬合,加上正則化參數(shù)
這里寫圖片描述

這里寫圖片描述

首先用一個小于1的隨機(jī)數(shù)初始化V 根據(jù)公式(4)求U 此時就可以得到初始的UV矩陣了,計算上面說過的差平方和 根據(jù)計算得到的U和公式(5),重新計算并覆蓋V,計算差平方和 反復(fù)進(jìn)行以上兩步的計算,直到差平方和小于一個預(yù)設(shè)的數(shù),或者迭代次數(shù)滿足要求則停止 取得最新的UV矩陣 則原本的稀疏矩陣R就可以用R=U(V)T來表示了
ALS算法的核心就是將稀疏評分矩陣分解為用戶特征向量矩陣和產(chǎn)品特征向量矩陣的乘積 交替使用最小二乘法逐步計算用戶/產(chǎn)品特征向量,使得差平方和最小 通過用戶/產(chǎn)品特征向量的矩陣來預(yù)測某個用戶對某個產(chǎn)品的評分
算法原理講述完畢,接下來進(jìn)行算法測試
算法測試:
算法測試分為兩部分: 一、測試最佳的參數(shù),如:隱性因子個數(shù),正則式等 二、測試在Streaming框架上算法的可用性
測試數(shù)據(jù)集來自MovieLens
測試一: 將整個數(shù)據(jù)集上傳至HDFS中 在spark程序中讀取ratings.dat文件,并隨機(jī)劃出80%作為訓(xùn)練數(shù)據(jù)集,20%作為測試數(shù)據(jù)集
設(shè)置隱性因子、正則式參數(shù)列表(由于物理機(jī)配置不好,集群能夠支持的最大迭代次數(shù)只有7次,在多就會內(nèi)存溢出,所以這里直接將迭代次數(shù)設(shè)置為7)
對參數(shù)列表的全排列分別進(jìn)行模型訓(xùn)練,并計算MSE、RMSE
結(jié)果如下圖:
這里寫圖片描述

比較得出最佳的參數(shù)組合,以后的模型訓(xùn)練參數(shù)都使用這個參數(shù)組合
測試二:
將原本的數(shù)據(jù)劃分為三部分 trainingData-10k testData-10k 剩下的為streamData,作為流數(shù)據(jù)實時發(fā)送 首先將trainingData、testData上傳到HDFS/data目錄下 在spark程序中讀取,并轉(zhuǎn)化為RDD[Rating]類型 使用Streaming框架接受流數(shù)據(jù),并進(jìn)行在線模型訓(xùn)練 每訓(xùn)練一次就計算一次MSE和RMSE 對比模型的精準(zhǔn)性有沒有提高
使用Scala讀取本地的streamData,通過Socket發(fā)送到spark程序中
結(jié)果如下圖:
隨著數(shù)據(jù)的不斷增加,模型的精準(zhǔn)度在不斷的提高,所以實時的更新推薦模型是可行的
推薦系統(tǒng)整合:
整體流程圖:
這里寫圖片描述

首先用程序生成用戶和圖書數(shù)據(jù),并隨機(jī)模擬用戶行為數(shù)據(jù),保存在Hbase中
在Hbase數(shù)據(jù)庫中包含了用戶表(4000個用戶),圖書表(5060本圖書)以及評分表(用戶對圖書的百萬條數(shù)據(jù)) 由于對個人來說無法得到真實的商業(yè)性數(shù)據(jù),故評分?jǐn)?shù)據(jù)都是程序 模擬隨機(jī)生成的,包括實時發(fā)送的流數(shù)據(jù),所以這可能會對整個系統(tǒng)的推薦結(jié)果帶來影響
另外,除了WebUI部分,其余的程序都是運行在Linux的Spark集群上
原始數(shù)據(jù)通過一個程序不斷地向Hbase的評分表中寫入數(shù)據(jù) 模擬用戶在網(wǎng)站上的評分行為 運行截圖:

其中,前300個用戶的行為偏向于前600本圖書(計算機(jī)相關(guān)) 實時流數(shù)據(jù)將通過另外一個程序發(fā)送Socket數(shù)據(jù),模擬用戶當(dāng)前在網(wǎng)站上的實時評分行為 在最后使用用戶進(jìn)行觀察測試時,程序?qū)荒M這個用戶的評分行為以便觀察推薦系統(tǒng)的實時性
首先推薦引擎會讀取Hbase中的評分?jǐn)?shù)據(jù) 并使用算法測試時得到的最佳參數(shù)組合來對其進(jìn)行訓(xùn)練 得到初始的模型 使用這個模型對Hbase中所有用戶進(jìn)行圖書推薦(取 top10) 并將推薦結(jié)果保存在Hbase中 以上階段為系統(tǒng)初始化階段 運行截圖:

這里寫圖片描述
這里寫圖片描述

這里寫圖片描述

在系統(tǒng)初始化完成之后,開啟實時推薦引擎 接收不斷生成的用戶行為數(shù)據(jù),并和Hbase中的原始數(shù)據(jù)混合,訓(xùn)練出新的模型,產(chǎn)生推薦結(jié)果保存 不斷地進(jìn)行流數(shù)據(jù)的讀取、訓(xùn)練和保存推薦結(jié)果,直至系統(tǒng)關(guān)閉或者無流數(shù)據(jù)產(chǎn)生 推薦引擎運行如下圖:
這里寫圖片描述

WebUI部分:
WebUI是由ASP.NET開發(fā)的一個簡單的B/S應(yīng)用,通過Thrift和Linux中的Hbase交互 選擇使用一個用戶觀察系統(tǒng)的實時推薦性,此時流數(shù)據(jù)模擬程序只產(chǎn)生這個用戶的評分行為 不同時刻,在該用戶有行為數(shù)據(jù)產(chǎn)生的情況下,推薦的內(nèi)容(細(xì)節(jié)沒有仔細(xì)處理,比如有的圖片找不到路徑等。。。): 當(dāng)前記錄
這里寫圖片描述
這里寫圖片描述

新的行為數(shù)據(jù)產(chǎn)生的記錄
這里寫圖片描述
這里寫圖片描述

總結(jié):
前前后后大概花了兩個禮拜多一點的時間(畢竟還要顧著上課,基本也就是晚上才有時間) 其中遇到了許多坑,上網(wǎng)找過,請人問過,也上過知乎啥的讓大牛指導(dǎo)過
總之一句話,沒有真正動手做過是不會知道其中的艱苦,當(dāng)然我早就變態(tài)的把它當(dāng)樂趣來看了
原本的設(shè)想是使用聯(lián)合聚類+ALS矩陣分解來做的,但是試了一下,聯(lián)合聚類貌似不想k-means啥的那么簡單,以自己的水平來說暫時無法實現(xiàn)(還是要怪自己基礎(chǔ)不好咯),遂放棄之
之后又有一個美好的想法,通過ItemCF、UserCF、關(guān)聯(lián)規(guī)則、ALS等算法組合起來,形成一個混合的模型,畢竟這種模式才是比較接近商業(yè)化的構(gòu)架,但是在Spark上面調(diào)用Mahout算法的時候又出現(xiàn)了各種各樣的問題,有時候甚至編譯都不通過。。。
在推薦算法性能測試的時候,自己實現(xiàn)了召回率,準(zhǔn)確率,覆蓋率,多樣性,新穎度等指標(biāo)的計算方式,但是實際測試時總是飆出莫名其妙的數(shù)據(jù)。。。
另外,使用ALS進(jìn)行實時訓(xùn)練模型的時候,每次都要重新訓(xùn)練,感覺這是一個優(yōu)化點,可否修改成接受到新數(shù)據(jù)之后不重復(fù)訓(xùn)練,只計算新來的數(shù)據(jù)(水平有限,暫時只是想法)
期末考又臨近了,只好先放下這些不成器的東西以后再研究
最后的最后,無奈之下只能實現(xiàn)了一個最簡單的推薦系統(tǒng)
最后附上所有源代碼和簡要記錄的開發(fā)日志
源代碼已打包上傳: 下載地址 (代碼有些凌亂,沒來得及重構(gòu),僅僅做了基本的注釋,有需要的童鞋不要介意。。。)
開發(fā)日志:
6-9:準(zhǔn)備book數(shù)據(jù)到hbase中。上傳到hdfs中文亂碼(Docker中),讀取hdfs數(shù)據(jù)到hbase中出異常(原因:數(shù)據(jù)格式不對,內(nèi)容太多超出一行,仔細(xì)看日志;scala輸入hbase異常)
6-10:完成t_users,t_books,t_ratings的數(shù)據(jù)導(dǎo)入
6-12:scala操作scan hbase表 坑位: 1:resultScaner不能直接for循環(huán) 2:spark上操作hbase 第一次簡單測試(按照之前的過程) offset (0) + length (4) exceed the capacity of the array: 2 使用String 3:Streaming接收socket數(shù)據(jù)測試 4:Streaming執(zhí)行內(nèi)容測試
6-13:實時推薦測試 問題記錄:不能同時運行兩個sparkcontext 解決:使用sparkContext來創(chuàng)建StreamingContext Streaming的處理方式 socketTextFile無法接受數(shù)據(jù)—logger缺少換行符 foreachRDD理解 完成實時更新模型
6-14:namenode經(jīng)常莫名掛掉,重新配置虛擬機(jī) ubuntu下hostname默認(rèn)為ubuntu所以一直無法正確啟動–修改/etc/hostname 重啟
6-15:SparkStreaming實時讀取更新模型老是拋異常 解決:allData.cache(沒有緩存的話之前的流數(shù)據(jù)丟失無法找到)
Unable to reconnect to ZooKeeper service, session 0x14df6b4bcdb0009 has expired, closing socket connection/ Socket connection established to localhost/127.0.0.1:2181, initiating sessio 解決:在代碼中設(shè)置hbase的zk,配置文件中無效
6-16:解決15鈤的問題 allData.repartition(3).cache 更新模型時連接到zk異常
WARN [sparkDriver-akka.actor.default-dispatcher-46] storage.BlockManagerMasterActor (Logging.scala:logWarning(71)) - Removing BlockManager BlockManagerId(4, cloud1, 56133) with no recent heart beats: 125833ms exceeds 120000ms 原因:由于網(wǎng)絡(luò)差或者數(shù)據(jù)量太大,worker節(jié)點在一定的時間內(nèi)(默認(rèn)45s)沒有給master信號,master以為它掛了。 解決辦法:修改運行命令或者sprak-env.sh,添加參數(shù) -Dspark.storage.blockManagerHeartBeatMs=6000000(以ms為單位,即6分鐘)。 修改:在此配置中無效,要在代碼中通過SparkConf設(shè)置 Spark1.4中直接通過spark.network.timeout一個配置全部
6-17:完成基礎(chǔ)推薦引擎搭建和測試;c#連接hbase環(huán)境搭建
6-18:spark批量寫hbase性能優(yōu)化 myTable.setAutoFlush(false, false)//關(guān)鍵點1 myTable.setWriteBufferSize(310241024)//關(guān)鍵點2 myTable.flushCommits()//關(guān)鍵點3 關(guān)鍵點1_:將自動提交關(guān)閉,如果不關(guān)閉,每寫一條數(shù)據(jù)都會進(jìn)行提交,是導(dǎo)入數(shù)據(jù)較慢的做主要因素。 關(guān)鍵點2:設(shè)置緩存大小,當(dāng)緩存大于設(shè)置值時,hbase會自動提交。此處可自己嘗試大小,一般對大數(shù)據(jù)量,設(shè)置為5M即可,本文設(shè)置為3M。 關(guān)鍵點3:每一個分片結(jié)束后都進(jìn)行flushCommits(),如果不執(zhí)行,當(dāng)hbase最后緩存小于上面設(shè)定值時,不會進(jìn)行提交,導(dǎo)致數(shù)據(jù)丟失。
注:此外如果想提高Spark寫數(shù)據(jù)如Hbase速度,可以增加Spark可用核數(shù)量。
修改:實際測試中,以上優(yōu)化并沒有起作用,反而會使一下數(shù)據(jù)丟失,沒有繼續(xù)深入測試
完成webapp的基本搭建
6-23:完成算法測試部分,評測指標(biāo)RMSE,MSE,==》(平均值,取不同的n推薦列表畫曲線)召回率,準(zhǔn)確率,覆蓋率,多樣性,新穎度 使用spark1.4 的新api來推薦物品提升效率 在spark-env和default里面的配置無效,在代碼中配置 System.setProperty(“spark.akka.frameSize”, “2000”)
6-24:系統(tǒng)原型完成
6-25:完善系統(tǒng)原型
6-26:論文初稿
參考資料: Spark 下操作 HBase(1.0.0 新 API) 【C#】通過Thrift操作HBase系列(1) ALS 在 Spark MLlib 中的實現(xiàn) 基于矩陣分解的協(xié)同過濾算法

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,578評論 6 544
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,701評論 3 429
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,691評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,974評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 72,694評論 6 413
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 56,026評論 1 329
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,015評論 3 450
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 43,193評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,719評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 41,442評論 3 360
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,668評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,151評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,846評論 3 351
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,255評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,592評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,394評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 48,635評論 2 380

推薦閱讀更多精彩內(nèi)容