【编译原理】Python自然语言处理中的词法分析

目录

一、实验目的

二、实验任务

三、实验原理

1 NumPy 简介

2 匹配算法

四、实验过程

1 正向最大匹配法

2 逆向最大匹配法

*3 jieba英文词组分词

五、实验结果

1 中文分词

2 jieba词频统计

参考资料

附录

1 任务一:中文分词代码

2 任务二:jieba词频统计


一、实验目的

1、掌握正向最大匹配法;

2、掌握逆向最大匹配法;

3、熟悉中文分词工具。

二、实验任务

1、给定字典,[‘研究’,’研究生’, ’生命’,’命’,’的’,‘起源’]

(1)实现正向最大匹配法或逆向最大匹配法,以实现对“研究生命的起源”这个串的分词(必做);

(2)对比两种方法在切分“研究生命的起源”的差异(附加)。

2、利用Jieba实现高频词提取(附加)。

三、实验原理

1 NumPy 简介

NumPy(Numerical Python)是Python语言的一个扩展程序库,支持大量的维度数组与矩阵运算,此外也针对数组运算提供大量的数学函数库。NumPy是一个运行速度非常快的数学库,主要用于数组计算,包含:一个强大的N维数组对象ndarray;广播功能函数;整合 C/C++/Fortran 代码的工具;线性代数、傅里叶变换、随机数生成等功能。NumPy最重要的一个特点是其N维数组对象ndarray,它是一系列同类型数据的集合,以 0 下标为开始进行集合中元素的索引。ndarray 对象是用于存放同类型元素的多维数组,它的每个元素在内存中都有相同存储大小的区域。

图3.1 ndarray存储示意图

图3.2 ndarray知识框架

2 匹配算法

正向最大匹配算法(FMM):从左到右将待分词文本中的几个连续字符与词表匹配,如果匹配上,则切分出一个词。它是一种基于词典的分词方法,同样的基于词典的方法还有逆向最大匹配法(RMM),ngram法.FMM故名思意,左向右扫描寻找词的最大匹配,是一种贪心的思想。

四、实验过程

1 正向最大匹配法

Step 1:假定分词词典中的最长词有i个汉字字符,则用被处理的当前字串中的前i个字作为匹配字段,查找字典。

Step 2:若字典中存在这样一个i字词,则匹配成功;否则,失败,将匹配字段中的最后一个字符去掉, 对剩下字串进行匹配。

Step 3:如此进行下去,直到匹配成功,即切分出一个词或剩余字串长度为0。

不停的匹配,直到文档被扫描完为止。

2 逆向最大匹配法

Step 1:假定分词词典中的最长词有i个汉字字符,则用被处理的当前字串中的后i个字作为匹配字段,查找字典。

Step 2:若字典中存在这样一个i字词,则匹配成功;否则,失败,将匹配字段中的首字符去掉, 对剩下字串进行匹配。

Step 3:如此进行下去,直到匹配成功,即切分出一个词或剩余字串长度为0。

不停的匹配,直到文档被扫描完为止。

*3 jieba英文词组分词

往相应的正则表达式添加空格,然后手动添加需要统计的词组:

五、实验结果

1 中文分词

采用两种不同的分词方法,其相应结果如下表4.1所示。

表4.1 分词结果对比

分词方法

结果

正向最大匹配法

['研究生', '命', '的', '起源']

逆向最大匹配法

['研究', '生命', '的', '起源']

正向最大匹配法和逆向最大匹配法两种不同的分词方法,分词的结果是不相同的。按照我们的理解,对本实验的例句进行分词,第二种匹配方法更为恰当。本次实验,我们只是采用了一个简单的中文句子,结果都不一样。可想而知,如果对于一篇文章或者一部文学著作而言,最终的结果更是有所差别。

2 jieba词频统计

如下图4.1所示,可以统计出自定义词组“5G network”的词频。

图4.1 jieba词频统计示意图

 

参考资料

  1. jieba官网:https://pypi.org/project/jieba/
  2. jieba英文空格分词问题:https://segmentfault.com/q/1010000016011808

附录

1 任务一:中文分词代码

# -*- coding: utf-8 -*-

"""

Created on Fri Feb 28 17:16:47 2020

 

@author: 郭百海

"""

 

dic_list=['研究生','研究','生命','命','的','起源'];

text="研究生命的起源"

ans_forward=[]

ans_reverse=[]

max_len=3#记录字典中词的最大长度

 

def Forward_Match(sentence):

    len_now=len(sentence)

    while len_now>0:

        divide=sentence[0:max_len]

        while divide not in dic_list:

            if len(divide)==1:

                dic_list.append(divide)

                break;

            divide=divide[0:(len(divide)-1)]

        ans_forward.append(divide)

        sentence=sentence[len(divide):]

        len_now=len(sentence)

    print("\"正向最大匹配\"的分词结果:",ans_forward)

 

def Reverse_Match(sentence):

    len_now=len(sentence)

    while len_now>0:

        divide=sentence[-max_len:]#取text后三个字符

        while divide not in dic_list:

            if len(divide)==1:

                dic_list.append(divide)

                break;

            divide=divide[1:]

        ans_reverse.append(divide)

        sentence=sentence[:(len_now-len(divide))]

        len_now=len(sentence)

    print("\"逆向最大匹配\"的分词结果:",ans_reverse[::-1])

   

if __name__=='__main__':

    Forward_Match(text)

    Reverse_Match(text)

2 任务二:jieba词频统计

import jieba

import re

 

jieba.enable_paddle()# 启动paddle模式。 0.40版之后开始支持,早期版本不支持

f=open('ex1_news.txt',encoding="ANSI");

text=f.read();

jieba.re_han_default = re.compile("([\u4E00-\u9FD5a-zA-Z0-9+#&\._% ]+)", re.U)

jieba.add_word('5G network')

seg_list = list(jieba.cut(text, cut_all=False))

dic_seg_list = set(seg_list)

newText='';

for i in dic_seg_list:

    newText=newText+i+' '+str(seg_list.count(i))+'\n';

newFile=open('ex1_结巴词频统计结果.txt','w');

newFile.write(newText);

newFile.close();

 

猜你喜欢

转载自blog.csdn.net/weixin_43442778/article/details/114971321