如果有一天,你向優酷傳了一個記錄着你和我當天一起去長城玩的小視頻(假設其大小爲1G)。在你傳完以後,我也傳了一個和你一模一樣的視頻。但是我一點擊上傳,幾秒鐘就現設上傳成功。這是爲什麼呢。這就是這這會要討論的simhash算法。
simhash過程一共有5個步驟,分詞,hash,加權,合併,降維。
第一步分詞。假設現在給一個句子:我今天有課。再給一個句子:我明天有課。很明顯這兩個句子代表的含義明顯不一樣,如果按照simhash的步驟來看,那麼我們首先應該分詞:第一個句子:我(),今天(),有課()。括號內代表着不同的權重。同理第二個句子可以分爲:我(),明天(),有課().括號內的權重應該有以下兩種方法:靜態給定和統計出現頻率來給權重。
第二步hash:hash結果將以二進制表示,比如給權重如下:我(5),今天(4),有課(3);我(5),明天(3),有課(3)。假設哈希結果爲”我”:100101, “今天”:101011。即通過某種算法,得出了一系列數字。
第三步加權:現在要對“我”這個字加權,遇到1則哈希值與權重正乘,遇到0則哈希值與權重負乘結果爲100101*5 =5-5 -5 5 -5 5 。“今天”的加權結果爲 101011*4 =4 -4 4 -4 4 4其他詞同樣操作。
第四步合併:將所有的加權結果累加,變成只有一個序列串。比如對“我今天”進行加權累加,得到的結果爲9 -9 1 -1 1 9
第五步降維:對於其結果,如果大於0就製爲1,否則就置爲0。所以得到結果:101011.這就是“我今天”最後得到的哈希值。
回到最開始的問題。如果我們最後看到你傳的視頻的哈希值和我傳的視頻的哈希值,是一模一樣的。那就代表着,我們兩個傳的文件,是一模一樣的。那既然一模一樣,爲什麼我還要再傳一遍呢?數據庫裏改一改就好了嘛。
換個話題繼續討論。如果你的數據庫裏存在着百萬,千萬,甚至上億個哈希值。並且系統對於上傳文件要求對於視頻允許存在一些細微的差別(比如多了幾秒片頭片尾的黑屏)那麼我們如果繼續使用這種挨個比較的算法,那時間上會不會太慢了?如果太慢了,那又該怎麼優化呢?
我們需要引入三個個新的概念:鴿巢原理、倒排索引、海明距離。三個概念在此不再詳述,請自行百度。
依照慣例,我們對於相似度的要求是在64位系統下海明距離不超過3,那麼根據鴿巢原理,我們將其64位平均分爲4個小塊。如果這兩個視頻是類似的,這樣就一定會有一個小塊裏的哈希值是全等的。那麼我們建立倒排索引,通過倒排索引來進行查找,這樣就不需要挨個比較了。