1. 什么是高阶函数与柯里化函数
以Python为例,一个普通函数是这样的:
代码语言:javascript复制def add(a, b):
return a b
一个高阶函数是可以把函数当参数输入的函数,例如:
代码语言:javascript复制def calc(a, b, f):
return f(a, b)
它可以这么调用:
代码语言:javascript复制calc(1, 2, add)
柯里化函数:
# 如下add_2是一个lambda函数,把add这个两参数函数变为了一个单参数的函数,这被称为柯里化
代码语言:javascript复制add_2 = lambda x: add(2 x)
2. 命令式与自然语言式
NLP和对话机器人的一个趋向,似乎就是鄙视命令行,觉得能用自然语言执行就特别厉害。这两者其实本质是等价的,或者说自然语言命令也只是命令的自然语言泛化而已。
代码语言:javascript复制自然语言式:帮我查北京的天气
等价命令式:weather(北京)
或者说这就像是做了多个自然语言到一个命令的泛化,即
代码语言:javascript复制自然语言式:帮我查北京的天气
自然语言式:查天气,北京
自然语言式:北京的天气怎么样?
全部都等价命令式:weather(北京)
3. 上下文、多轮对话、高级函数、柯里化
自然语言对话:
代码语言:javascript复制- 帮我查北京的天气
- 上海呢
命令式等价:
代码语言:javascript复制- weather(北京)
-(上海)
那么有人就会问了,自然语言的第二句是“上海呢”,没提到天气啊,命令式的第二个是(上海),没有查天气啊,这样是不是说明自然语言才有上下文呢?
从自然语言的角度我们可以认为,第二句虽然只说了上海呢,但是其实通过上下文判断,这句话也可以等价改写为“上海的天气呢”。也就是说这里在自然语言中也相当与隐藏了一个来自上下文的天气函数!
假设我们有一个函数是解释命令的,它是一个高阶函数,如:
代码语言:javascript复制def parse_func(cmd_func=None, cmd_parameters=None):
cmd_func(cmd_parameters)
即 parse_func(weather, 北京) 是 weather(北京) 的等价
那我们为了融入weather这个上文怎么做呢?我们需要把上面函数改写为一个高阶函数
代码语言:javascript复制def parse_func(cmd_func=None, cmd_parameters=None, last_func=None, last_parameters=None):
cmd_func = cmd_func or last_func
cmd_parameters = cmd_parameters or last_parameters
cmd_func(cmd_parameters)
return cmd_func, cmd_parameters
即我们调用的时候变成了:
代码语言:javascript复制last_func, last_parameters = None, None
last_func, last_parameters = parse_func(weather, 北京, last_func, last_parameters)
last_func, last_parameters = parse_func(None, 上海, last_func, last_parameters)
也就是说我们通过高阶函数与柯里化确实的相当于解决了上下文问题!
总结
在实际的工程中,当然肯定不需要了解什么是高阶函数什么是柯里化,也并不似乎如上所说这么写的代码。实际中机器人会保存所有上下文变量,就类似我们上面的last_func和last_parameters做为对话状态(Dialog State / Dialog Belief)。而cmd_func和cmd_parameters实际上就是对话中NLU所解析出来的意图(Intent)和槽值(Slot)。