相關搜索 --- 離線和在線的結合

前面說了相關搜索底層的算法邏輯,本篇會繼續以相關搜索爲例子介紹一下相關搜索的的在線部分架構和一種常規的算法類系統的工程化方式。前端

0. 前面的話

在說正題以前仍是先來閒扯一下,都說產品經理的想象和最後工程師的實現之間差了十萬八千里,一樣的,算法的模型和最後的工程化部分也是差了十萬八千里。看到一個好的算法的論文,一看臥槽這麼牛逼,感受能解決一切問題,因而想盡一切辦法想要用到系統中,發現實現的過程當中坑無數,這樣的例子數不勝數。python

好比說推薦系統中常用的SVD矩陣分解,看上去很美好,可是實際工程化中發現計算量實在是太大,大數據規模下計算量特別大,算出來之後調個參數,又幾天過去了,這樣的話,須要快速上一個算法項目很難的,論文的算法不少是沒考慮工程化狀況的,雖然如今有hadoop,有spark,可是有些算法真算起來仍是很耗時間的,因此對算法的改進很重要。 拿到一個算法,對算法的評估很重要,並且須要找到一個可以快速驗證算法有效性的方法,不至於作無用功,最好的評估辦法是什麼呢?呵呵,就是使用成熟的算法,你們都用過的,效果總不至於太差,好比協同過濾這種推薦算法,用了這麼多年了,工程應用也不少,怎麼也不會太差。redis

本篇是相關搜索的總體設計,我會從算法預研,算法選擇和評估,離線算法設計,在線服務設計,總體設計,工程化實現幾個部分來講說一個包含算法的系統的工程化實現過程。算法

1. 算法預研

其實上一篇【相關搜索】介紹的那些個算法就算是算法預研了,算法的預研其實是比較考驗經驗和技術實力的。編程

  • 首先,你須要有必定的技術積累,你才知道哪些個算法和方法能夠解決目前的這個問題,像上一篇的不少相關的算法,好比協同過濾,文本類似性計算,word2vec詞向量這些東西,是須要平時的積累和理解才能知道是否能用在目前的這個場景中的。
  • 其次,若是有相關的經驗的話那就更省事一點了,如今的互聯網的技術棧,哪怕是這類算法類的技術棧,也基本上是有人實現過的,不多能看到一個徹底全新的領域須要你去作,因此若是有相關的經驗的話,預研階段確定是事半功倍了。
  • 通常狀況下,預研階段還須要查閱一些資料或者論文,上網搜一搜別人都怎麼作的,而後總結出來一些個方法,這些就是你預研階段的成果了。拿着這些東西到下一步作進一層的選擇了。

預研階段通常不須要寫代碼,大概想一想這個算法的模型就差很少了,也就說在這個階段,你的腦子裏面應該有各類算法的模型可供下一步的選擇。服務器

2. 算法選擇和評估

預研階段會獲得一批備選的技術方案,在這一步的評估階段就要對這些算法進行更加深層一點的評估了,找到最適合當前場景的技術方案,而後寫一些代碼來幫助進行評估,好比對於相關搜索,咱們在預研階段已經找到了一些技術方案,假設咱們找到了經過後繼詞直接匹配經過搜索詞協同過濾經過點擊的結果集協同過濾經過後繼詞的word2vec方法這四個方案,如何來選擇呢?微信

  • 成本,做爲一個工程項目,成本永遠是不可忽視的部分,工程項目不像科研項目能夠不計成本的進行研究,工程項目都是有最後期限的,因此成本就顯得很重要了,上面四個方案中。
    • 第一個的成本最低,基本上就是一個統計邏輯
    • 第二個和第三個稍微複雜點,須要實現一下協同過濾算法,但這個算法自己仍是很容易的,因此成本稍微比第一個高一點。
    • 第四個方案若是沒有現成的代碼庫可用的話,成本是最高的,由於你必須先完全的瞭解word2vec這套算法,這套算法不是像協同過濾那麼簡單就能夠了解的,而後還須要實現它,而且還要保證正確性,最後實現出來還要保證性能,這其實是很難的。
  • 工程化可能性,就是這些個算法有沒有工程化的可能性或者說好很差進行工程化,在這裏的四個技術方案,都是能夠方便的進行工程化的,因此在相關搜索中,不存在這個工程化可能性的問題,可是在有一些項目中,真會遇到算法沒法進行工程化的狀況,沒法進行工程化的狀況不少,常常遇到的就是計算資源不夠,好比你在一小公司,一共就那麼幾臺小內存的雲主機,你必定要弄一個牛逼的算法,算法中有不少大矩陣相乘的運算,這種就屬於不可能工程化的狀況,還有就是你的團隊技術能力不夠,沒法把一個複雜的算法進行工程化的編程,別說,這種狀況也不佔少數,如今是有各類各樣的開源算法庫支持,把開發的難度下降了很多,否則有些複雜算法實現起來仍是比較困難的。
  • 效果預估,這個是最難的,由於算法類的系統,除非你以前作過相似的系統,不到最後上線之後A/B測試,都不知道效果會如何。這裏咱們粗略的估計一下
    • 經過後繼詞直接匹配,因爲單個用戶的數據畢竟有限,隨機性太強,因此直接使用這個的話,估計效果不會太好。
    • 後面兩個協同過濾中,用戶的點擊數據無論怎麼說,都比直接使用結果集要靠譜點吧,由於用戶的點擊行爲多少表明了用戶當時場景下的意圖,因此第三個方案經過結果集的協同過濾比較好一點
    • 而第四個方案屬於把word2vec進行了一下領域的改變,因此效果好很差不太好直觀感受,這個只有作了才知道好很差。

經過以前的成本評估,雖然word2vec的方案實現起來很複雜,可是目前有針對這個的開源實現,因此對於word2vec而言,開發成本沒那麼高,能夠放入考慮中,這麼算下來,最後肯定使用經過結果集的協同過濾word2vec兩個方案進行系統開發。數據結構

3. 離線算法設計

肯定好算法之後,就要開始漫漫的離線算法設計之路了,其實離線算法設計基本上算工程化的一部分了,驗證的過程當中總體的流程就須要設計好了,哪些須要在線處理的,哪些是離線處理的,這些在離線算法設計的階段就要進行考慮了,主要是爲了後續的架構設計更加順暢。架構

算法類的系統,流程架構基本上有如下三種app

  • 第一種是最簡單的,直接出結果數據,而後把結果數據推到在線服務上,生成合適的數據結構,前端來的請求直接查詢數據結構獲取數據,返回前端,這種適用於結果集變化不是很大的狀況,好比咱們的相關搜索,每一個人搜索關鍵詞出來的相關搜索結果都是同樣的。
  • 第二種稍微複雜點,離線部分生成的除了結果數據,還有個計算模型,把二者都推送到在線服務上,提供服務的時候除了直接獲取結果之外,還須要使用計算模型在線算一下結果,對結果集進行一下微調,而後在返回前端,這種主要適用於結果集改變比較頻繁的場景,好比推薦廣告系統,有個初步的結果集,會根據每一個用戶的標籤,把結果集再排排序之類的。
  • 第三種只生成計算模型,全部的結果都由在線部分實時完成,這樣的場景其實不是不少,主要應用在一些個性化很是明顯的場景中,好比智能問答系統,每一個問題的解答其實是根據當時的狀況實時計算出來,而後再給出結果的。 固然,我這裏把產出概括成結果數據計算模型兩種,實際的狀況中比這複雜一些,但基本上思想就是上面說的這樣子。

好了,咱們來看看相關搜索的離線算法設計部分吧。

上一節咱們說了使用經過結果集的協同過濾word2vec這兩個方案,那麼如何來設計這個流程完成這兩個算法的驗證呢?

對於數據的處理,通常有兩種形式,一種是狀態機模式,就是根據條件在各個條件在各個狀態之間跳轉,還有一種是流式處理模式,就是直接一步一步往下走,算法類的離線處理流程儘可能作到流式處理,樹形結構,由於方便進行任務分配,不一樣人能夠寫不一樣的模塊,組合起來也很容易,並且方便進行數據驗證,每一步均可以單獨進行驗證,而且若是目前是單機的運算,數據量大了之後,也方便進行hadoop的移植,基於這個原則,咱們能夠按照如下圖形來設計這個算法流程。

  • 首先,原始數據來源須要作預處理,生成一個統一的數據結構供後續的節點使用,這個至關於原始數據。
  • 從原始數據出來之後會分紅兩組數據進入不一樣的節點,下面這個節點用來作協同過濾的,先對數據進行二次加工,上面這個節點用來作word2vec,也是對數據進行二次加工,加工成算法須要的數據格式。
  • 第三層節點就是具體的算法模塊了,數據按照格式要求輸入,而後輸出成須要的數據格式供在線平臺使用。

這個流程畫的比較簡單,不過整個相關搜索也不復雜啦,大概的數據處理流程也就是這樣子,只不過算法模塊有些不一樣而已。

在離線算法設計這個環節中,若是你有資源,而且數據量比較大的話,固然能夠直接用hadoop進行驗證,也推薦這麼作,畢竟這樣和最後的工程化的差別比較小,若是你的資源有限,呵呵,那就本機驗證吧,用相似python mapper.py | sort | python reducer.py > res.txt這樣的腳原本驗證算法吧,哈哈。。。

離線算法設計的最後產出就是最後的數據集合了,這也是最後在線部分的基礎數據了。

4. 在線服務設計

離線部分設計完了,也驗證了算法了,那麼就得開始在線服務部分的設計了,離線部分獲得的數據是一個相似KV形式的數據集合,那麼很明顯,最簡單的在線服務就是把這一堆數據存到redis中,而後在線服務根據搜索的query在redis中查詢數據返回結果就好了。

做爲一個高端的設計人員,這麼幹顯然不符合個人一向做風啊。

  • 首先,即使是離線計算出來的,也是有不少搜索詞覆蓋不到的,因此對這部分要在線處理一下。
  • 第二,使用一個redis集羣多耗資源啊,直接在本機用一個本地的kv存儲就能解決,不必上redis啊。

對於第一種狀況,能夠先分詞,而後找到中心詞(這部分能夠在搜索的query分析統一來作),用中心詞就行推薦,好比搜索女士黃色碎花連衣裙加大碼這種搜索詞,極可能由於太長尾了,沒有數據支持,因此得不到相關搜索,咱們能夠在在線服務的時候把這個搜索詞改爲女士連衣裙,這樣就有相關搜索的推薦了,雖然相關性沒那麼高,可是聊勝於無吧,這種就屬於在線算法部分了。

在線算法還有一個功能就是作A/B測試,看看哪一種算法的效果更好,或者是一共10個結果,前5個是協同過濾的,後5個是word2vec的,把那種算法的結果排在前面效果更好,這種的話,經過一個流量的切分來能夠看到兩種算法的效果。

關於A/B測試,能夠專門寫一篇文章,這裏簡單的說一下,流量切分通常有兩種,一種是和用戶相關的,就是對於某一個用戶,你就想讓他看到A版本或者B版本;還有一種是用戶無關的,只是把全部的請求流量切到A版本或者B版本。使用哪個須要根據業務場景來決定。通常狀況下,爲了用戶體驗,都會使用用戶切分的方式,由於你讓一個用戶先看到一種版本的結果,刷新一下頁面就看到另一個版本,總感受怪怪的。A/B測試最基本的辦法就是經過用戶id取模,而後分發到不一樣的版本上去。

對於算法類的系統,由於是機器算出來的效果,還有一個很重要的功能就是人工干預了,當看到badcase之後能夠迅速先解決掉,記錄下badcase,積攢到必定程度,找到規律,而後再去修改算法,既然要先解決掉,那麼就直接人工干預就好了,對於相關搜索,人工干預也很容易,把某個搜索詞的相關搜索推薦結果直接人填寫就好了,把在線服務加一個post的請求接口就能夠搞定了。

綜合上面的全部因素,咱們能夠將在線服務設計成下面這個樣子,具體就不描述了,你們看看圖吧,有問題能夠留言。

5. 總體設計

離線和在線部分都已經設計好了,那麼把他們串起來就是總體設計了,可是總體設計的時候更多的須要考慮外圍的因素了。

外圍的因素在這裏就是原始日誌的收集,這一部分在離線和在線部分都沒涉及到,可是真正工程化的時候是須要考慮的,好比多久整合一第二天志啊,日誌從什麼渠道推送到離線平臺啊,這些都是總體設計的時候考慮的,由於咱們的系統並不須要實時計算,因此對於日誌的處理,能夠天天從各個服務器直接拉取了,也不須要什麼Kafka了,直接wget過來就好了,固然,通常須要作相關搜索的公司,都是搜索有必定的規模了,對於日誌早都有統一的處理的平臺了,日誌早就按時同步到HDFS上了,你只須要直接處理就好了。

總體設計中還有一個環節就是怎麼把離線數據推送到在線服務中,這也是兩個模塊的鏈接點,凡是這種分爲在線和離線兩部分的系統都有這麼一個過程,最簡單的就是寫個腳本rsync啦,別以爲low啊,rsync仍是簡單有效的,至少傳輸的時候不會出錯,或者說出錯的機率比你本身經過tcp傳輸要低得多。還有就是啓一個http的服務,在線模塊wget這份離線數據啊。再高端點,本身實現一個同步數據的協議來進行同步啊。

在數據傳輸中,也會遇到一個小坑,就是推模型拉模型的選擇,我的以爲拉模型比較合適,由於在線服務通常是一個集羣,要是用推模型挨個去推,一個失敗了還要不停的嘗試重新推,推到一半失敗了下次是斷點續傳仍是重新來過也是個問題,這樣會對離線端產生不少複雜邏輯,還有若是在線集羣增長或者減小了機器,還須要通知到離線端,若是是拉模型就好多了,離線端產生了數據之後就不用管了,前面的集羣愛何時拉取數據就何時拉取,離線端徹底不用操心。

因此,把兩個線上和線下系統串起來之後,就是下面這個樣子了,能夠說是一個搜索詞的輪迴,從搜索引擎產生搜索詞的日誌,到最後又變成了一個個的推薦搜索詞,而後這些個搜索詞又能夠進入到搜索日誌中,繼續優化這個系統。

6. 後記

一個小小的相關搜索,雖然簡單,可是基本上涵蓋了一個算法類系統的全部部分,從算法選型,算法驗證,而後是工程化過程當中的離線算法部分和在線服務設計,還要包括A/B測試,在線部分和離線部分結合架構設計。

大部分的算法類系統,都有離線部分,有在線部分,兩個部分各自分擔一部分算法邏輯,最後把兩部分結合起來就是總體的系統了,離線部分負責複雜的算法,在這一塊中,你可使用各類高端算法,各類機器學習算法,關鍵是要儘量的給在線服務分擔計算壓力,最後要生成一個夠簡單的數據給在線服務,在線服務負責性能,如何能更快的響應客戶的請求是這部分須要重點考慮的問題。

哦了,相關搜索部分就寫完了,從頭至尾應該沒有什麼難點,要是你,看了這個設計,能擼出代碼來麼?


若是你以爲不錯,歡迎轉發給更多人看到,也歡迎關注個人公衆號,主要聊聊搜索,推薦,廣告技術,還有瞎扯。。文章會在這裏首先發出來:)掃描或者搜索微信號XJJ267或者搜索西加加語言就行

相關文章
相關標籤/搜索