索引時利用K-鄰近算法過濾重復歌曲
最近一直在做公司搜索的優化與維護,做完索引和搜索的分離之后,又有一個新需求,因為做的是歌曲方面的搜索,所以在數據庫中有多個同歌名,同演唱者的的數據,這樣在用戶搜索的時候,會出來一大堆不同版本的歌曲,影響搜索質量,所以需要在建立索引庫時做一個初步的過濾,因為只是一個簡單的過濾,所以并不需要太精確。
首先呢是要確定哪些歌曲需要過濾,我調研后覺得對于同一歌名,同一演唱者的歌曲數量大于10時,就進行過濾,也即閥值為10,當然這個后期可以隨時調整。
然后是需要確定過濾的維度,也即怎樣確定一個歌曲就比另一個歌曲質量好?維度如下:
播放次數
播放完成度(總播放時長/總播放次數)
歌曲質量(超清、高清、普通….)
…..
確定完維度之后,還需要確定權重,因為不同的維度對歌曲質量的影響是不同的。
最后需要一個算法,這要是最核心的,正好以前稍微看了下機器學習這本書,就想到了里面的K鄰近算法,據我粗淺的理解,也就是空間向量計算距離,距離預期近,就說明好。
那么我的步驟如下:
先確定預期,也即一個理論上完美的歌曲,每個維度的值應該為多少。
//expectation point Integer[] origonPoint = {1,2,100000000};
我這邊出于各種考慮,就只給出三個維度,其實維度增加,道理是一樣的。
我用一個INT數組來表示預期完美的點,依次為:播放完成度、歌曲質量、播放次數。
那么對于一首歌曲(0.5,1,10000)距離預期的點的距離就為:
(1-0.5)^2 + (2-1)^2 + (100000000 - 10000)開根號,其實這樣大家應該也能看出來,那么對于距離影響最大的肯定是播放次數,但是如果播放次數占比過大,會導致一個很致命的問題,那就是,過濾算法是不能彌補的,因為一旦開始把歌曲過濾后,那么用戶在搜索時,過濾掉的歌曲就不會出現,那么播放次數肯定是一直為零的,那么一旦一個歌曲被干掉了,那么就永遠的被干掉了。
所以就像前面說的,需要確定全權重
int playCompletenessFactor = 10; double qualtityFactor = 2.5; int timesFactor = 1/10000000;
因為需要提高播放完成度和質量的權重,減少播放次數的權重,那么就初步定為以上的權重個,事實上,這種算法,最重要的就是權重的設定,需要不斷試驗調整。
那么現在距離就為:
(1-0.5)^2 * playCompletenessFactor + (2-1)^2 * qualtityFactor + (100000000 - 10000) * timesFactor開根號
在不斷的試驗和調整中,最終能找到一個合適的權重系數。
所以總結下,整個算法其實很簡單,主要步驟如下:
-
在建索引時,先按照歌曲名稱,歌手名稱排字典序,所以可以用當前索引的歌曲同上一個歌曲比對,如果相同,數量加1,如果不同,就看數量如果大于閥值,就將所有歌曲進行過濾。
-
進入過濾算法,得到各歌曲與預期的距離,按照距離升序排列,取出前N首歌曲
-
將N首歌曲進行索引,其余歌曲丟棄。