1. 程式人生 > >基於sklearn庫,搭建一個簡單的問答系統

基於sklearn庫,搭建一個簡單的問答系統

第一部分: 在這部分裡,首先需要去讀取給定的檔案,並把檔案裡的內容讀取到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或在部落格下方留言~