语言模型介绍

本文将介绍部分nlp相关概念

1分词

无论对于中文还是英文的文本处理任务,首先要做的都是分词操作。中文常用的是jieba分词,英文则直接按照空格进行分词操作。

1.1、正向最大匹配法:

正向即从前往后取词,从7->1,每次减一个字,直到词典命中或剩下1个单字。

第1次:“我们在野生动物”,扫描7字词典,无

第2次:“我们在野生动”,扫描6字词典,无

。。。。

第6次:“我们”,扫描2字词典,有

扫描中止,输出第1个词为“我们”,去除第1个词后开始第2轮扫描,即:

第2轮扫描:

第1次:“在野生动物园玩”,扫描7字词典,无

第2次:“在野生动物园”,扫描6字词典,无

。。。。

第6次:“在野”,扫描2字词典,有

扫描中止,输出第2个词为“在野”,去除第2个词后开始第3轮扫描,即:

第3轮扫描:

第1次:“生动物园玩”,扫描5字词典,无

第2次:“生动物园”,扫描4字词典,无

第3次:“生动物”,扫描3字词典,无

第4次:“生动”,扫描2字词典,有

扫描中止,输出第3个词为“生动”,第4轮扫描,即:

第4轮扫描:

第1次:“物园玩”,扫描3字词典,无

第2次:“物园”,扫描2字词典,无

第3次:“物”,扫描1字词典,无

扫描中止,输出第4个词为“物”,非字典词数加1,开始第5轮扫描,即:

第5轮扫描:

第1次:“园玩”,扫描2字词典,无

第2次:“园”,扫描1字词典,有

扫描中止,输出第5个词为“园”,单字字典词数加1,开始第6轮扫描,即:

第6轮扫描:

第1次:“玩”,扫描1字字典词,有

扫描中止,输出第6个词为“玩”,单字字典词数加1,整体扫描结束。

正向最大匹配法,最终切分结果为:“我们/在野/生动/物/园/玩”,其中,单字字典词为2,非词典词为1。

1.2、逆向最大匹配法:

逆向即从后往前取词,其他逻辑和正向相同。即:

第1轮扫描:“在野生动物园玩”

第1次:“在野生动物园玩”,扫描7字词典,无

第2次:“野生动物园玩”,扫描6字词典,无

。。。。

第7次:“玩”,扫描1字词典,有

扫描中止,输出“玩”,单字字典词加1,开始第2轮扫描

第2轮扫描:“们在野生动物园”

第1次:“们在野生动物园”,扫描7字词典,无

第2次:“在野生动物园”,扫描6字词典,无

第3次:“野生动物园”,扫描5字词典,有

扫描中止,输出“野生动物园”,开始第3轮扫描

第3轮扫描:“我们在”

第1次:“我们在”,扫描3字词典,无

第2次:“们在”,扫描2字词典,无

第3次:“在”,扫描1字词典,有

扫描中止,输出“在”,单字字典词加1,开始第4轮扫描

第4轮扫描:“我们”

第1次:“我们”,扫描2字词典,有

扫描中止,输出“我们”,整体扫描结束。

逆向最大匹配法,最终切分结果为:“我们/在/野生动物园/玩”,其中,单字字典词为2,非词典词为0。

1.3、双向最大匹配法:

正向最大匹配法和逆向最大匹配法,都有其局限性,我举得例子是正向最大匹配法局限性的例子,逆向也同样存在(如:长春药店,逆向切分为“长/春药店”),因此有人又提出了双向最大匹配法,双向最大匹配法。即,两种算法都切一遍,然后根据大颗粒度词越多越好,非词典词和单字词越少越好的原则,选取其中一种分词结果输出。

如:“我们在野生动物园玩”

正向最大匹配法,最终切分结果为:“我们/在野/生动/物/园/玩”,其中,两字词3个,单字字典词为2,非词典词为1。

逆向最大匹配法,最终切分结果为:“我们/在/野生动物园/玩”,其中,五字词1个,两字词1个,单字字典词为2,非词典词为0。

非字典词:正向(1)>逆向(0)(越少越好)

单字字典词:正向(2)=逆向(2)(越少越好)

总词数:正向(6)>逆向(4)(越少越好)

因此最终输出为逆向结果。

2、语言模型概念

unigram 一元分词,把句子分成一个一个的汉字
bigram 二元分词,把句子从头到尾每两个字组成一个词语
trigram 三元分词,把句子从头到尾每三个字组成一个词语.

2.1 unigram、bigram频率统计

基于python代码

class NGram(object):
 
    def __init__(self, n):
        # n is the order of n-gram language model
        self.n = n
        self.unigram = {}
        self.bigram = {}
    def scan(self, sentence):
        # file your code here
        for line in sentence:
            self.ngram(line.split())
        #unigram
        if self.n == 1:
            try:
                fip = open("data.uni","w")
            except:
                print >> sys.stderr ,"failed to open data.uni"
            for i in self.unigram:
                fip.write("%s %d\n" % (i,self.unigram[i]))
        if self.n == 2:
            try:
                fip = open("data.bi","w")
            except:
                print >> sys.stderr ,"failed to open data.bi"
            for i in self.bigram:
                fip.write("%s %d\n" % (i,self.bigram[i]))
    # caluclate the ngram of the words
    #
    # @param    words       list{str}
    # @return   none
    def ngram(self, words):
        # unigram
        if self.n == 1:
            for word in words:
                if word not in self.unigram:
                    self.unigram[word] = 1
                else:
                    self.unigram[word] = self.unigram[word] + 1
 
        # bigram
        if self.n == 2:
            num = 0
            stri = ''
            for i in words:
                num = num + 1
                if num == 2:
                    stri  = stri + " "
                stri = stri + i
                if num == 2:
                    if stri not in self.bigram:
                        self.bigram[stri] = 1
                    else:
                        self.bigram[stri] = self.bigram[stri] + 1
                    num = 0
                    stri = ''
 
if __name__=="__main__":
    import sys
    try:
        fip = open(sys.argv[1],"r")
    except:
        print >> sys.stderr, "failed to open input file"
    sentence = []
    for line in fip:
        if len(line.strip())!=0:
            sentence.append(line.strip())
    uni = NGram(1)
    bi = NGram(2)
    uni.scan(sentence)
    bi.scan(sentence)
    

3 文本矩阵化

如果是句子,需要进行分词
如果是文件,需要将文件处理为每一行对应一个句子(已经分词,以空格隔开),实例处理过程见文末。

法一:语料处理为列表
from gensim.models import Word2Vec
sentences = [["Python", "深度学习", "机器学习"], ["NLP", "深度学习", "机器学习"]]
model = Word2Vec(sentences, min_count=1)

把Python内置列表当作输入很方便,但当输入量很大的时候,大会占用大量内存。

法二:语料是文件(处理为迭代器)

Gensim需要输入一个可迭代的列表,可以是迭代器,没有必要把一切东西都保存在内存中,提供一个语句,加载处理它,忘记它,加载另一个语句。

一般我们的语料是在文件中存放的,首先,需要保证语料文件内部每一行对应一个句子(已经分词,以空格隔开),方法见上。

对一个目录下的所有文件生效(法1)

这些文件已经被分词好了,如果还需要进一步预处理文件中的单词,如移除数字,提取命名实体… 所有的这些都可以在MySentences 迭代器内进行,保证给work2vec的是处理好的迭代器。

class MySentences(object):
    def __init__(self, dirname):
        self.dirname = dirname

    def __iter__(self):
        for fname in os.listdir(self.dirname):
            for line in open(os.path.join(self.dirname, fname)):
                yield line.split()

sentences = MySentences('/some/directory') # a memory-friendly iterator
model = gensim.models.Word2Vec(sentences)
对于单个文件语料,使用LineSentence

class: gensim.models.word2vec.LineSentence

每一行对应一个句子(已经分词,以空格隔开),我们可以直接用LineSentence把txt文件转为所需要的格式。

LineSentence功能解释:Iterate over a file that contains sentences: one line = one sentence. Words must be already preprocessed and separated by whitespace(对包含句子的文件进行迭代:一行=一句话。单词必须经过预处理,并由空格分隔)

from gensim import Word2Vec
from gensim.Word2Vec import LineSentence
from gensim.test.utils import common_texts, get_tmpfile

# inp为输入语料
inp = 'wiki.zh.text.jian.seg.txt'
sentences = LineSentences(inp)
path = get_tmpfile("word2vec.model") #创建临时文件
model = Word2Vec(sentences, size=100, window=5, min_count=1)
model.save("word2vec.model")
训练
import jieba
import jieba.analyse
from gensim.test.utils import common_texts, get_tmpfile
from gensim.models import Word2Vec
#文件位置需要改为自己的存放路径
#将文本分词
with open('C:\\Users\Administrator\Desktop\\in_the_name_of_people\in_the_name_of_people.txt',encoding='utf-8') as f:
    document = f.read()
    document_cut = jieba.cut(document)
    result = ' '.join(document_cut)
    with open('./in_the_name_of_people_segment.txt', 'w',encoding="utf-8") as f2:
        f2.write(result)
#加载语料
sentences = word2vec.LineSentence('./in_the_name_of_people_segment.txt')
#训练语料
path = get_tmpfile("word2vec.model") #创建临时文件
model = word2vec.Word2Vec(sentences, hs=1,min_count=1,window=10,size=100)
# model.save("word2vec.model")
# model = Word2Vec.load("word2vec.model")
#输入与“贪污”相近的100个词
for key in model.wv.similar_by_word('贪污', topn =100):
    print(key)
#输出了100个,示例前几个
('地皮', 0.9542419910430908)
('高昂', 0.934522807598114)
('证', 0.9154356122016907)
('上强', 0.9113685488700867)
('一抹', 0.9097814559936523)
('得罪', 0.9082552790641785)
('屁股', 0.9072068929672241)
('能伸能屈', 0.9049990177154541)
('二十五万', 0.9045952558517456)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值