推薦系統(個人小結)

推薦系統

最近在看公司的舊的推薦系統的,可能沒有spark的als過濾好,但是我覺得蠻有特點,這個用來記錄一下的

從HDFS中獲取數據源

APP的數據格式:

    df_log = df_log
                .filter(
                        df_log.col("page_id").isin(appPageId.toArray())
                )
                .filter(
                        df_log.col("context_id").isNotNull()
                );
        // 使用deviceID作爲USER_ID。並構造ITEM_ID:CITY_CHANNEL_LISTID
        df_log = df_log.selectExpr("cast (device_id as string) as USER_ID",
                "concat(city,'_',context_id) as ITEM_ID");

        df_log = df_log.filter(df_log.col("USER_ID").isNotNull())
                .filter(df_log.col("ITEM_ID").isNotNull());
        df_log = df_log.dropDuplicates();
USER_ID ITEM_ID
device_id city_contextid

WEB的數據格式:

 df_log = df_log.filter(df_log.col("ga_channel").isin("newhouse", "villa"))
                .filter(df_log.col("ga_contextid").isNotNull());

        // 使用GUID作爲USRE_ID。並構造ITEM_ID:CITYID_CHANNEL_LISTID
        df_log = df_log.selectExpr("cast (guid as string) as USER_ID",
                "concat(cityid,'_',ga_contextid) as ITEM_ID");

        df_log = df_log.filter(df_log.col("USER_ID").isNotNull())
                .filter(df_log.col("ITEM_ID").isNotNull());
        df_log = df_log.dropDuplicates();
USER_ID ITEM_ID
guid cityid_ga_contextid

針對spark的datafram進行處理

從上面可以看出,這些數據時日誌數據,並且數據是一一對應的,所以生產對應的JavaPairRDD<String, String> pairRDD

分別求出其中的userid和iemid,並且生產userid對應的行索引、itemid對應的列索引。

spark的廣播,廣播變量可以讓程序高效地向所有工作節點發送一個較大的只讀值,以供一個或多個Spark操作使用

從而生成兩個廣播參數

userIndexBiMap itemIndexBiMap uiRDD
(USER_Id,rowindex) (ITEM_Id,colindex) (rowindex,colindex)

後面會經常用到這三個參數,前兩個值是沒有重複的,後面的一個值是在日誌裏面的信息

svd相似性計算

svd是deep learning上面非常基礎,也是非常重要的一個內容,我也花費了大量的時間學習和整理linear algebra.到現在還不是很清楚,後期我會整理一下的。

spark MLlib 核心基礎:向量 and 矩陣
CoordinateMatrix 是通過RDD[MatrixEntry]實例創建,MatrixEnry是(long,long,Double)形式。座標矩陣可以轉化爲IndexedRowMatrix

通過上面的uiRDD 生產評分矩陣,存在對應的關係的話,在矩陣中賦值1. 就形成了簡單的一個矩陣中值只有1和0
的座標矩陣。

rows indexed rows of this matrix param,nRows number of rows,A non-postive value means unknown, and then the number of rows will be determinded by the max row index plus one param.nClos number of columns. A non-postive value means unknown, and then the number of columns will be determined by the size of the first row

上面是indexedRowMatrix說明

compute the singular value decompostion of this indexedRowMatrix, Denote this matrix by A(m*n),this will compute matrices U S V such that A=U*S*V^T
the cost and implemenation of this method is identical to that in RowMatrix with the addition of indices
At most k largest non-zero singular values and associated vectors are returned, if there are k such values,then the dimensions of the return will be
Parameters: k- number of singular values to keep, we might return less than k if there are numerically zero singular values
Parameters computeU - whether to compute U
Parameters rCond - the reciprocal condition number. All singular values smaller than rCond*sigma(0)are threated as zero, where sigma(0) is the largest singular value
SingularValueDecomposition(U, s, V)

上面是spark的computeSVD

column-major dense matrix,the entry values are stored in a single array of doubles with columns listed in sequence.

上面是DenseMatrix,其實核心就是轉置矩陣

從而得到UsV中的V的值,然後將矩陣V轉置. 爲後期的推薦提供轉置後的矩陣V。

如果推薦的類型是猜你喜歡推薦,則將userRSIDIndexBiMap,itemRSIDIndexBiMap,computer,uiRDD直接保存在文件中。

構建過濾器

根據推薦的類型設置,過濾器,對結果進行篩選。猜你喜歡的有兩個過濾條件:

  • 推薦的條數
  • 對自己的過濾,主要是看推薦的結果中是否有重複的item

構建jaccard推薦器

    public JaccardItemRecommender(
            JavaSparkContext sc,
            BiMap<String, Integer> userRSIDIndexBiMap,
            BiMap<String, Integer> itemRSIDIndexBiMap,
            SVDItemSimilarityComputer computer,
            CandidateFilter filter,
            JobConfiguration jobConf) {
        this.sc = sc;
        this.computer = computer;
        this.jobConf = jobConf;
        this.filter = filter;
        this.userRSIDIndexBiMap = userRSIDIndexBiMap;
        this.itemRSIDIndexBiMap = itemRSIDIndexBiMap;
    }

最核心的推薦算法recommend

  • 構建constructItemBiMap,通過查詢數據提取房源對應的數據,sql如下:select WP.PRJ_ID as prjId, CI.CITY_ID_WEB_IP as cityId,CI.CITY_NAME as cityName, CI.CITY_KEY as cityKey, WC.ITEMNAME as name, WP.PRJ_LISTID as listId,WC.CHANNEL as channel, WP.PRJ_DIST as dist,WP.PRJ_BLOCK as block,WP.MAP_X as mapx, WP.MAP_Y as mapy,WC.PRICE as price,WC.PRICE_MORE as priceMore, WC.SALESTAT as salestats from dwb_web_w_channel WC inner join dwb_web_project WP on WC.PRJ_ID = WP.PRJ_ID inner join dwd_city_info CI on WP.PRJ_CITY = CI.CITY_ID where WP.prj_disp = 1 and salestat=3
變量名 indexItemBiMap
參數 (cols,Item)
Item的實體類
private int prjId;
private int cityId;
private String cityName;
private String cityKey;
private int listId;
private String name;
private int channel;
private int dist;
private int block;
private String mapx;
private String mapy;
private int price;
private String priceMore;
變量名 indexItemBiMap
參數 (colsindex, Item)

- ratings.groupBy(new Functors.GroupByItem())
通過spark的groupBy 將itemid的colsindex提煉出來,
參數樣式:colsindex:(rowsindex,colsindex),(rowsindex,colsindex) 相同的colsindex

變量名 ratingsGroupByItem
參數 (colsindex,[(rowsindex,colsindex),(rowsindex,colsindex)…])

- numVisiterPerItem 就是後面的list計數colsindex:the number of colsindex

變量名 numVisiterPerItem
參數 (colsindex,the number of colsindex)

- ratingsWithNumVisiter 參數的格式爲rowsindex,colsindex,the number of colsindex

變量名 ratingsWithNumVisiter
參數 (rowsindex,colsindex,the number of colsindex)

- ratingsWithNumVisiterKeyByUser 參數的格式爲rowsindex:(rowsindex,colsindex,the number of colsindex)

變量名 ratingsWithNumVisiterKeyByUser
參數 rowsindex:(rowsindex,colsindex,the number of colsindex)

- ratingsWithNumVisiterKeyByUser 參數的格式爲
<ITEM_A,ITEM_B> -> <ITEM_A_COUNT, ITEM_B_COUNT,COMMON_COUNT>

變量名 ratingsWithNumVisiterKeyByUser
參數 (itema_colsindex),(itemb_colsindex)->(itema_colsindex_count),(itemb_colsindex_count),(common_count)

狹義jaccar相似度,計算兩個集合之間的相似程度,元素的取值爲0或1。

對於集合A和B,Jaccard相似度計算如下:Jaccard(A,B)=|A intersect B|/|A union B| 相似度數值在[0,1]之間

  • jaccardSimilarityEntries先求出沒有關聯的數據,userid,針對沒有關聯出來的數據,賦值,數據格式爲(rowsindex,0,0). 這樣的話,我們就得到一個矩陣,矩陣的左邊都是房源,房源值是他們之間的相似度。
  • Functors.recommend 是在spark中的推薦核心算法
變量名 rowMatrix indexItemBiMapBroadcast filter svdComputer recommendNum
參數 (itemA,itemB,score) Integer, Item 過濾器 svd的算法 推薦的條數

算法的原理是:

  • 先將userid和city_ga_context從行爲記錄中提煉出來的,是一對一對的。
  • 給userid和city_ga_context去重,並賦予行索引和列索引
  • 這個是爲了計算svd(這兒還不是很清楚)[爲後面服務的]
  • 後面用rowsindex表示userid,colsindex表示itemid。
    這兒我們就得到一張表
xxx itemA itemB itemC
userA
userB
userC

- 在行爲記錄中,我們以item爲維度,groupby。這樣我們就得到了item有多少次的訪問記錄

user item the number of viewing
userA itemA number
userB itemB number
userC itemC number

- 通過user,自己關聯,將同一個用戶瀏覽過的item通過userid關聯在一起形成了

變量名 樣式
參數 (itema_colsindex),(itemb_colsindex)->(itema_colsindex_count),(itemb_colsindex_count)

- 然後對於這個itemA 和itemB的key值 進行累加得到一個common_count,記錄下來

變量名 樣式
參數 (itema_colsindex),(itemb_colsindex)->(itema_colsindex_count),(itemb_colsindex_count),(common_count)

我們由上面的數據,繪製出一個表數據:

xxx itema itemb
….
itema jaccard_score
….
itemb jaccard_score
….

以上的數據,我們已經將userid去掉了,然後我們表數據一行中的每一列的數據進行計算,如果存在jaccard_score,則直接使用jaccard_score.如果沒有的話,我們會使用svd的來計算這個值。

  • 這樣我們就計算出,每個item的相關性最高的幾個item。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章