2022-07-29
用戶 問題 標簽 向量 可以
用戶畫像
1. 我們在選擇如何存儲用戶標簽時,遇到了問題(標簽查詢速度慢,并且構建不夠靈活,標簽更新和刪除比較麻煩),比如之前用HDFS或者ES存儲,后來切換為ClikcHouse,并用BitMap存儲,原因如下
針對標簽的表示形式,存儲方式有很多,結構為`寬表,BitMap` 都可以,存儲選擇`HDFS,ES,ClickHouse 等` 也都可以,需要衡量的有兩點`1.標簽構建的靈活性和構建速度 2.標簽的查詢效率 ` `HDFS [Presot,Impala]:` 標簽的增加,刪除,更新不友好, 一個小變動,要重寫整個`Parquet`, 寫放大問題。 查詢效率還可以,但是不夠優秀。 支持查詢并發較小。 `ES:`標簽的構建的寫入速度一般, 新增和修改標簽需要對ES文檔結構更新,ES的DSL語法不友好,有一定學習成本。查詢效率還算優秀,同時支持高并發。ES資源占用高,需要較好的硬件配置。 `ClickHouse[BitMap]` 標簽可以并行構建,查詢效率優秀,標簽的增加非常方便,標簽的更新和刪除可以實現,但是并不高效,并發查詢支持比Presto,Impala要好,但同樣不支持高并發,能夠滿足大部分場景需求。注意兩點`1. BitMap存儲的是用戶ID 2. BitMap使用了RoaringBitMap, 解決BitMap空間占用問題,不然1億這一個數也要占用11.9M空間`
2. 如何構建用戶的稠密向量的問題
如果我們直接將用戶的標簽轉換為稀疏向量來存儲,對于類別標簽使用`one-hot`編碼,但這樣會出現維度爆炸的問題,向量過于稀疏,向量之間的余弦相似度計算結果基本沒有意義,根本無法實現用戶相似度的計算。所以就開始思考如何將用戶表示為轉換為稠密向量,經過調研發現,Word2Vec可以將詞轉換為稠密向量,同時借助Word2Vec思想,也可以將物品轉換為向量Item2Vec,比如將一個Session內,用戶購買的物品或者點擊的物品列表,看成是一句話,每個物品看成是一個單詞,就可以借助Word2Vec的思想將物品轉換為稠密向量表示。(這里注意如果是文章,可以使用分詞,然后抽取關鍵詞,將詞通過Word2Vec轉換為向量的方式) ,我們再將用戶點擊或者購買的物品列表中物品向量加和求平均,就可以得到用戶的稠密向量。后來發現通過ALS模型`矩陣分解`的方式也可以得到用戶的稠密向量,兩者`表達的用戶向量含義`是不同的,一個是有濃重的物品屬性特征的,一個是有協同特征的向量。但是都可以作為用戶的向量表示方式。
推薦系統
1. SparkML Pipline 訓練模型通過PMML跨平臺部署時字符串轉向量的問題
由于我們通過Pipline訓練出來的排序模型,模型的輸入是之前存入HBase中向量(用戶和物品)字符串,當我們使用`jpmml-sparkml` 這個類庫去生成PMML模型,進行擴平臺部署時,發現無法正常生成PMML。 原因是因為對于字符串轉向量這種`transformer操作` jpmml沒有支持,我們參照jpmml源碼的實現方式,做了自定義transformer的實現。原理是先自定義一個Spark ML的transform,然后再擴展一個jpmml對應的converter即可。
2. 特征向量Load到HBase慢的問題
我們構建出來的用戶特征向量和物品特征向量,最終是存儲到HBase中的,最初是使用HBase API寫入數據,但是太慢了,整個數據的寫入要耗費5~6個小時,之后我們`使用了bulkLoad的方式`,直接通過使用Spark生成將數據`生成HFile文件`寫入到HDFS,然后使用blukLoad直接生成好的HFile文件mv過去即可,15分鐘完成。 更具體點,首先我們把我們將要寫入hbase的rdd,按照設定的行鍵排序,之后將行鍵和值構造一個HFile的KeyValue結構,設定outputformat 為HFileOutputFormat2,將生成的hfile數據寫入到hdfs,之后通過doBulkLoad方法將寫到HDFS上hfile數據移動到hbase目錄中。(這些項目的代碼中都有)
3. 多路召回結果如何如何統一排序的問題
因為我們采用了多種召回算法,比如ItemCF,ALS, 基于熱門,基于地域 等召回算法。 沒有召回算發的結果集我們是無法直接排序的,因為各個召回算法表達的含義是不同的,最開始不知道該怎么做,因此就是各個召回算法設定一個人為比例去取。 之后學習了解到可以加`一個排序模型`做這個事情,原理就是用戶向量和物品向量作為基礎特征,用戶是否點擊物品作為標簽,訓練一個排序模型(LR),只有將各路召回策略輸入排序模型重新排序即可。 # 注意如果你同時說1,3問題,注意順序
數倉問題
1. Flink Watermark激增的問題
參考:http://coder.yihongyeyan.com/question/7, `里面有watermark 激增的場景說明`。從這上面的我舉的例子,你應該知道這種情況發生的原因,是因為我們抽取事件事件直接減去延遲時間造成,解決方式就是我們再抽取watermark時,判斷一下事件中的時間和上次watermark的時間,如果兩者時間相差很大,我們就不更新watermark或者將watermark加上一個小值就可以了,一般選擇不更新。
2. 實時作業和離線作業的資源競爭問題
因為我們統一用Yarn做資源調度,實時作業Flink(Spark Streaming)和離線作業會調度到同一個機器上,集群相對空閑時沒什么問題,但是當集群負載較高時,尤其是晚上大批離線任務啟動,就會造成我們實時作業的某些Container所在機器負載過高,同時我們實時作業中如果有重計算邏輯,Flink計算不過來,背壓產生,Kafka消費延遲,數據積壓。解決這個問題的方法是,YARN Label,給YARN管理的機器打上標簽,離線和實時分開,提交作業時指定Lable。
3. 實時作業調度集中的問題
問題產生的背景是,當提交一個作業時(Flink,Spark),作業不大,YARN上申請10個Container,發現10個Container都調度到一個節點上,或者大部分調度到一個節點上,幾個調度到另一個節點,資源分配傾斜。 這樣造成如果我的作業是一個重計算的作業,10Container都在一個節點上,CPU load過高,計算延遲。 當時出現這個問題,比較苦惱,不知道什么原因,也沒有search到解決方案,最后只能去看源碼了(我們用的是Fair調度器),發現Container的分配策略是在一個NodeManger心跳中盡可能多的分配Container,這是為了提升調度的吞吐,但是源碼中有參數可以控制,是否一個心跳允許分配多個Container,以及一次心跳最大分配多少個Container給當前的NodeManager.這個參數Yarn已經暴露給用戶了`yarn.scheduler.fair.assignmultiple` 默認是true。`yarn.scheduler.fair.max.assign` 默認是-1,就是無限制。 解決的方式是`yarn.scheduler.fair.max.assign` 設置為一個較小的值,比如2.
開班時間:2021-04-12(深圳)
開班盛況開班時間:2021-05-17(北京)
開班盛況開班時間:2021-03-22(杭州)
開班盛況開班時間:2021-04-26(北京)
開班盛況開班時間:2021-05-10(北京)
開班盛況開班時間:2021-02-22(北京)
開班盛況開班時間:2021-07-12(北京)
預約報名開班時間:2020-09-21(上海)
開班盛況開班時間:2021-07-12(北京)
預約報名開班時間:2019-07-22(北京)
開班盛況Copyright 2011-2023 北京千鋒互聯科技有限公司 .All Right 京ICP備12003911號-5 京公網安備 11010802035720號