NLP概述
NLP = NLU+NLG,本文重点学习NLU
NLU:对于语音/文本,能够理解它所表示的意思
NLG:通过获取的意思,能够生成文本/语音
例:今天参观了苹果公司
现在正好是苹果季节
上面两句话第一句中“苹果”代表一个公司,第二句中“苹果”代表一中食物,那么对于一词多义,我们应该怎么理解句子意思?所以我们可以根据上下文(context)来判断每个单词不同意思的概率,选取最大的概率所表达的意思。
机器翻译
如果我们想把一句中文翻译成英文,可以分成两部,先把中文单词分开对应翻译成英文单词,然后英文单词组合成多种情况的英文句子,通过语言模型来判断哪个英文句子更加合理。
例:今晚的课有意思
1、利用词典将分词汉语对应成英文
今晚/的/课/有意思-----tonight,of,the course,interesting
2、句子组合,利用语言模型根据概率判断
tonight of interesting the course ----概率0.3
tonight of the course interesting—概率0.1
the course of tonight interesting —概率0.85
0.85概率最高,所以选择第三句。
上面两个步骤为翻译模型和语言模型,那么我们可以想办法把两者结合起来进行判别Decoding Algorithm
-
语言模型
给定一句英文e,计算概率p(e)
如果符合英文语法,p(e)高
如果随机语句p(e)低 -
翻译模型
-
给定一对<c,e>,计算p(c|e)
语义相似度高则p(c|e)高
语义相似度低则p(c|e)低 -
Decoding Algorithm
给定语言和翻译模型和c,找出最优的使得p(e)p(c|e)最大
viterbi算法可以将复杂度O(2^N)变为O(n的p次方)
NLP应用场景:问答系统、情感分析、机器翻译、自动摘要、信息抽取
NLP关键技术
Morphology(单词):单词层面的技术(分词,词性等)
Syntax(句子结构):语法分析(各个的依存分析)
Semantic(语义NLU):涉及机器学习算法,(这句话什么意思)
时间/空间复杂度
在实现算法的时候,通常会从两方面考虑算法的复杂度,即时间复杂度和空间复杂度。顾名思义,时间复杂度用于度量算法的计算工作量;空间复杂度用于度量算法占用的内存空间。
时间复杂度
对于一个算法来说,评估运行时间是很难的,因为针对不同大小的输入数据,算法处理所要消耗的时间是不同的,因此通常关注的是时间频度,即算法运行计算操作的次数,记为T(n),其中n称为问题的规模。T(n)是关于n的函数,我们称时间复杂度的极限情形称为算法的“渐近时间复杂度”,记为O(n)。
举个简单例子
# 下面时间复杂度 为O(n^2)
# O(n^2)+ O(n)= O(n^2)
# 空间复杂度为O(1)表示为常数
# 程序中用到a,b两个变量,占用两个空间地址
def compute(a,b):
for i in range(n): # 第一个for执行n^2次操作 时间复杂度O(n^2)
for j in range(n):
a = a + rand()
for j in range(n): # 第二个for执行n次操作 时间复杂度O(n)
b = b + rand()
return s
时间复杂度计算方法:
1.按照函数数量级角度来说,相对增长低的项对相对增长高的项产生的影响很小,可忽略不计。
2.最高项系数对最高项的影响也很小,因此也可以忽略不计。针对第1点,常见的时间复杂度有:常数阶:常数阶:O(1),对数阶:O(log_2 n),线性阶:O(n),k次方阶:O(n^ K), 指数阶:O(2^n)。
根据上述两种特性,总结时间复杂度的计算方法:
1.只取相对增长最高的项,去掉低阶项;
2.去掉最高项的系数;
3.针对常数阶,取时间复杂度为O(1)。
空间复杂度:
空间复杂度指的是算法在内存上临时占用的空间。在递归运算时,由于递归计算是需要使用堆栈的,所以需要考虑堆栈操作占用的内存空间大小。
空间复杂度的计算方法:
1.通常只考虑参数表中为形参分配的存储空间和为函数体中定义的局部变量分配的存储空间(比如变量a=0在算法中空间复杂度为O(1);list_a=[0,1,…,n]的空间复杂度为O(n);set(list_a)的空间复杂度为O(1))。
2.递归函数情况下,空间复杂度等于一次递归调用分配的临时存储空间的大小乘被调用的次数。
斐波那契数
def fib(n):
if n < 3:
return 1
else:
return fib(n-2)+fib(n-1)
时间复杂度为2^0+ 2 ^1…+2 ^n所以为O(2 ^n)
空间复杂度
斐波那契数的空间复杂度英文有递归,需要进行堆栈,其中用到数深度n个地址空间,所以空间复杂度为O(n)
改进的斐波那契数,时间复杂度为O(n),空间复杂度为O(1)代码如下:
def fib(n):
a,b=1,1
c =0
for i in range(2,n):
c = a + b
a = b
b = c
return c
归并排序
上面设需要操作T(n),归并排序后T(n)=T(n/2)+T(n/2)+n,含有递归式,计算时间复杂度需要通过主方法定理实现,计算结果为O(n log n)
Master Theorem(主方法):
Master Theorem是为了计算含有递归调用的算法的时间复杂度的。因为算法中如果含有递归调用算法的情况下使用归纳证明的方法计算时间复杂度是相当困难的,因此我们需要利用Master Theorem来帮我们计算复杂情况下的算法的时间复杂度,Master Theorem定理如下:
Master Theorem的一般形式是T(n) = a T(n / b) + f(n), a >= 1, b > 1。递归项f(n)理解为一个高度为log_b n 的a叉树, 这样总时间频次为 (a ^ log_b n) - 1, 右边的f(n)假设为 nc 那么我们对比一下这两项就会发现 T(n)的复杂度主要取决于 log_b a 与 f(n) 的大小。(log_b a表示以b为底,a的对数)因此我总结了使用Master Theorem的三种case的简单判断:
1.计算log_b a的值,比较n^(log_b a)与f(n)的大小。
2.若n^ (log_b a)>f(n),时间复杂度为O(n^(log_b a)) (case 1)
3.若n^(log_b a)<f(n),时间复杂度为O(f(n)) (case 3)
4.若n^ (log_b a)=f(n),时间复杂度为O(n^ (log_b a)*(log n)^k+1) (case 2) (其中k值为f(n)中如果有log对数项时,该对数项的指数为k,例如,如果f(n)=log n ,k=1;f(n)=n,k=0)