很多人在提問的時候都會重複,所以他希望有一個功能,就是假設新問題跟已經有的問題相似,就直接推給答案,就避免了重複提問和解答,以及找到解答的時間了。
那麼問題就很清楚的定義了,新問題(文字)與已有的問題(文字)之間怎麼算重複問題?
我們能否通過設計一個相似度函數,通過呼叫 Similar(新問題,老問題),把每個老問題都計算一邊,就判斷出是否相似。
於小文發現「日本多大」,「日本大小」
假設我們說文字「日本多大的面積」,和文字「日本面積多大」,一個想法是,這兩個文字中有很多字一樣,那麼我們假設文字是由單個的字組成的集合,那麼最簡單的的方法是,判斷兩個集合交集來多少。
「日本時間」和「本日時間」顯然不是一個時間,但是如果按照剛纔的演算法,它們相似度就是100%了。
解決辦法是分詞
於小文發現了一個問題,有些問題中有很多「廢話」,例如
有用的詞往往是不常見的,沒用的詞往往是常見的,例如「的」,「有」都很常見,但是「日本」,「面積」在日常說話中並不常見。
例如一個問題是:「switch到底哪好了我發現好多人都買了switch」,這裏switch提到了兩次,應該是一個比較重要的詞。如果我們僅僅用所有問題統計的詞權重就忽略了問題(當前文字)本身中的特性(權重),於是決定把這兩個特性結合一下。
有人問:「廁所怎麼裝修」,有人問「洗手間怎麼裝修」,「洗手間」和「廁所」應該是一個意思,吧?但是顯然它們從文字上沒有任何相似性。
也就是說這兩個詞從「字元」級別上完全沒相似性,但是從「含義」上有相似性。
假設我們有一個神奇的函數,例如叫他T,T可以把輸入的詞,都轉換爲一個真實且唯一的含義的某個符號,也就是說它有一個如下的性質:
T(廁所) = T(洗手間)
因爲廁所和洗手間的含義相同,它們經過T轉換後的符號也肯定相同。
例如我們說填空題:「我來到了海邊,放眼望去一片()」,括號裏面填什麼?
我們把這類填空題也定義爲一個函數,例如叫V,所以可以得到下面 下麪的關係:
V(我來到了海邊,放眼望去一片) = T(藍色) = T(藍)
當然在實際上我們其實並不需要完全等於,所以粗略的也可以把上面修改爲:
V(我來到了海邊,放眼望去一片) ≈ T(藍色) ≈ T(藍)
也就是說我們假設找到了函數T和V,就可以讓「藍色」、「藍」,歸一到一個一致或至少差不多的符號上,這樣就可以用這兩個字元之間的相似度來代替它們的字元相似度,也就是可以讓「廁所」和「洗手間」等價。
那麼爲什麼需要填空題呢,因爲填空題不需要太多額外的處理,只要我們從一個完整句子挖空一個詞就可以了,非常容易得到。
而且我們也不需要設計T(藍色) ≈ T(藍)的部分,只要我們通過訓練能使得函數T和函數V滿足:
V(我來到了海邊,放眼望去一片) ≈ T(藍色)
V(我來到了海邊,放眼望去一片) ≈ T(藍)
自然可以得到 T(藍色) ≈ T(藍)
以上是Word2vector的某種解釋。
於小文遇到一個問題,有很多人不僅僅是爲了提問,也是會去看看別人問的問題都有什麼。這個時候最好能把問題做一些分類。
但是於小文只會用相似度,於是想,什麼是分類?
假設我們有分類A、B、C,新來一個問題x,那麼所謂分類不就是看x跟A、B、C哪個相似?或者說跟A、B、C裏面的哪些問題相似?
所以一個最樸素的想法是這樣的:假設問題x跟A、B、C裏面所有的問題都比較一下相似度,然後看排前n個最相似的問題都是分別屬於A、B、C哪些裏面的,投個票,就好了。
這個演算法基本上是K-Nearest-Neighbour
那麼我現在沒有A、B、C這些個分類啊?
一個方法是於小文辛苦一點,自己先把問題都過一遍,按照某個標準,分個幾萬個問題,先把A、B、C都先大概分出來。
但是於小文很懶,真的很懶。
相似的問題總是相似的 —— 於小文
我們假設我們要把問題分成10類,假設我們每類先隨機放入一個問題。第11個問題,看它跟這10個分類裏面的問題哪個最相似,哪個最相似就放入裏面,這樣不斷的往裏放。當然還要注意就是分類裏面已有的問題,如果它其實跟本身分類的問題都不太相似,反而跟別的分類的一些問題更相似,就挑出來放到別的分類裏面。
重複上面兩個過程,不就是把相似的都放一起了?
然後於小文只需要大概看看每個分類,給一些明確的分類起個名字就好了
這個演算法基本上是K-means
搜尋和聚類、分類其實差不多,我們可以認爲語意搜尋從某種意義上來說,是拿搜尋中的「查詢語句」去找已有資料庫中的最相似的資料。
這方面首先我們需要有一種判斷相似度的方法,其次是可能構建分層次的搜尋方法。
例如先進行粗力度的大範圍搜尋,例如用annoy庫,或者jina FAISS這樣的引擎。
然後可以再進行某些細粒度的排序,例如用某種Siamese Networks的複雜模型,最終得到結果