基於sklearn庫,搭建一個簡單的問答系統
阿新 • • 發佈:2018-12-24
第一部分: 在這部分裡,首先需要去讀取給定的檔案,並把檔案裡的內容讀取到list裡面。這部分的任務主要需要檔案IO操作方面的基本知識。
# 讀取檔案 def read_corpus(file): with open(file) as f: list = [] lines = f.readlines() for i in lines: list.append(i) return list questions = read_corpus('./Question_combined.dat') answers = read_corpus('./Answer_combined.dat') assert len(questions)==len(answers), "問題和答案列表的大小不一樣,請檢查讀入資料是否有誤!"
第二部分: 處理已有的字串資料,並把它們轉換成詞袋向量。這部分內容涉及到一些簡單的字串預處理技術(比如過濾掉一些沒用的字元、分詞等),還有就是基於sklearn的把字串轉換向量的過程。本部分的內容需要字串操作、分詞、詞袋模型相關的基礎知識。
import re import jieba from sklearn.feature_extraction.text import CountVectorizer def filter_out_category(input): new_input = re.sub('[\u4e00-\u9fa5]{2,5}\\/','',input) return new_input def filter_out_punctuation(input): new_input = re.sub('([a-zA-Z0-9])','',input) new_input = ''.join(e for e in new_input if e.isalnum()) return new_input def word_segmentation(input): new_input = ','.join(jieba.cut(input)) return new_input def conver2BOW(data): new_data = [] for q in data: q = filter_out_category(q) q = filter_out_punctuation(q) q = word_segmentation(q) new_data.append(q) vectorizer = CountVectorizer() X = vectorizer.fit_transform(new_data) return vectorizer, X vectorizer, X = conver2BOW(questions)
第三部分: 對於使用者的新輸入,返回答案。 這是最後一部分,也就是等我們建立完詞袋向量之後,我們就可以輸入一些新的問題,然後從庫中找出最合適的答案。這部分的任務涉及到餘弦相似度、簡單搜尋排序等方面基礎知識。
import numpy as np def idx_for_largest_cosine_sim(input, questions): list = [] input = (input.toarray())[0] for question in questions: question = question.toarray() num = float(np.matmul(question, input)) denom = np.linalg.norm(question) * np.linalg.norm(input) cos = num / denom list.append(cos) best_idx = list.index(max(list)) return best_idx def answer(input): input = filter_out_punctuation(input) input = word_segmentation(input) bow = vectorizer.transform([input]) best_idx = idx_for_largest_cosine_sim(bow, X) return answers[best_idx]
輸入問題,檢視結果
print(answer("誰知道網上找兼職工作的網站"))
搜尋結果如下:
這裡沒有對返回資料進行過清洗,否則體驗會更好一些…
原始碼及測試資料已上傳至git,點選這裡可直接檢視,有疑問的同學可提Issues或在部落格下方留言~