文章目录

  • 前言
  • part0 资源准备
    • 基本功能
    • 语料
      • 停用词
      • 问答
      • 闲聊语料
    • 获取
  • part01句的表达
    • 表达
      • one-hot编码
    • 词嵌入
        • 大致原理
        • 实现
          • 简单版
          • 复杂版
            • 如何训练
      • 转换后的形状
  • part02 循环神经网络
    • RNN
      • RNN投影图
      • RNN是三维立体的
    • LSTM&GRU
  • part03意图识别
    • 分词
    • FastText分类
      • FastText网络结构
      • 优化点
    • 构造FastText数据集
    • 训练
  • part04 闲聊对话
    • Seq2Seq
      • 网络结构
      • 输入与输出(编/解码器)
    • 数据准备
      • 构造词典
      • 数据加载
    • 网络搭建
      • 编码器
      • 解码器
      • 注意力机制
    • 训练
      • 搭建seq网络
      • 训练
    • 推理
      • BeamSearch
      • 完整过程
  • Part05 问答处理
    • 简单思路
    • 难点
  • 上文分割线

前言

okey,许久不见甚是想念,那么今天的话也是来开启一个新的一个章节吧。当然承认最近是有在划水,但是问题不大。那么今天的话咱们就是来填一填以前的坑,吹过的牛皮总还是要实现的。那么在这边咱们的目的是实现出一个简单一点的AI助手,通过我们的文本来实现一些对话,问答之类的一些处理。从基础部分,一步一步实现一个这样的小AI,在未来你还可以打造属于自己的一个数据集,同时在这个架构的基础上不断优化,在未来的某一天也许是有机会得到一个专属于你的一个AI对象的。

所以咱们今天给出的还是一个baseline。同时本文的风格也是慢慢来递进的,从最基础的尺度表达,到搭建一个网络,再到基本的优化,最后是一个封装。
项目开源地址:
https://github.com/Huterox/xiaojiejieBoot.git

咱们的这个机器人就叫叫作“小姐姐”。是的非常的直接:Although I have been rejected, I will not give up.
对应语料资源:
https://github.com/codemayq/chinese_chatbot_corpus

基本要求,阅读本篇文章需要一定的门槛:

  • 熟练掌握python
  • 了解基本的深度学习知识
  • 会使用pytorch搭建神经网络
  • 具备一定的抽象能力(受限于篇幅问题,本博文在原理部分只能做简化,因此重点还是实战(或者说,都在代码里面了),但是对应相应内容都会进行一个介绍,和我认为比较容易不太好理解的点,所以如果想要完善理论部分的话,建议自行深入,这里更多是科普,之后是代码实现,你将这部分作为灰盒子就好了,因为你还是可以调参,准备自己的数据集的)

part0 资源准备

ok,在开始之前呢,咱们先来说说在咱们本篇博文当中,咱们是怎么设计的,需要使用到哪些资源。

基本功能

先来看到咱们的这个基本功能的一个样例图吧:

所以的话,咱们这边有问答功能,和闲聊功能,现在的话,那么闲聊的话其实顾名思义,其实就是说如果你想要让这个AI能够就是说像情侣一样对话的话,那么这个闲聊就是咱们的这个恋爱聊天功能,也就是所谓的AI女友的最基本的一个对话雏形。

语料

ok,看到了咱们的一个具体的大致的功能,那么咱们接下来要做的就是说,我们需要使用到哪些东西。首先的话,由于咱们只是先做一个baseline级别的dome,加上咱们的这个算力确实比较那啥。所以的话,咱们的这个语料都是做了一个简要的删减,因为确实是太多了。
那么首先咱们这边使用的主要是这四个东西:

首先第一个是百度问答的问答对一共是5W,还有小黄鸡的一个语料库,大概是50W条问答。
之后第百度停用词和汉语词库。大概就这几个。那么如果你是想要做AI情侣的话,那么就需要把小黄鸡的一个语料库,换成这个对应的恋爱对话的一个语料(你可以尝试把你和你对象的对话搞过来,但是量得足够大,那么咱们这边就不去搞这种,一方面是我搞不到这个数据集,也没有没有办法从自己身上收集,另一方面确实不太合适,但是方法我还是会说的)

之后的话,咱们来看看一看咱们的这个格式:

停用词

打开之后的话,格式大概是这样的:

词库的格式也是类似的。

问答

之后的是问答的一个语料,这个是百度的一个问答,通过数据处理之后的一个格式。这边整理好了。格式是这样的:

问答对。

闲聊语料

这个闲聊也简单,是这样的:

E 是开始标志
M 对话

这个到时候怎么用,咱们在后面再说。

获取

之后的话是咱们的一个资源的获取。
这块的资源的话都已经打包好了在这:
链接:https://pan.baidu.com/s/1Bb0sWcITQLrkibDqIT8Qvg
提取码:6666

part01句的表达

表达

计算机和我们人类是不一样的,他只能进行基本的数字运算,在咱们先前的图像处理当中,图像的表达依然还是通过数值矩阵的,但是一个句子或者单纯是如何表示的呢。所以为了能够让计算机可以处理到咱们的文本数据,咱们需要对文本做一点点处理。

那么在这里是如何做的呢,其实很简单,既然计算机只能处理数字,对数字进行运算,那么我们只需要把我们的一个句子转化为一种向量就好了。那么这个是如何做的呢?

其实非常简单。

看下面一组图就明白了:

我们通过一个词典其实就可以完成一个向量的映射。

看到了吧,我们这个时候我们只需要对一个句子进行分词,之后将每一个词进行标号,这样一来就可以实现把一个句子转化为一个向量。

one-hot编码

此时我们得到了一组序列,但是这个序列的表达能力是在是太弱了,只能表示出一个标号,不能表示出其他的特点。或者说,只有一个数字表示一个词语实在是太单调了,1个词语也应该由一个序列组成。那么这个时候one-hot编码就出来了。他是这样做的:

首先一个词,一个字,我们叫做token,那么编码的很简单。其实就是这样:

但是这样是有问题的,那就是说,我们虽然实现了一个词到向量的表示。但是这个表示方法显然是太大了,假设有10000个词语,那么按照这种方式进行标号的话,那么1个词就是10000个维度。这样显然是不行的。所以这块需要优化一下。

词嵌入

这个原来解释起来稍微复杂一点。你只需要需要知道他们的本质其实就是这样的:
词 ——> 向量空间1 ——> 向量空间2
现在向量空间1不合适,所以我们要想办法能不能往空间2进行靠拢。

于是乎这里大概就有了两个方案:

1)尝试将词向量映射到一个更低维的空间;
2)同时保持词向量在该低维空间中具备语义相似性,如此,越相关的词,它们的向量在这个低维空间里就能靠得越近。

对于第一个,咱们可以参考原来咱们做协同过滤推荐dome的时候,使用SVD矩阵分解来做。(关于这篇博文的话也是有优化的,优化方案将在本篇博文中查看到,先插个眼)

那么缺点的话也很明显嘛,用咱们的这个方案:

1)亲和矩阵的维度可能经常变,因为总有新的单词加进来,每加进来一次就要重新做SVD分解,因此这个方法不太通用;
2)亲和矩阵可能很稀疏,因为很多单词并不会成对出现。

大致原理

ok,回到咱们的这个(这部分可以选择跳过,知道这个玩意最后得到的是啥就好了),这个该怎么做,首先的话,实现这个东西,大概是有两种方案去做:Continuous Bag Of Words (CBOW)方法和n-gram方法。第一个方案的话,这个比较复杂,咱们这里就不介绍了。

咱们来说说第二个方案。

首先咱们来说说啥是N-gram,首先原理的话也是比较复杂的,具体参考这个:https://blog.csdn.net/songbinxu/article/details/80209197

那么我们这边就是简单说一下这个在咱们这边N-gram实际是咋用的。

[cuted[i:i+2]for i in range(len(cuted))]

其实就是这个,用代码表示,cuted是一个分好词的句子。i+2表示跨越几个。

这样做的好处是,通过N-gram可以考虑到词语之间的一个关系,如果我们使用这个方案来实现一个词向量的话,那么我们必然是可以能够实现:“同时保持词向量在该低维空间中具备语义相似性,如此,越相关的词,它们的向量在这个低维空间里就能靠得越近。”的。因为确实考虑到了之间的一个关系,那么现在我们已经知道了大概N-garm是怎么样的了,其实就是一种方式,将一个句子相近的词语进行连接,或者说是对句子进行一个切割,上面那个只是一种方式只有,这个我们在后面还会有说明,总之它是非常好用的一种方式。

ok,知道了这个我们再来介绍几个名词:

1.跳词模型
跳词模型,它是通过文本中某个单词来推测前后几个单词。例如,根据‘rabbit’来推断前后的单词可能为‘a’,‘is’,‘eating’,‘carrot’。在训练模型时我们在文本中选取若干连续的固定长度的单词序列,把前后的一些单词作为输出,中间的某个位置的单词作为输入。

2.连续词袋模型
连续词袋模型与跳词模型恰好相反,它是根据文本序列中周围单词来预测中心词。在训练模型时,把序列中周围单词作为输入,中心词作为输出。

这个的话其实和我们的这个关系不大,因为N-gram其实是句子–>词 的一种方式,但是对我训练的时候的输入还是有帮助的,因为这样输入的话,我们是可以得到词在句子当中的一种关联关系的。

而embedding是词到one-hot然后one-hot到低纬向量的变化过程。

实现

ok,扯了那么多,那么接下来看看我们如何实现这个东西。

我们需要一个词向量,同时我们有很多词语,因此我们将得到一个矩阵,这个矩阵叫做embedding矩阵。

我们首先随机初始化embeddings矩阵,构建一个简单的网络。初始化weights和biases,计算隐藏层的输出。然后计算输出和target结果的交叉熵,之后使用优化器完成一次反向传递,更新可训练的参数,包括embeddings变量。并且我们将词之间的相似度可以看作概率。

ok,我们直接看到代码,那么咱们也是有两个版本的。简单版,复杂版。

简单版

简单版本的话,在pytorch当中有实现:

embed=nn.Embedding(word_num,embedding_dim)
复杂版

那么我们显然是不满足这个的,那么我们还有复杂版本。就是自己动手,丰衣足食!
首先我们定义这个:

class embedding(nn.Module):def __init__(self,in_dim,embed_dim):super().__init__()self.embed=nn.Sequential(nn.Linear(in_dim,200),nn.ReLU(),nn.Linear(200,embed_dim),nn.Sigmoid())def forward(self,input):b,c,_=input.shapeoutput=[]for i in range(c):out=self.embed(input[:,i])output.append(out.detach().numpy())return torch.tensor(np.array(output),dtype=torch.float32).permute(1,0,2)

很简单的一个结构。
那么我们输入是上面,首先其实是我们one-hot编码的一个矩阵。
我们其实流程就是这样的:词—>one-hot—>embedding/svd

ok,那么我们的N-gram如何表示呢,其实这个更多的还是在于对句子的分解上,输入的句子的词向量如何表示的。

如何训练

如何训练的话,首先还是要在one-hot处理的时候再加一个处理,这个过程可能比较绕。就是说我们按照上面提到的词袋模型进行构造我们的数据,我们举个例子吧。

现在有这样的一个文本,分词之后,词的个数是content_size。有num_word个词。

import torch
import re
import numpy as nptxt=[] #文本数据
with open('peter_rabbit.txt',encoding='utf-8') as f:for line in f.readlines():l=line.strip()spilted_sentence=re.split(" |;|-|,|!|\'",l)for w in spilted_sentence:if w !='':txt.append(w.lower())
vol=list(set(txt)) #单词表
n=len(vol) #单词表单词数
vol_dict=dict(zip(vol,np.arange(n))) #单词索引'''
这里使用词袋模型
每次从文本中选取序列长度为9,输入单词数为,8,输出单词数为1,
中心词位于序列中间位置。并且采用pytorch中的emdedding和自己设计embedding两种方法
词嵌入维度为100。
'''
data=[]
label=[]for i in range(content_size):in_words=txt[i:i+4]in_words.extend(txt[i+6:i+10])out_word=txt[i+5]in_one_hot=np.zeros((8,n))out_one_hot=np.zeros((1,n))out_one_hot[0,vol_dict[out_word]]=1for j in range(8):in_one_hot[j,vol_dict[in_words[j]]]=1data.append(in_one_hot)label.append(out_one_hot)class dataset:def __init__(self):self.n=ci=config.content_size def __len__(self):return self.ndef __getitem__(self, item):traindata=torch.tensor(np.array(data),dtype=torch.float32) trainlabel=torch.tensor(np.array(label),dtype=torch.float32)return traindata[item],trainlabel[item]

我们只是在投喂数据的时候按照词袋模型进行投喂,或者连续模型也可以。

当然我们这里所说的都只是说预训练出一个模型出来,实际上,我们直接使用这个结构,然后进行正常的训练完成我们的一个模型也是可以的。她是很灵活的,不是固定的!

那么继续预训练的话就是按照词袋模型来就好了(看不懂没关系,跳过就好了)

import torch
from torch import nn
from torch.utils.data import DataLoader
from dataset import dataset
import numpy as npclass model(nn.Module):def __init__(self):super().__init__()self.embed=embedding(num_word,100)self.fc1=nn.Linear(num_word,1000)self.act1=nn.ReLU()self.fc2=nn.Linear(1000,num_word)self.act2=nn.Sigmoid()def forward(self,input):b,_,_=input.shapeout=self.embed (input).view(b,-1)out=self.fc1 (out)out=self.act1(out)out=self.fc2(out)out=self.act2(out)out=out.view(b,1,-1)return out
if __name__=='__main__':pre_model=model()optim=torch.optim.Adam(params=pre_model.parameters())Loss=nn.MSELoss()traindata=DataLoader(dataset(),batch_size=5,shuffle=True)for i in range(100):print('the {} epoch'.format(i))for d in traindata:p=model(d[0])loss=Loss(p,d[1])optim.zero_grad()loss.backward()optim.step()

这样一来就可以初步完成预训练,你只需要加载好embeding部分的权重就好了,这个只是加快收敛的一种方式。

转换后的形状

最终,词嵌入的话,得到的矩阵是将one-hot变化为了这样的矩阵

ok,词的表达已经

快速构建一个简单的对话+问答AI (上)相关推荐

  1. pyqt5如何循环遍历控件名_如何用 PyQt5 快速构建一个简单的 GUI 应用

    点击上方"Python全家桶","星标"或"置顶" 关键时刻,第一时间送达 本文已获授权,欢迎分享转发 1. 介绍 Python GUI 常 ...

  2. delphi gui编辑工具源码_Python 快速构建一个简单的 GUI 应用

    点击上方"AirPython",选择"加为星标" 第一时间关注 Python 技术干货! 1. 介绍 Python GUI 常用的 3 种框架是:Tkinter ...

  3. [转载] 如何用 PyQt5 快速构建一个简单的 GUI 应用

    参考链接: Python | 使用PyQt设计GUI应用程序 点击上方"AirPython",选择"加为星标" 第一时间关注 Python 技术干货! 1. 介 ...

  4. 知识图谱实战应用11-基于py2neo构建一个简单的问答功能

    大家好,我是微学AI,今天给大家介绍一下知识图谱实战应用10-基于py2neo构建一个简单的问答功能,利用知识图谱来实现智能的问答功能.知识图谱是一种用于表示实体之间关系的图形化模型,它是人工智能和自 ...

  5. 3.2 实战项目二(手工分析错误、错误标签及其修正、快速地构建一个简单的系统(快速原型模型)、训练集与验证集-来源不一致的情况(异源问题)、迁移学习、多任务学习、端到端学习)

    手工分析错误 手工分析错误的大多数是什么 猫猫识别,准确率90%,想提升,就继续猛加材料,猛调优?     --应该先做错误分析,再调优! 把识别出错的100张拿出来, 如果发现50%是"把 ...

  6. 通过python 构建一个简单的聊天服务器

    构建一个 Python 聊天服务器 一个简单的聊天服务器 现在您已经了解了 Python 中基本的网络 API:接下来可以在一个简单的应用程序中应用这些知识了.在本节中,将构建一个简单的聊天服务器.使 ...

  7. 如何使用ChatGPT快速构建一个网站模板

    前端Q 我是winty,专注分享前端知识和各类前端资源,乐于分享各种有趣的事,关注我,一起做个有趣的人- 公众号 点击上方 前端Q,关注公众号 回复加群,加入前端Q技术交流群 英文 | https:/ ...

  8. 如何使用ChatGPT快速构建一个网站模板?

    欢迎来到令人兴奋的自然语言处理和机器学习世界!今天,我们将探索 ChatGPT 的功能,它是由 OpenAI 公司开发的目前最先进的人工智能工具.当然,你也可以将其看作是一个智能机器人.ChatGPT ...

  9. 【jQuery插件】用jQuery Masonry快速构建一个pinterest网站布局(转)

    [jQuery插件]用jQuery Masonry快速构建一个pinterest网站布局 时间:2011年03月21日作者:愚人码头查看次数:29,744 views评论次数:25条评论 前段时间领导 ...

最新文章

  1. 最新!2022中国大学排名发布!
  2. socket模块简单使用
  3. MySQL内存预估_mysql时该如何估算内存的消耗,公式如何计算?
  4. php循环输出多个网络地址图片,php中curl循环往请求多个URL和多线程去请求多个URL的方法...
  5. Win 系统 PyTorch 安装配置教程
  6. Kubernetes学习笔记(一)
  7. dalvik对于Java方法调用的实现
  8. C语言 | 结构体指针
  9. booth算法实现乘法器
  10. FTP 协议和 HTTP 协议的比较
  11. 技术动态 | 知识可视化,连接和探究知识之间的联系!
  12. unixbench类似_UnixBench的实现介绍-阿里云开发者社区
  13. Linux之父:开源不为金钱名利只为娱乐
  14. Java文档阅读笔记-JDBC Driver
  15. linux 下各个工具使用(screen、tmux,pyenv、virtualenv,pip国内源,tree)
  16. Salesforce正面叫板微软Office:5.82亿美元收购Quip
  17. Learun敏捷框架甘特图——摆脱项目管理的泥沼
  18. CDR案例:广告条幅banner设计
  19. Paddle-Lite 安卓端部署
  20. Linux云计算工程师路线

热门文章

  1. 一不小心把此电脑删了,如何把此电脑添加到桌面?
  2. Ubuntu 16.04 4k屏高分辨率卡顿问题
  3. U盘产生快捷方式病毒
  4. linux改mac地址目录,Linux下如何修改网卡MAC地址
  5. Linux系统裁剪与定制
  6. ARX关于块的相关疑难问题整理
  7. 多传感器时频信号处理:多通道非平稳数据的分析工具(Matlab代码实现)
  8. Matlab中的参数解析
  9. SAP UI5 Simple Form 属性 columnsL,columnsM,columnsXL 的属性深入剖析试读版
  10. 【历史上的今天】9 月 29 日:“美国支付宝” Stripe 正式上线;HotJava 面世;VR/AR 领域先驱诞生