NLP第一课(我也是才开始学)
闲着无聊的时候,我就会问问自己,编程也有了五年经验了,除了增删改查,我还会什么,有一天我跳槽,去面试的时候,我能比那些年轻而且期望薪资待遇低的年轻毕业生,我有什么优势,而且我只是一个专科的机电系学生,居然来做软件编程,好戏剧的一切,渐渐的给自己洗脑,自己都忘记自己是培训机构出来的,说了这么多抱怨的话,没有说培训机构的不好,没有说我们专科生就一定比高学历人才的差,归根到底还是需要学习吧,自学了半年多python,现在报了一个假期培训班来学习NLP,英语是硬伤,自己表示很无奈。
言归正传,我来给大家分享一下,我这这段时间学到了什么(2019-06-15至2019-07-01)。
既然我们选择了人工智能,我们就应该知道什么是人工智能,什么是NLP,我们先来明确这个几个名词吧。
人工智能(Artificial Intelligence),英文缩写为AI。它是研究、开发用于模拟、延伸和扩展人的智能的理论、方法、技术及应用系统的一门新的技术科学。人工智能是计算机科学的一个分支,它企图了解智能的实质,并生产出一种新的能以人类智能相似的方式做出反应的智能机器,该领域的研究包括机器人、语言识别、图像识别、自然语言处理和专家系统等。人工智能从诞生以来,理论和技术日益成熟,应用领域也不断扩大,可以设想,未来人工智能带来的科技产品,将会是人类智慧的“容器”。人工智能可以对人的意识、思维的信息过程的模拟。人工智能不是人的智能,但能像人那样思考、也可能超过人的智能。人工智能是一门极富挑战性的科学,从事这项工作的人必须懂得计算机知识,心理学和哲学。人工智能是包括十分广泛的科学,它由不同的领域组成,如机器学习,计算机视觉等等,总的说来,人工智能研究的一个主要目标是使机器能够胜任一些通常需要人类智能才能完成的复杂工作。但不同的时代、不同的人对这种“复杂工作”的理解是不同的。 [1] 2017年12月,人工智能入选“2017年度中国媒体十大流行语”。(百度摘取)
在我这,我认为,人工智能就是希望让我们现有的设备(比如计算机,机器人)来帮助人们做更多的事,并且可以赋予人类的思想,人类的理性和人类的行为的机器。比如我们现在的智能停车场,语音客服,工厂的自动机器人等等。
NLP是神经语言程序学(Neuro-Linguistic Programming)的英文缩写。一般被成为自然语言处理,在我这认为NLP主要是就是让机器可以赋予人类语言正常交流并且赋予人类思想的功能。比如聊天机器人,比如新闻分类,垃圾邮件处理。
我们知道中文的语法比较多,我们先来一个最简单的,生成一句话。现有一个文本,大致为
host = """ host = 时间名词 主语名词 形容词 动词 事务名词 时间名词 = 上午、下午、昨天、晌午、半夜、去年、明天 主语名词 = 学生、群众、老头、妇女、同志、叔叔 形容词 = 很快地、迅速地、悄悄地、静静地 动词 = 打、追着、敲着、吆喝、盯着 事务名词 = 蜗牛、猎豹、奥托、棒球、战斗机、冥王星 """
我们可以看到,文本的第一行为一个句子的元素都有什么,时间名词+主语+(形容词)+动词+(事务名词)可以构成一句话,比如,今晚我们要狠狠的加班。也可以为,明天领导请我们吃大餐。
所有我们在上述文本中按照时间名词+主语+(形容词)+动词+(事务名词)的格式可以组成任意的语句(别考虑有的通不通顺的问题),下面我们来看一下代码的实现。
思路,1-得到文本,2-按照行来切割,3-得到句子元素格式,4-随机从下面的元素集取值,5-按照格式来拼接成句子。
代码:
#!/usr/bin/env python # -*- coding: utf-8 -*- import random host = """ host = 时间名词 主语名词 形容词 动词 事务名词 时间名词 = 上午、下午、昨天、晌午、半夜、去年、明天 主语名词 = 学生、群众、老头、妇女、同志、叔叔 形容词 = 很快地、迅速地、悄悄地、静静地 动词 = 打、追着、敲着、吆喝、盯着 事务名词 = 蜗牛、猎豹、奥托、棒球、战斗机、冥王星 """ # 该方法主要是将文本转换成字典类型的数据 def create_grammar(grammar_str, split='=', line_split='\n', code_split='、'): grammar = {} for line in grammar_str.split(line_split): if line is '': continue k, v = line.split(split) grammar[k.strip()] = [s.split() for s in v.split(code_split)] return grammar # 随机选择 choice = random.choice # 得到句子 def generate(gram, target): if target not in gram: return target else: li = choice(gram[target]) sentence = '' # 最终的句子 aa = [generate(gram, t) for t in li] for s in aa: if s is not '/n': sentence += s return sentence if __name__ == '__main__': for i in range(10): adj = generate(create_grammar(host, '='), target='host') print(adj)
运行后,我们会发现很多句子是错的,完全不符合我们的讲话习惯,所以我们这样的随机选择并不是明智的选择,我们接下来处理这个不明智选择问题,让他尽力做到可以按照人类讲话方式来输出‘固定格式’的话。
下面我来做个小游戏,也是电视节目中常见的,给予提示,让你猜出词语,比如金罐、上火;我们大多数人会第一想到加多宝,比如,我们说教室、黑色,我们会想到黑板;再比如,下午,6点,我们会想到加班。还有等等,也是人类根据前面给予的词语,会立即给予一个反应。这个也就是我最近学到的N-gram
N-gram模型是一种语言模型(Language Model,LM),语言模型是一个基于概率的判别模型,它的输入是一句话(单词的顺序序列),输出是这句话的概率,即这些单词的联合概率(joint probability)。
N-Gram是基于一个假设:第n个词出现与前n-1个词相关,而与其他任何词不相关(这也是隐马尔可夫当中的假设)。整个句子出现的概率就等于各个词出现的概率乘积。各个词的概率可以通过语料中统计计算得到。通常N-Gram取自文本或语料库。N=1时称为unigram,N=2称为bigram,N=3称为trigram,假设下一个词的出现依赖它前面的一个词,即 bigram,假设下一个词的出现依赖它前面的两个词,即 trigram,以此类推。理论上,n 越大越好,经验上,trigram 用的最多,尽管如此,原则上,能用 bigram 解决,绝不使用 trigram。
我们先来看几个公式:
1-gram: P(w1, w2, w3, … , wn)=P(w1)P(w2|w1)P(w3|w1w2)P(w4|w1w2w3)…P(wn|w1w2…wn-1)≈P(w1)P(w2|w1)P(w3|w2)P(w4|w3)…P(wn|wn-1)
2-gram:P(w1, w2, w3, … , wn)=P(w1)P(w2|w1)P(w3|w1w2)P(w4|w1w2w3)…P(wn|w1w2…wn-1)≈P(w1)P(w2|w1)P(w3|w1w2)P(w4|w2w3)…P(wn|wn-2wn-1)
大概来解释一下是什么,P(w1)就是w1在语料库内出现的概率,也就是count(w1)/ total;P(w2|w1)是w2出现在w1后面的概率,也就是说 count(w1w2)/count(w2);我们再用2-gram来看一个实际的例子。
我们喜欢看书,切词以后变为 我们、喜欢、看、书,这时变为P(我们,喜欢,看,书)=p(我们)p(喜欢|我们)p(看|我们,喜欢)p(书|喜欢,看)
p(我们)表示“我们”这个词在语料库里面出现的概率;
p(喜欢|我们)表示“喜欢”这个词出现在“大家”后面的概率;(出现《我们》词语的次数当作分母,出现《我们喜欢》词语的次数当作分子)
p(看|我们,喜欢)表示“看”这个词出现在“我们喜欢”后面的概率;(出现《我们喜欢》的次数当作分母,出现《我们喜欢看》的次数当作分子)
p(书|喜欢,看)表示“书”这个词出现在“我们喜欢看”后面的概率。(出现《喜欢看》的次数当作分母,出现《喜欢看书》当作分子)
以此类推,我们用2-gram时,只考虑其前面两个词语就可以了。
然后他们的乘积我们会得到一个0-1的数字,无限趋近于0表示这个语句很有可能是错的,无限趋近于1的时候表示这个语句很有可能是对的
代码实现还没完成。最近工作烦心事比较多,代码写了一部分,还没有完全弄完的。过几天会补上。