NLP学习__task2:特征提取:基本文本处理、语言模型

1. 基本文本处理技能——中文分词

1.1 分词的概念

      中文分词,即Chinese Word Segmentation,即将一个汉字序列进行切分,得到一个个单独的词。根据中文的特点,可以将分词算法分为四大类:1)基于规则的分词方法;2)基于统计的分词方法;3)基于语义的分词方法;4)基于理解的分词方法。

下面对这几种方法分别进行总结:

1)基于规则的分词方法

    又称为机械分词方法、基于字典的分词方法,是按照一定的策略将待分析的汉字串与一个“充分大的”机器字典中的词条进行匹配。若在词典中找到某个字符串,则匹配成功。该方法有三个要素,即分词词典、文本扫描顺序和匹配原则。文本的扫描顺序有正向扫描、逆向扫描和双向扫描。匹配原则主要有最大匹配、最小匹配、逐词匹配和最佳匹配。常见的方法有:正向最大匹配法、逆向最大匹配法、N-最短路径方法

正向最大匹配法(forward maximum matching method,FMM):从左到右扫描寻找词的最大匹配。首先我们规定一个词的最大长度,每次扫描的时候寻找当前开始的这个长度的词来和字典中的词匹配,如果没找到,就缩短长度继续寻找,直到找到或者成为单字。如:“中国科学院计算机研究所”,按照FMM切分原则结果为“中国科学院/计算机研究所”。如:”他从东经过我家”,切分结果为”他/从/东经/过/我/家”

逆向最大匹配法(backward maximum matching method,BMM):从右到左扫描寻找词的最大匹配。与FMM思路相同,方向相反。如:”他从东经过我家”切分为”他/从/东/经过/我/家”。

双向最大匹配法(Bi maximum matching method,BiMM):从左到右和从右到左同时进行切分,将其结果进行比较,选择切分词语数量最少的结果。

基于规则匹配的方法的优缺点:

优点: 1)程序简单易行,开发周期短;2)没有任何复杂计算,分词速度快。

缺点: 1)不能处理歧义;2)不能识别新词;3)分词准确率不高,不能满足实际的需要;

2)基于统计的分词方法

主要思想:词是稳定的组合,因此在上下文中,相邻的字同时出现的次数越多,就越有可能构成一个词。因此字与字相邻出现的概率或频率能较好地反映成词的可信度。可以对训练文本中相邻出现的各个字的组合的频度进行统计,计算它们之间的互现信息。互现信息体现了汉字之间结合关系的紧密程度。当紧密程度高于某一个阈值时,便可以认为此字组可能构成了一个词。该方法又称无字典分词。

该方法主要的模型有:N元文法模型(N-gram)、隐马尔科夫模型(Hidden Markov Model,HMM)、最大熵模型(ME)、条件随机场模型(Conditional Random Fields,CRF)等。

3)基于语义的分词方法

语义分词法引入了语义分析,对自然语言自身的语言信息进行更多的处理,如扩充转移网络法、知识分词语义分析法、邻接约束法、综合匹配法、后缀分词法、特征词库法、矩阵约束法、语法分析法等。

4)基于理解的分词方法

基于理解的分词方法是通过让计算机模拟人对句子的理解,达到识别词的效果。其基本思想就是在分词的同时进行句法、语义分析,利用句法信息和语义信息来处理歧义现象。它通常包括三个部分:分词子系统、句法语义子系统、总控部分。在总控部分的协调下,分词子系统可以获得有关词、句子等的句法和语义信息来对分词歧义进行判断,即它模拟了人对句子的理解过程。这种分词方法需要使用大量的语言知识和信息。目前基于理解的分词方法主要有专家系统分词法和神经网络分词法等。

1.2 词、字符频率统计

此部分主要介绍,如何将中文文本进行字、词级别的切分,以及统计。下面直接以代码为例:

文档:程序员从事程序开发、维护的专业人员。一般将程序员分为程序设计人员和程序编码人员,但两者的界限并不非常清楚,特别是在中国。软件从业人员分为初级程序员、高级程序员、系统程序员和项目经理四大类。

1)字级别频率统计

首先将文档内容以字级别切分,然后统计频率。字级别的切分处理比较简单,可以直接当作字符串进行处理,即可得到结果。词频统计的方法有collections.Counter模块,当然也可以自己写代码。代码如下:

from collections import Counter

# 文档
a = '程序员从事程序开发、维护的专业人员。一般将程序员分为程序设计人员和程序编码人员,但两者的界限并不非常清楚,特别是在中国。软件从业人员分为初级程序员、高级程序员、系统程序员和项目经理四大类。'
a = list(a) # 将字符串直接list即可得到字的切分
b = Counter(a) # collections.Counter模块计算a中字的频率

# 不调用模块实现词频统计
c = dict()
for each in a:
    if each in c:
        c[each] += 1
    else:
        c[each] = 1

如果是读入的文本内容,可以将读入的文本内容先整理为一个字符串,然后进行切分,再做统计。

2)词级别频率统计

首先需要考虑文本内容的词语的切分,然后统计频率。中文分词工具有Jieba分词、SnowNLP、THULAC、NLPIR和LTP等,这里以jieba分词为主来实现文本内容的切分。具体见代码:

import jieba
a = '程序员从事程序开发、维护的专业人员。一般将程序员分为程序设计人员和程序编码人员,但两者的界限并不非常清楚,特别是在中国。软件从业人员分为初级程序员、高级程序员、系统程序员和项目经理四大类。'
b = jieba.cut(a,cut_all=False) #精确模式
c = ' '.join(b)
print(c)
# 结果如下: '程序员 从事 程序开发 、 维护 的 专业 人员 。 一般 将 程序员 分为 程序设计 人员 和 程序 编码 人员 , 但 两者 的 界限 并 不 非常 清楚 , 特别 是 在 中国 。 软件 从业人员 分为 初级 程序员 、 高级 程序员 、 系统 程序员 和 项目经理 四大 类 。'
# 加上统计词频,一般会直接这样写
d = Counter([each for each in jieba.cut(a,cut_all=False)])
e = dict() # 存储词语:P(词语)
for each in d:
    e[each] = d[each]/50

2 语言模型

语言模型中unigram、bigram、trigram的概念

语言模型主要有统计语言模型(n-gram语言模型)和神经网络语言模型等。下面主要介绍n-gram语言模型。

知乎上面关于这一块讲解比较详细,不做重复:深入理解语言模型 Language Model

这篇博客讲解浅显易懂:深入浅出语言模型

 

3. 文本矩阵化

        首先将文本内容进行分词,然后存储文本内所有词语,生成词语对应的数字,即{'词语':数字}(例如:{'我':0,'是':1,'中国人':2}),最后将文本内容全部替换为数字。

举例1:程序员从事程序开发、维护的专业人员。一般将程序员分为程序设计人员和程序编码人员,但两者的界限并不非常清楚,特别是在中国。软件从业人员分为初级程序员、高级程序员、系统程序员和项目经理四大类。

代码:

import jieba
import pandas as pd

a = '程序员从事程序开发、维护的专业人员。一般将程序员分为程序设计人员和程序编码人员,但两者的界限并不非常清楚,特别是在中国。软件从业人员分为初级程序员、高级程序员、系统程序员和项目经理四大类。'
# first : 切分词语,并保存为list
a_list = [each for each in jieba.cut(a)]
# second : 生成词语与数字对应的字典
char2num = dict(zip(sorted(list(set(a_list))),range(0,len(set(a_list)))))
# third : 词语换成数字.此处使用DataFrame的一个特点进行置换
aa = pd.Dataframe()
aa['char'] = a_list
aa['num'] = aa['char'].map(char2num)
print(aa)

结果如图:

 举例2:数据下载http://pan.baidu.com/s/1hugrfRu   密码:qfud

             stopword.txt下载:链接

使用cnews.test数据为例进行说明,具体代码见链接:文本矩阵化

import jieba
import pandas as pd

with open('./cnews.test.txt','r',encoding='UTF-8') as f:
    cnews_test = f.readlines()
# 将test中的label取出
test_label,test_x = [],[]
for each in cnews_test:
    each0 = each.split('\t')
    test_label.append(each0[0])
    test_x.append(each0[1])
# 载入停用词字典,对其进行去停用词
with open('./stopword.txt','r',encoding='UTF-8') as f:
    stopwords = f.readlines()
# 之所以对停用词进行了下面的处理,是因为读入时有'\n'的存在
a = ''
for each in stopwords:
    a = a + ' '+each
stopwords = a.replace('\n','').split(' ')
stopwords = [each for each in stopwords if each not in ['\n','']]
test_x0 = [[each0 for each0 in jieba.cut(each) if each not in stopwords] for each in test_x]
# 使用DataFrame的特点进行文本转化为数字
import pandas as pd
textDict = []
for each in test_x0:
    textDict.extend(each)
textDict = list(set(textDict))
char2num = dict(zip(sorted(textDict),range(0,len(textDict))))
testData = []
for each in test_x0:
    aa = pd.DataFrame()
    aa['char'] = each
    aa['num'] = aa['char'].map(char2num)
    testData.append(aa['num'].values.tolist())
# 得到的testData就是一个文本对应数字的矩阵

或者按照task1中的处理方式进行:文本矩阵化

参考资料:

链接1:中文分词原理及常用Python中文分词库介绍

链接2:(2)中文分词——基于词典的方法

链接3:自然语言处理基础-中文分词

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值