minhash演算法檢索相似文字 基於檢索的問答系統

2021-10-13 21:08:36 字數 4687 閱讀 8539

實現架構

主要流程:

建語料庫:首先建立乙個語料庫,即問題和答案的集合,乙個問題對應乙個答案

文字預處理:對輸入的問題進行分詞,拼寫糾錯,詞過濾word-filter,去停用詞stopwords

文字表示成向量:詞向量技術word2vec,tf-idf

文字相似度計算:余弦相似度,歐式距離

文字高效檢索:倒排表排序

返回結果:把相似度最高的問題所對應的答案返回給使用者

part1: 文字預處理

def read_corpus(filepath):

"""讀取給定的語料庫,並把問題列表和答案列表分別寫入到 qlist, alist 裡面

qlist = ["問題1", 「問題2」, 「問題3」 ....]

alist = ["答案1", "答案2", "答案3" ....]

務必要讓每乙個問題和答案對應起來(下標位置一致)

"""qlist =

alist =

with open(filepath) as file:

json_text = file.read()

json_dict = json.loads(json_text)

for data in json_dict["data"]:

for paragraphs in data["paragraphs"]:

for qas in paragraphs["qas"]:

assert len(qlist) == len(alist) # 確保長度一樣

return qlist, alist

# 統計一下在qlist 總共出現了多少個單詞?

# 做簡單的分詞,對於英文我們根據空格來分詞即可

def word_count(qlist):

questions = #分詞後列表

set_que =

word_total = 0

print(len(qlist))

for index in range(len(qlist)):

for index in range(len(questions)):

word_total += len(questions[index])

print(word_total)

return word_total, questions

stopwords = stopwords.words("english")

#預處理 資料清洗 停用詞 小寫 去標點

def clean_words(strwords):

wordlist = nltk.word_tokenize(strwords)

lemmatizer = wordnetlemmatizer()

filteredwords = [lemmatizer.lemmatize(word.lower()) for word in wordlist if word.isalpha() and word.lower() not in stopwords]

return filteredwords

part2: 文字的向量表示對於tf-idf演算法,其訓練出來的句子向量具有高維、稀疏的缺點,故在計算的時候比較慢,本文針對這個問題對其進行了優化,在一定程度上降低了時間複雜度。

相反,對於word2vec演算法,其訓練出來的向量具有低維、稠密的優點,計算速度快,但詞向量的訓練需要大量的語料才能達到好的效果。在進行word2vec詞向量的訓練時,需要根據具體的問題,使用合適的語料,這樣才能更好的表示句子之間的相似度。

def tfidf(qlist):

# 每乙個問題字串轉換成tf-idf向量

vectorizer = tfidfvectorizer(smooth_idf=false, lowercase=true, stop_words=stopwords)

# 得到的是csr_matrix型矩陣(壓縮後的稀疏矩陣)

vectorizer.fit_transform(qlist)

# 獲取詞列表

keywordlist = vectorizer.get_feature_names()

return keywordlist

part3: 文字相似度計算本文採用余弦夾角來計算向量之間的相似度,相似問題一般包含更多相同的特徵詞,兩個問句的主題是否接近,取決於它們的特徵向量「長得像不像」。是使用者提問的問句向量,得到和後,它們所對應的兩個問句之間的相似度就可以利用和這兩個向量之間夾角的余弦值來表示。。 余弦相似度的定義雖然簡單,但是在利用公式計算兩個向量的夾角時,計算量為,當使用者提出乙個問題時,需計算次(為語料庫中問句的數量,),如果語料庫很大,則將答案返回給使用者需要很長的時間,所有後續先採用倒排列表進行處理,降低余弦相似度匹配的語料庫數量。

# 兩個問題之間的相似度(余弦相似度計算)

def cosine_similarity(input_q, que_dict):

simi_dict = {}

vectorizer = tfidfvectorizer(smooth_idf=false, lowercase=true, stop_words=stopwords)

for index, question in que_dict.items():

tfidf = vectorizer.fit_transform([input_q, question])

simi_value = ((tfidf * tfidf.t).a)[0, 1]

if simi_value > 0:

simi_dict[index] = simi_value

return simi_dict

part4: 文字高效檢索上面的演算法,乙個最大的缺點是每乙個使用者問題都需要跟庫里的所有的問題都計算相似度。假設我們庫里的問題非常多,這將是效率非常低的方法。 這裡面乙個方案是通過倒排表的方式,先從庫裡面找到跟當前的輸入類似的問題描述。然後針對於這些candidates問題再做余弦相似度的計算。這樣會節省大量的時間。

倒排索引源於實際應用中需要根據屬性的值來查詢記錄。這種索引表中的每一項都包括乙個屬性值和具有該屬性值的各記錄的位址。由於不是由記錄來確定屬性值,而是由屬性值來確定記錄的位置,因而稱為倒排索引(inverted index)。帶有倒排索引的檔案我們稱為倒排索引檔案,簡稱倒排檔案(inverted file)。

def invert_idxtable(qlist_kw):  # 乙個簡單的倒排表

inverttable = {}

for idx, tmplst in enumerate(qlist_kw):

for kw in tmplst:

if kw in inverttable.keys():

else:

inverttable[kw] = [idx]

return inverttable

part5: 返回結果

def filter_questionbyinverttab(inputq_keyword, qlist, inverttable):

idx_lst =

q_dict = {}

for kw in inputq_keyword:

if kw in inverttable.keys():

idx_lst.extend(inverttable[kw])

idxset = set(idx_lst)

for idx in idxset:

q_dict[idx] = qlist[idx]

return q_dict

def top5results_invidx(input_q):

inputq_keyword = clean_words(input_q)

filtered_qdict = filter_questionbyinverttab(inputq_keyword, qlist, inverttable)

# 計算相似度

simi_dict = cosine_similarity(input_q, filtered_qdict)

d = sorted(simi_dict, key=simi_dict.get, reverse=true)

#print(d)

# top5最相似問題,及它們對應的答案

print("top5相似-基於倒排表")

for idx in d[:5]:

print("問題: " + qlist[idx])

print("答案: " + alist[idx])

part6: 測試

print (top5results_invidx("at what age did frédéric move to paris?"))

文字去重之MinHash演算法

1.概述 跟simhash一樣,minhash也是lsh的一種,可以用來快速估算兩個集合的相似度。minhash由andrei broder提出,最初用於在搜尋引擎中檢測重複網頁。它也可以應用於大規模聚類問題。2.jaccard index 在介紹minhash之前,我們先介紹下jaccard in...

文字檢索演算法

純c語言實現。這個函式的功能是檢索檔案中的單詞,並定位到那一行,並輸出出現數目。演算法感覺難度不是特別大,但我這個演算法效率並不高,準備以後寫個效率更高的。函式的第二個引數可以刪除,在這裡並沒有什麼用。void word count file file,int line no,char word 統...

文字相似度演算法

1.基於詞向量 余弦相似度 分詞 列出兩個句子的並集 計算詞頻向量 計算余弦值,適合基於語義的相似度分析 曼哈頓距離 歐幾里得距離 明式距離 是前兩種距離測度的推廣 在極限情況下的距離是切比雪夫距離 2.基於字元的 編輯距離 simhash,對於短小的文字,計算相似度並不十分準確,更適用於較長的文字...