清洗文本
import pandas as pd
import jieba
from collections import Counter
TRAIN_PATH = '../DataSets/THUCNews/cnews.train.txt'
STOPWORDS_PATH = '../DataSets/ChineseStopWords.txt'
VOCAB_SIZE = 5000
def read_file(file_name):
'''
读文件
'''
file_path = {'train': TRAIN_PATH}
contents = []
labels = []
with open(file_path[file_name], 'r', encoding='utf-8') as f:
for line in f:
try:
labels.append(line.strip().split('\t')[0])
contents.append(line.strip().split('\t')[1])
except:
pass
data = pd.DataFrame()
data['text'] = contents
data['label'] = labels
return data
def get_stopwordslist(path):
stopwords = [line.strip() for line in open(path, 'r', encoding='utf-8').readlines()]
return stopwords
def pre_data(data):
content = []
stop_words = get_stopwordslist(STOPWORDS_PATH)
for text in data['text']:
for uchar in text:
# 判断是否为汉字
if uchar >= u'\u4e00' and uchar<=u'\u9fa5':
continue
# 判断是否为数字
if uchar >= u'\u0030' and uchar<=u'\u0039':
continue
# 判断是否为英文字母
if (uchar >= u'\u0041' and uchar<=u'\u005a') or (uchar >= u'\u0061' and uchar<=u'\u007a'):
continue
else:
text = text.replace(uchar, '')
# jieba分词
text_jieba = jieba.cut(text, cut_all=False)
# 去停用词
text = []
for word in text_jieba:
if word not in stop_words:
text.append(word)
content.append(text)
return content
def get_wordsCounter(data):
'''
词,字符频率统计
'''
all_content = []
# 把所有的text放到一个list中
for content in data:
all_content.extend(content)
# 对字符频率统计
counter = Counter(all_content)
count_pairs = counter.most_common(VOCAB_SIZE - 1)
words_counter = pd.DataFrame([i[0] for i in count_pairs], columns={'words'})
words_counter['counter'] = [i[1] for i in count_pairs]
return words_counter
train = read_file('train')
train = train.iloc[:100]
content = pre_data(train)
counter_words = get_wordsCounter(content)
print(counter_words)
jieba分词
-
分词
cut
方法,具有3个参数:需要分词的字符串;cut_all 参数用来控制是否采用全模式;HMM 参数用来控制是否使用 HMM 模型。使用全模式会将所有字的组合都切分出来,而精确模式则试图将句子最精确地切开,适合文本分析。import jieba #cut_all=True,开启全模式 sen = jieba.cut('今天二囧正在努力学习', cut_all=True) print('全模式分词:{}'.format('/ '.join(sen))) #cut_all=False,开启精确模式 sen = jieba.cut('今天二囧正在努力学习', cut_all=False) print('精确模式分词:{}'.format('/ '.join(sen)))
运行结果:
-
添加自定义词典
用户可以添加自定义词典,使得分词结果更好1.使用方法:
jieba.load_userdict(file_name)
其中,file_name 为文件类对象或自定义词典的路径词典格式和 dict.txt 一样,一个词占一行;每一行分三部分:词语、词频(可省略)、词性(可省略),用空格隔开,顺序不可颠倒。file_name 若为路径或二进制方式打开的文件,则文件必须为 UTF-8 编码。比如 dict.txt 格式可为:
创新办 3 i
詹皇 2
复联词频省略时使用自动计算的能保证分出该词的词频
2.使用
add_word(word, freq=None, tag=None)
和del_word(word)
可在程序中动态修改词典3.使用
suggest_freq(segment, tune=True)
可调节单个词语的词频,使其能(或不能)被分出来sen = jieba.cut('今天二囧正在努力学习', cut_all=False) print('精确模式分词:{}'.format('/ '.join(sen3))) #提高「二囧」的词频 jieba.suggest_freq('二囧', tune=True) sen = jieba.cut('今天二囧正在努力学习', cut_all=False) print('提高词频后,可以成功分出「二囧」:{}'.format('/ '.join(sen3)))
运行结果:
词、字符数量统计
-
中文文本
词统计思路:首先使用 jieba 分词,然后使用 Python collections 模块的 Counter 类来统计词的数量字符统计思路:可以直接使用 Counter 类来统计字符的数量
from collections import Counter sen = 'jieba分词和NLTK都可以用于NLP任务中的分词环节' ci = list(jieba.cut(sen, cut_all=False)) print('词统计:{}'.format(Counter(ci))) print('=' * 100) zifu = list(sen) print('字符统计:{}'.format(Counter(zifu)))
运行结果:
-
英文文本
可以使用 NLTK 库处理英文文本的分词,并进行统计。
语言模型
-
统计语言模型
统计语言模型( Statistical Language Model),是今天所有自然语言处理的基础,并且广泛应用于机器翻译、语音识别、印刷体或手写体识别、拼写纠错、汉字输入和文献查询,而在NLP中可以用于衡量一个句子是否有实际意义,即计算一个句子的概率。
假定S表示某一个有意义的句子,由一连串特定顺序排列的词W1,W2,…,Wn组成,这里n是句子的长度(句子中词汇的个数)。于是S出现的可能性也就是数学上所说的S的概率P(S)=P(W1, W2, …, Wn),利用条件概率公式,以上算式可以展开为:
P(W1, W2, …, Wn) = P(W1)*P(W2|W1)*P(W3|W1,W2)…P(Wn|W1,W2,…,Wn-1)
其中P(W1)表示第一个词W1出现的概率;P(W2|W1)是在已知第一个词的前提下,第二个词出现的概率;以此类推,词Wn出现的概率取决于它前面所有的词。
从计算上来看,第一个词的条件概率P(W1)很容易算,第二个词的条件概率P(W2|W1)也还不太麻烦,第三个词的条件概率P(W3|w1,w2)已经非常难算了,因为它涉及到三个变量W1,W2,W3,每个变量的可能性都是种语言字典的大小。到了最后一个词Wn,条件概率P(wn|w1,w2,…,Wn-1)的可能性太多,无法估算,只能采用近似计算的方法。从19世纪到20世纪初,俄国有个数学家叫马尔可夫( Andrey Markov),他提出了一种偷懒但还颇为有效的方法,也就是每当遇到这种情况时,就假设任意一个词Wi出现的概率只同它前面的词Wi-1有关,于是问题就变得很简单了。这种假设在数学上称为马尔可夫假设。
现在,S出现的概率就变得简单了:P(S)=P(W1)*P(W2|W1)*P(W3|W2)…P(Wn|Wn-1)
上述公式就是统计语言模型的二元模型(Bigram Model)。
接下来的问题就是如何计算P(Wn|Wn-1),根据概率论,该公式可以变化为:P(Wn|Wn-1)=P(Wn-1,Wn)/P(Wn-1)
因为在互联网时代有大量的语料库(Corpus)可以作为训练样本,所以只要数一数Wn-1、Wn这对词在语料库中前后相邻出现了多少次,以及Wn-1本身在相同的语料库中出现了多少次,就可得到 P(Wn|Wn-1)。
-
n-gram 语言模型
n-gram 模型就是统计语言模型的一种近似求解方法,它的基本思想是将文本里面的内容按照字节进行大小为N的滑动窗口操作,形成了长度是N的字节片段序列。n-gram 模型也称为n-1阶马尔科夫模型,它有一个有限历史假设:当前词的出现概率仅仅与前面n-1个词相关。因此统计语言模型中的P(S)可以近似为:
当n取1、2、3时,n-gram模型分别称为unigram、bigram和trigram语言模型。unigram 表示以每一个字进行划分,bigram 表示以每两个字进行划分,trigram 表示以每三个字进行划分。
n-gram模型的参数就是条件概率P(Wi|Wi-n+1,…,Wi-1)。假设词表的大小为100,000,那么n-gram模型的参数数量为100,000n。n越大,模型越准确,也越复杂,需要的计算量越大。最常用的是bigram,其次是unigram和trigram,n取≥4的情况较少。