Task2 特征提取 (2 days)
1. 分词
1.1 分词概念
1.2 词、字符频率统计
2. unigram、bigram、trigram
2.1 语言模型中unigram、bigram、trigram的概念
2.2 unigram、bigram频率统计;(可以使用Python中的collections.Counter模块,也可以自己寻找其他好用的库)
3. 文本矩阵化:要求采用词袋模型且是词级别的矩阵化
3.1 分词(采用结巴分词来进行分词操作)
3.2 去停用词;构造词表
3.3 每篇文档的向量化
1.1中文分词概念
中文分词是中文信息处理的基本技术,指将一个汉字序列切分成一个个单独的词。分词就是将连续的字序列按照一定的规范重新组合成词序列的过程。
现有的中文分词算法有五大类:基于词典的分词方法,基于统计的分词方法,基于规则的分词方法,基于字标注的分词方法,基于人工智能技术(基于理解)的分词方法。
基于字典的分词方法,它是按照一定策略将待分析的汉字串与一个“充分大的”机器词典中的词条进行匹配,若在词典中找到某个字符串,则匹配成功。根据扫描方向的不同,这种分词方法分为正向匹配、逆向匹配和双向匹配,常见的匹配原则有逐词匹配、最大匹配、最小匹配和最佳匹配。
正向最大匹配法
分词目标:
在词典中进行扫描,尽可能地选择与词典中最长单词匹配的词作为目标分词,然后进行下一次匹配。
算法流程:
假设词典中最长的单词为 5 个,那么最大匹配的起始子串字数也为 5 个
(1)从左往右读入子串,扫描字典,测试读入的子串是否在字典中
(2)如果存在,则从输入中删除掉该子串,重新按照规则取子串,重复(1)
(3)如果不存在于字典中,则从右向左减少子串长度,重复(1)
逆向最大匹配法
分词目标:
在词典中进行扫描,尽可能地选择与词典中最长单词匹配的词作为目标分词,然后进行下一次匹配。 在实践中,逆向最大匹配算法性能优于正向最大匹配算法。
算法流程:
假设词典中最长的单词为 5 个,那么最大匹配的起始子串字数也为 5 个
(1)从右往左读入子串,扫描字典,测试读入的子串是否在字典中
(2)如果存在,则从输入中删除掉该子串,重新按照规则取子串,重复(1)
(3)如果不存在于字典中,则从左向右减少子串长度,重复(1)
双向最大匹配法
分词目标:
将正向最大匹配算法和逆向最大匹配算法进行比较,从而确定正确的分词方法。
算法流程:
(1) 比较正向最大匹配和逆向最大匹配结果
(2) 如果分词数量结果不同,那么取分词数量较少的那个
(3) 如果分词数量结果相同
- 分词结果相同,可以返回任何一个
- 分词结果不同,返回单字数比较少的那个
1.2词、字符频率统计
1.字符频统计
import numpy as np
from collections import Counter
word="大连海事大学一百一十周年快乐"
result=Counter(word)
print(result)
Counter({'一': 2, '大': 2, '事': 1, '年': 1, '十': 1, '连': 1, '百': 1, '海': 1, '乐': 1, '学': 1, '快': 1, '周': 1})
2.词频统计
from collections import Counter
import jieba
word="大连海事大学一百一十周年快乐"
seg_list = list(jieba.cut(word))
result = Counter(seg_list )
print(result)
Counter({'快乐': 1, '周年': 1, '一百一十': 1, '大连海事大学': 1})
2. unigram、bigram、trigram
2.1 语言模型中unigram、bigram、trigram的概念
为了解决自由参数数目过多的问题,引入了马尔科夫假设:随意一个词出现的概率只与它前面出现的有限的n个词有关。基于上述假设的统计语言模型被称为N-gram语言模型。
从模型的效果来看,理论上n的取值越大,效果越好。但随着n取值的增加,效果提升的幅度是在下降的。同时还涉及到一个可靠性和可区别性的问题,参数越多,可区别性越好,但同时单个参数的实例变少从而降低了可靠性。
其中,有关中文分词的一些概念是我们需要掌握的,譬如:
- unigram 一元分词,把句子分成一个一个的汉字,每个词之间没有关联关系;
- bigram 二元分词,把句子从头到尾每两个字组成一个词语,当前词只和上一个词有关系;
- trigram 三元分词,把句子从头到尾每三个字组成一个词语,当前词只和前两个词有关系。
比如:
大连海事大学:
unigram 形式为:大/连/海/事/大/学
bigram形式为: 大连/连海/海事/事大/大学
trigram形式为:大连海/连海事/海事大事通大学
2.2 unigram、bigram频率统计
import collections #参考博考1
import os
import wordCount
base_dir = 'data/cnews'
train_dir = os.path.join(base_dir, 'news.txt')
text = wordCount.read_file(train_dir)
unigram_counter = collections.Counter([text[i] for i in range(0, len(text))])
for k, v in unigram_counter.items():
print(k, v)
bigram_counter = collections.Counter([(text[i], text[i + 1]) for i in range(0, len(text) - 1)])
for k, v in bigram_counter.items():
print(k, v)
bigram_counter = collections.Counter([(text[i], text[i + 1], text[i + 2]) for i in range(0, len(text) - 2)])
for k, v in bigram_counter.items():
print(k, v)
3. 文本矩阵化:
3.1 分词
分词工具采用结巴中文分词,涉及到的算法:
- 基于Trie树结构实现高效的词图扫描,生成句子中汉字所有可能成词情况所构成的有向无环图(DAG);
- 采用了动态规划查找最大概率路径, 找出基于词频的最大切分组合;
- 对于未登录词,采用了基于汉字成词能力的HMM模型,使用了Viterbi算法。
结巴中文分词支持的3种分词模式:
- 精确模式:试图将句子最精确地切开,适合文本分析;
- 全模式:把句子中所有的可以成词的词语都扫描出来, 速度非常快,但是不能解决歧义问题;
- 搜索引擎模式:在精确模式的基础上,对长词再次切分,提高召回率,适合用于搜索引擎分词。
关于jieba可以参考全国计算机等级考试中命题人嵩天在MOOC的课程
import jieba
# 全模式
text = '大连海事大学的校训是:学汇百川,德济四海'
seg_list = jieba.cut(text, cut_all=True)
print(u"[全模式]: ", "/ ".join(seg_list))
# 精确模式
seg_list = jieba.cut(text, cut_all=False)
print(u"[精确模式]: ", "/ ".join(seg_list))
# 默认是精确模式
seg_list = jieba.cut(text)
print(u"[默认模式]: ", "/ ".join(seg_list))
# 搜索引擎模式
seg_list = jieba.cut_for_search(text)
print(u"[搜索引擎模式]: ", "/ ".join(seg_list))
[全模式]: 大连/ 大连海事大学/ 海事/ 大学/ 的/ 校训/ 是/ / / 学/ 汇/ 百川/ / / 德/ 济/ 四海
[精确模式]: 大连海事大学/ 的/ 校训/ 是/ :/ 学汇/ 百川/ ,/ 德济/ 四海
[默认模式]: 大连海事大学/ 的/ 校训/ 是/ :/ 学汇/ 百川/ ,/ 德济/ 四海
[搜索引擎模式]: 大连/ 海事/ 大学/ 大连海事大学/ 的/ 校训/ 是/ :/ 学汇/ 百川/ ,/ 德济/ 四海
3.2停用词
人类语言包含很多功能词。与其他词相比,功能词没有什么实际含义。最普遍的功能词是限定词(“the”、“a”、“an”、“that”、和“those”),这些词帮助在文本中描述名词和表达概念,如地点或数量。介词如:“over”,“under”,“above” 等表示两个词的相对位置。
这些功能词的两个特征促使在搜索引擎的文本处理过程中对其特殊对待。第一,这些功能词极其普遍。记录这些词在每一个文档中的数量需要很大的磁盘空间。第二,由于它们的普遍性和功能,这些词很少单独表达文档相关程度的信息。如果在检索过程中考虑每一个词而不是短语,这些功能词基本没有什么帮助。
在信息检索中,这些功能词的另一个名称是:停用词(stopword)。称它们为停用词是因为在文本处理过程中如果遇到它们,则立即停止处理,将其扔掉。将这些词扔掉减少了索引量,增加了检索效率,并且通常都会提高检索的效果。停用词主要包括英文字符、数字、数学字符、标点符号及使用频率特高的单汉字等。
# 读取停用词
stopwords = []
with open('stopwords.txt', 'r') as fr: #stopwords是下载下来的停用词表,不同的公司不同
for line in fr:
stopwords.append(line[:-1])
3.3构造词表
import jieba
# 计算词频
text='大连海事大学的校训是:学汇百川,德济四海'
seg_list = jieba.cut(text, cut_all=False)
result = []
for seg in seg_list:
seg = ''.join(seg.split())
if seg != '' and seg != "\n" and seg != "\n\n" and seg not in stopwords:
result.append(seg)
word_fre = {}
for i in set(result):
word_fre[i] = result.count(i)
word_fre = sorted(word_fre.items(), key=lambda item: item[1], reverse=True)
#取前100条数据加快处理,参考的另一篇
data = lists[:100]
#统计词表出现次数
wordList = {}
for i in data:
for j in i:
if j in wordList:
wordList[j] += 1
else:
wordList[j] = 1
#创建词表
count = 0
dic = {}
for i, j in wordList.items():
if j > 2:
dic[i] = count
count += 1
#反向词表
resDic = {}
for i, j in dic.items():
resDic[j] = i
3.3文档向量化
sklearn.feature_extraction.text 的4中文本特征提取方法:
- CounterVector
- TfidfVectorizer
- TfidfTransformer
- HashingVectorizer
train_data = train_data[:5]
words = []
for sentence in train_data['content']:
word = list(jieba.cut(sentence))
for w in list(set(word) and set(stopwords)):
while w in word:
word.remove(w)
words.append(' '.join(word))
train_data['content_'] = words
# 计算 TF-IDF
count_vectorizer = CountVectorizer(max_features=256, min_df=2)
count_vectorizer.fit_transform(train_data['content_'])
fea_vec = count_vectorizer.transform(train_data['content_']).toarray()
参考博客:
1.https://blog.csdn.net/mxs1123/article/details/88090715
2.https://blog.csdn.net/Heitao5200/article/details/88242389#1__1
3.https://blog.csdn.net/qq_35175666/article/details/89162925
5.https://blog.csdn.net/nc514819873/article/details/89094687
6.https://blog.csdn.net/ljfwz153076024/article/details/89071850#PR_77