rasa框架nlu源码解析

nlu模块的主要功能是解析用户输入数据,识别出用户输入的实体、意图等关键信息,同时也可以添加诸如情感分析等自定义模块。
nlu模块的包:
在这里插入图片描述
 
1. classifiers模块

Rasa支持的意图分类器有:
在这里插入图片描述
1.1 MitieIntentClassifier
使用MitieNLP的分类器,需要Tokenizer都使用MitieNLP,但是MitieIntentClassifier分类器里边已经自带Featurizer功能,所以不是必须配置的。简单来说,是基于稀疏线性核的一个多分类线性SVM。
1.2 SklearnIntentClassifier
使用SklearnIntentClassifier去做意图识别。Sklearn也是通过SVM做意图识别,只是Sklearn的SVM是通过grid search方法优化的,关于。
1.3 keywordIntentClassifier
简单的关键字匹配意图分类,适用于小型项目,意图比较少的情况。当意图很多,相关性有很大的时候,关键词分类器无法区分。关键字的匹配方式是,训练数据的整句话都作为关键字,去搜索用户说的话。因此写配置数据的时候,仔细设计那个训练数据很重要。关键字不能太长,这容易匹配不上意图。也不能太短,缺少意图的区分度。
1.4 DIETClassifier
DIET模型是Dual Intent and Entity Transformer的简称,解决了对话理解中的两个问题,意图分类和实体识别。DIET使用的是纯监督的方式,没有任何预训练的情况下。无需大规模训练时关键,性能好于fine-tuning Bert,但是训练速度时bert的6倍。输入是用户消息和可选意图的稠密或者稀疏向量。输出是实体,意图和评分。
下面简要介绍下DIET,内容来自Rasa的2020年5月论文翻译。DIET架构如下图,意图是play_game,实体是ping pong,FFW是共享权重。输入特征分为2部分,稠密特征dense features和稀疏特征sparse features。稀疏特征是n-grams(n<5)的one-hot或者multi-hot编码,但是稀疏特征包含很多冗余特征,为了避免过拟合,对此加入了dropout。稠密特征来自预训练模型,如bert或glove等。假如使用ConveRT的_CLS 向量作为DIET的初始输入。这就是作为单词信息之外的句子信息特征了。如果使用BERT,我们使用BERT【CLS】token,对于Glove,我们使用句子所有token的均值作为_CLS。
稀疏特征通过一个全连接计算,其中全连接的权重是和其他序列的时间步全连接共享的,目的是为了让稀疏特征的维度和稠密特征的维度一致,然后将稀疏特征的FFW的输出和稠密特征的向量进行concat拼接,在拼接后面再接一个FFW。FFW权重也是共享的。在实验中,这一层的维度是256.这一步是让稀疏特征和稠密特征合并,并转换成预训练模型的特征维度。
一、输入数据
nlu模块接受Message类型的数据作为输入,与core模块流转的Usermessage数据不同,Message定义在rasa/nlu/training_data/message.py中,默认有三个变量,分别是text、time、data。其中,text中存储的是用户输入的问题,time存储的是时间,data存储的是解析后的数据。

class Message:
	def __init__(self,text:Text,data=None,time=None,output_properties=None) --> None:
	self.text=text
	self.time=time
	self.data=data if data else {
   }

Message中常用的方法是get和set方法,get是从data中取出想要的数据,set是将解析后的intent等信息存入data中。
有的时候,我们可以要传入更多的信息进入nlu模块,例如,在我们的智能客服场景下,需要传入scene_id(场景id),这个时候我们需改源码,以支持传入scene_id,需要修改的py文件如下

rasa/nlu/training_data/message.py
rasa/nlu/model.py
rasa/core/interpreter.py
rasa/core/processor.py

下面将一一解析每一模块代码的作用以及需要修改的部分

  1. message.py
    message.py中定义的class Message是nlu模块传入的数据,它有get、set方法,为了传入其他数据进入nlu模块,我们需要在初始化部分初始化要传输的数据。
class Message:
	def __init__(self,text:Text,prior_info:List[Dict[Text,Any]],data=None,time=None,output_properties=None) --> None:
	self.text=text
	self.prior_info=prior_info
	self.time=time
	self.data=data if data else {
   
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值