第4章 算法设计

4.1 实现方式1:欧式距离

实验原理如下图:



图 1 实验原理


4.1.1 步骤1:数据预处理

这一部分对应实验代码1的preprocess函数,首选将文本大写转为小写,然后利用正则表达式去除标点符号,接下来使用nltk包去除句子中的停用词,比如the、a等。经过以上去除一些冗余信息和无关特征,有利于提高模型准确率。

4.2.2 步骤2:获取文档单词列表

实现函数为get_words,主要步骤为读取文档内容,然后行读取句子,将句子按空格分词,最后进行去重,返回单词列表。

4.2.3 步骤三:获取单词词频矩阵

这块分为两部分,一个是为文档单词词频设计的get_Xdw,一个是为查询语句设计的get_Yw,主要步骤是通过get_wors获取文本中的单词列表,然后遍历列表中每一个单词,统计文本中含有该单词的个数。

4.2.4 步骤四:计算查询语句与文档的欧式距离

给定一个查询语句,通过get_Yw获取单词词频矩阵,然后遍历所有的文档,利用下图公式,计算查询语句与文档之间的欧式距离,最后结果按从大到小进行排序。



图2 欧氏距离公式


第5章 程序实现

5.1 实验代码1 计算query与document之间的欧式距离(Euclidean Metric)

# -*- coding: utf-8 -*-
# @Time    : 2018/4/10 15:11
# @Author  : quincyqiang
# @File    : main.py
import os
import math
from nltk.corpus import stopwords
from nltk.stem import PorterStemmer
import matplotlib.pyplot as plt
import numpy as np
# pre-process
def preprocess(words=None):
    print("text propressing..")
    # lower 大写转小写
    words=[word.lower() for word in words]
    # 去除标点符号
    words=[word.replace('[^\w\s]','') for word in words]
    # 去除停用词
    stop=stopwords.words('english')
    temp=[]
    for word in words:
        if word not in stop:
            temp.append(word)
    # 提取词干
    st=PorterStemmer()
    words=[st.stem(word) for word in words]
    return words

# get word list
def get_words():
    words=[]
    for txt in os.listdir('data'):
        with open('data/'+txt,'r') as txt_file:
            for line in txt_file.readlines():
                if line!='\n':
                    for word in line.split():
                        words.append(word)
    new_words=list(set(words))
    # print(new_words)
    new_words=preprocess(new_words)
    return new_words

# get X-dw(document word vector)
def get_Xdw():
    Xdw=[]
    words=get_words()
    # print(words)
    # print(len(words))
    for txt in os.listdir('data'):
        with open('data/'+txt,'r') as txt_file:
            content=txt_file.read()
            Xdw.append((txt,[content.count(word) for word in words]))
    # print(Xdw[0],len(Xdw))
    return Xdw

# get Yw(query word vector)
def get_Yw(sentence):
    words=get_words()
    sentence_words=sentence.split()
    sentence_words=preprocess(sentence_words)
    sentence=' '.join(sentence_words)

    Yw=[sentence.count(word) for word in words]
    # print(Yw)
    return Yw

def evaluate(sentence):
    scores=[]
    Yw=get_Yw(sentence)
    Xdw=get_Xdw()
    for X in Xdw:
        sum=0
        for data in zip(X[1],Yw):
            sum+=(data[0]-data[1])*(data[0]-data[1])
        score=math.sqrt(sum)
        scores.append(round(score,2))
    result=[]
    for data in zip(os.listdir('data'),scores):
        result.append(data)
    result.sort(key=lambda result:result[-1],reverse=True)
    print(result)
    return result
# evaluate('awarded  as a mathematician about approximate measure')
result=evaluate('awarded as a statistician about data model and inference')

x=np.linspace(1,13,13)
y=np.array([score[1] for score in result])

plt.plot(x,y)
plt.show()

第六章 实现结果

6.1 实验结果1:

给定查询语句“awarded as a statistician about data model and inference”,得出如下结果,欧氏距离最小的为'leobrieman.txt'。




图3 查询结果




图4 查询语句与文档相似曲线