pytorch之诗词生成3--utils

先上代码:


import numpy as np
import settings


def generate_random_poetry(tokenizer, model, s=''):
    """
    随机生成一首诗
    :param tokenizer: 分词器
    :param model: 用于生成古诗的模型
    :param s: 用于生成古诗的起始字符串,默认为空串
    :return: 一个字符串,表示一首古诗
    """
    # 将初始字符串转成token
    token_ids = tokenizer.encode(s)
    # 去掉结束标记[SEP]
    token_ids = token_ids[:-1]
    while len(token_ids) < settings.MAX_LEN:
        # 进行预测,只保留第一个样例(我们输入的样例数只有1)的、最后一个token的预测的、不包含[PAD][UNK][CLS]的概率分布
        output = model(np.array([token_ids, ], dtype=np.int32))
        _probas = output.numpy()[0, -1, 3:]
        del output
        # print(_probas)
        # 按照出现概率,对所有token倒序排列
        p_args = _probas.argsort()[::-1][:100]
        # 排列后的概率顺序
        p = _probas[p_args]
        # 先对概率归一
        p = p / sum(p)
        # 再按照预测出的概率,随机选择一个词作为预测结果
        target_index = np.random.choice(len(p), p=p)
        target = p_args[target_index] + 3
        # 保存
        token_ids.append(target)
        if target == 3:
            break
    return tokenizer.decode(token_ids)


def generate_acrostic(tokenizer, model, head):
    """
    随机生成一首藏头诗
    :param tokenizer: 分词器
    :param model: 用于生成古诗的模型
    :param head: 藏头诗的头
    :return: 一个字符串,表示一首古诗
    """
    # 使用空串初始化token_ids,加入[CLS]
    token_ids = tokenizer.encode('')
    token_ids = token_ids[:-1]
    # 标点符号,这里简单的只把逗号和句号作为标点
    punctuations = [',', '。']
    punctuation_ids = {tokenizer.token_to_id(token) for token in punctuations}
    # 缓存生成的诗的list
    poetry = []
    # 对于藏头诗中的每一个字,都生成一个短句
    for ch in head:
        # 先记录下这个字
        poetry.append(ch)
        # 将藏头诗的字符转成token id
        token_id = tokenizer.token_to_id(ch)
        # 加入到列表中去
        token_ids.append(token_id)
        # 开始生成一个短句
        while True:
            # 进行预测,只保留第一个样例(我们输入的样例数只有1)的、最后一个token的预测的、不包含[PAD][UNK][CLS]的概率分布
            output = model(np.array([token_ids, ], dtype=np.int32))
            _probas = output.numpy()[0, -1, 3:]
            del output
            # 按照出现概率,对所有token倒序排列
            p_args = _probas.argsort()[::-1][:100]
            # 排列后的概率顺序
            p = _probas[p_args]
            # 先对概率归一
            p = p / sum(p)
            # 再按照预测出的概率,随机选择一个词作为预测结果
            target_index = np.random.choice(len(p), p=p)
            target = p_args[target_index] + 3
            # 保存
            token_ids.append(target)
            # 只有不是特殊字符时,才保存到poetry里面去
            if target > 3:
                poetry.append(tokenizer.id_to_token(target))
            if target in punctuation_ids:
                break
    return ''.join(poetry)

我们首先看第一个函数generate_random_poetry,用于随机生成古诗。

def generate_random_poetry(tokenizer, model, s=''):
    """
    随机生成一首诗
    :param tokenizer: 分词器
    :param model: 用于生成古诗的模型
    :param s: 用于生成古诗的起始字符串,默认为空串
    :return: 一个字符串,表示一首古诗
    """

 tokenizer是一个分词器,用于将文本转化为模型可以理解的token序列。

# 将初始字符串转成token
    token_ids = tokenizer.encode(s)
    # 去掉结束标记[SEP]
    token_ids = token_ids[:-1]

是将我们传入的字符串转化为id序列。并使用切片操作切除token序列的最后一个元素。这个元素是用来标记结束标志[SEP]的。

我们接着看:

 while len(token_ids) < settings.MAX_LEN:
        # 进行预测,只保留第一个样例(我们输入的样例数只有1)的、最后一个token的预测的、不包含[PAD][UNK][CLS]的概率分布
        output = model(np.array([token_ids, ], dtype=np.int32))
        _probas = output.numpy()[0, -1, 3:]
        del output

这里我们就可以看出为什么我们要对最后一个 token进行切片处理了,是为了控制预测的长度。

之后我们进行预测,通过model模型对当前的token_ids序列进行预测,model接受一个形状为(batch_size,sequence_length)的输入,这里batch_size为1,sequence_length为token_ids的长度。因此,我们将token_ids包装成一个形状为(1,sequence_length)的numpy数组,并将其传递给model进行预测。

输出的结果是一个3D数组,形状为(1,sequence_length,vocab_size)。其中vocab_size是词汇表,得到的是对下一个词的预测。

然后通过output.numpy()将输出转化为numpy数组,由于我们只关注当前序列的最后一个token的预测结果,所以使用[0,-1,3:]来获取这部分概率分布。具体的,[0,-1]表示获取第一个样例的最后一个token的预测,而[3:]表示去除前三个token,即[PAD],[UNK]和[CLS]。

最后,通过del output释放output变量所占用的内存空间,这样做是为了及时释放内存,避免内存占用过多。

解释一下四个特殊的token在自然语言处理任务中的不同作用。

  • [PAD](填充):在序列中用于填充长度不足的部分,使得序列长度统一,在很多深度学习模型中,要求输入的序列长度是相同的,因此当序列长度不足时,可以使用[PAD]进行填充,使得序列达到统一的长度。
  • [UNK](未知):用于表示模型未见过的或者无法识别的词汇,当模型在处理文本时遇到不在词汇表中的词汇,就会用[UNK]表示,这样可以避免模型对于未知词汇的处理错误。
  • [CLS](分类):在自然语言处理中的一些任务中,例如文本分类,文本语义相似度等,[CLS]被用作特殊的起始标记。模型会将[CLS]作为整个序列的表示,并用于后续任务的处理。例如:对于文本分类任务,模型可以根据[CLS]表示进行预测分类标签。
  • [SEP](分隔符):用于表示序列的分隔,常见于处理多个句子或多个文本之间的任务。他可以用来分隔句子,句子对,文本片段等,在一些任务中,如文本对分类,问答系统等,输入可能包含多个句子或文本片段,模型可以通过识别[SEP]来理解不同句子之间的关系。另外,[SEP]还可以用于标记序列的结束,在一些 情况下,序列的长度是固定的,使用[SEP]标记还可以表示序列的结束。

继续看我们的代码:

 # 按照出现概率,对所有token倒序排列
        p_args = _probas.argsort()[::-1][:100]
        # 排列后的概率顺序
        p = _probas[p_args]
        # 先对概率归一
        p = p / sum(p)
        # 再按照预测出的概率,随机选择一个词作为预测结果
        target_index = np.random.choice(len(p), p=p)
        target = p_args[target_index] + 3
        # 保存
        token_ids.append(target)

 首先,通过argsort()函数对得到的所有outputs进行从小到大的排序,然后经过[::-1]将排序结果进行反转,这样就变成了从大到小的排序,[:100]表示只选择排名前100的token。返回的是_probas中元素从小到大排序的索引数组。

得到索引数组之后,我们通过p=_probas[p_args],根据排名靠前的token的索引p_args,从预测的概率分布_probas中获取对应的概率值,这样得到的p就是排列后的概率顺序(概率值从大到小)。

之后对概率进行归一化,将概率值除以概率之和,使其概率和为1。

target_index = np.random.choice(len(p), p=p)根据参数p(给定的概率分布)在长度为len(p)的范围内进行随机选择,并返回选择的索引target_index。(显然,元素对应的p值越大,被选择的概率就越高)。

后面的target = p_args[target_index] + 3,其中+3是必不可少的,我刚刚因为没有+3就运行报错了,因为我们得到的target是对应于token_ids的索引,而token_ids的前三项是特殊字符,为了和实际中的模型相对应,我们需要将预测的token编号做一些偏离处理。

最后我们将我们的预测列表中加上我们预测的词的索引值,也就是target。

看着一段:

 if target == 3:
        break
return tokenizer.decode(token_ids)

如果生成的target的值是3,表示生成的token是特殊的[CLS]标记,这意味着生成的序列已结束。
返回我们解码之后的结果也就是生成的诗词。等于3的情况是存在的,3意味着结束标志SPE,当句子的长度合适时,其预测的下一个词很可能是3,我们规定3也属于可预测范围。

看生成藏头诗的代码:

def generate_acrostic(tokenizer, model, head):
    """
    随机生成一首藏头诗
    :param tokenizer: 分词器
    :param model: 用于生成古诗的模型
    :param head: 藏头诗的头
    :return: 一个字符串,表示一首古诗
    """
    # 使用空串初始化token_ids,加入[CLS]
    token_ids = tokenizer.encode('')
    token_ids = token_ids[:-1]
    # 标点符号,这里简单的只把逗号和句号作为标点
    punctuations = [',', '。']
    punctuation_ids = {tokenizer.token_to_id(token) for token in punctuations}
    # 缓存生成的诗的list
    poetry = []
    # 对于藏头诗中的每一个字,都生成一个短句
    for ch in head:
        # 先记录下这个字
        poetry.append(ch)
        # 将藏头诗的字符转成token id
        token_id = tokenizer.token_to_id(ch)
        # 加入到列表中去
        token_ids.append(token_id)
        # 开始生成一个短句
        while True:
            # 进行预测,只保留第一个样例(我们输入的样例数只有1)的、最后一个token的预测的、不包含[PAD][UNK][CLS]的概率分布
            output = model(np.array([token_ids, ], dtype=np.int32))
            _probas = output.numpy()[0, -1, 3:]
            del output
            # 按照出现概率,对所有token倒序排列
            p_args = _probas.argsort()[::-1][:100]
            # 排列后的概率顺序
            p = _probas[p_args]
            # 先对概率归一
            p = p / sum(p)
            # 再按照预测出的概率,随机选择一个词作为预测结果
            target_index = np.random.choice(len(p), p=p)
            target = p_args[target_index] + 3
            # 保存
            token_ids.append(target)
            # 只有不是特殊字符时,才保存到poetry里面去
            if target > 3:
                poetry.append(tokenizer.id_to_token(target))
            if target in punctuation_ids:
                break
    return ''.join(poetry)

我们看一下tokenizer.id_to_token(3,2,1,0)

这段代码和上面的随机生成古诗类似,不同的是:

上面的是完整生成一首古诗,其中就算遇到“,”或者“。”不会中断,直到遇到结束符号[SEP]才会中止。

而我们生成的藏头诗是对每一个字进行生成,这里遇到“,”,“。”就进行下一个字的继续生成。然后将每个字的自动生成进行拼接。得到完整的诗句。(当然,遇到[SEP]也是进行终止的,保证了句式的协调)。

return ''.join(poetry)

作用是将我们的peotry中的内容(短句),连接成一个字符串。并将其作为函数值返回。

如果不加join函数的话,输出是一个列表:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/456557.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Kubernetes operator(十) kubebuilder 实战演练 之 开发多版本CronJob【更新中】

云原生学习路线导航页&#xff08;持续更新中&#xff09; 本文是 Kubernetes operator学习 系列第十篇&#xff0c;本节会在前篇开发的Cronjob基础上&#xff0c;进行 多版本Operator 开发的实战 本文的所有代码&#xff0c;都存储于github代码库&#xff1a;https://github.c…

豆瓣书影音存入Notion

使用Python将图书和影视数据存放入Notion中。 &#x1f5bc;️介绍 环境 Python 3.10 &#xff08;建议 3.11 及以上&#xff09;Pycharm / Vs Code / Vs Code Studio 项目结构 │ .env │ main.py - 主函数、执行程序 │ new_book.txt - 上一次更新书籍 │ new_video.…

13-Vue基础之路由

个人名片&#xff1a; &#x1f60a;作者简介&#xff1a;一名大二在校生 &#x1f921; 个人主页&#xff1a;坠入暮云间x &#x1f43c;座右铭&#xff1a;懒惰受到的惩罚不仅仅是自己的失败&#xff0c;还有别人的成功。 &#x1f385;**学习目标: 坚持每一次的学习打卡 文章…

26-1 SQL 注入攻击 - delete注入

环境准备:构建完善的安全渗透测试环境:推荐工具、资源和下载链接_渗透测试靶机下载-CSDN博客 一、注入原理: 对于后台来说,delete操作通常是将对应的id传递到后台,然后后台会删除该id对应的数据。 如果后台没有对接收到的 id 参数进行充分的验证和过滤,恶意用户可能会…

一、NLP中的文本分类

目录 1.0 文本分类的应用场景 1.1 文本分类流程 ​编辑 1.2 判别式模型 1.3 生成式模型 1.4 评估 1.5 参考文献 NLP学习笔记系列&#xff0c;欢迎收藏交流&#xff1a; 零、自然语言处理开篇-CSDN博客 一、NLP中的文本分类-CSDN博客 二、NLP中的序列标注&#xff08;分…

scrcpy远程投屏控制Android

下载 下载后解压压缩包scrcpy-win64-v2.4.zip scrcpy连接手机 1. 有线连接 - 手机开启开发者选项&#xff0c;并开启USB调试&#xff0c;连接电脑&#xff0c;华为手机示例解压scrcpy&#xff0c;在scrcpy目录下打开终端&#xff0c;&#xff08;或添加scrcpy路径为环境变…

NVIDIA vGPU三种授权方式(个人玩家版)

NVIDIA vGPU三种授权方式(个人玩家版) 旧版本的License Server搭建(比较推荐)说明搭建所需文件创建一个Linux虚拟机(我创建的是Ubuntu 18.04.06)修改虚拟机的MAC地址关闭虚拟机的时间同步及修改系统时间安装java安装Apache Tomcat安装许可证服务器软件上传授权文件新版本…

智慧城管:街面秩序沿街商铺视频可视化AI智能监管方案

一、背景分析 随着城市化的加速和商业活动的日益繁荣&#xff0c;沿街商铺的管理面临着越来越多的挑战。沿街商户的乱堆乱放、占道经营、违章停车等违法行为&#xff0c;一直以来都是城市管理中的难题。这不仅存在交通安全隐患&#xff0c;也造成了市容秩序混乱&#xff0c;严…

【CSS3】CSS3 3D 转换示例 - 3D 旋转木马 ( @keyframes 规则 定义动画 | 为 盒子模型 应用动画 | 开启透视视图 | 设置 3D 呈现样式 )

文章目录 一、3D 导航栏示例 - 核心要点1、需求分析2、HTML 结构section 标签 3、CSS 样式keyframes 规则 定义动画为 盒子模型 应用动画开启透视视图设置 3D 呈现样式鼠标移动到控件上方效果设置 6 个子盒子模型的效果 二、完整代码示例1、代码示例2、展示效果 一、3D 导航栏示…

访问者模式(Visitor Pattern)

访问者模式 说明 访问者模式&#xff08;Visitor Pattern&#xff09;属于行为型模式&#xff0c;表示一个作用于某对象结构中的各元素的操作。它使你可以在不改变各元素的类的前提下定义作用于这些元素的新操作。 该模式是将数据结构与数据操作分离的设计模式&#xff0c;是…

实现微服务:匹配系统

HTTP与WebSocket协议 1. HTTP协议是无状态的&#xff0c;每次请求都是独立的&#xff0c;服务器不会保存客户端的状态信息。而WebSocket协议是有状态的&#xff0c;一旦建立连接后&#xff0c;服务器和客户端可以进行双向通信&#xff0c;并且可以保持连接状态&#xff0c;服务…

“遥感+”多技术融合:碳排放监测的创新路径“

在全球环境问题日益严重的今天&#xff0c;以全球变暖为主要特征的气候变化成为了人类面临的巨大挑战。它威胁着地球的生态平衡&#xff0c;对全球可持续发展构成了严峻的挑战。为了应对这一挑战&#xff0c;各国纷纷采取行动&#xff0c;致力于实现碳达峰和碳中和的目标。 在…

Window11安装达梦数据库

由于现在流行国产化&#xff0c;很多公司的数据库产品都使用了国产数据库&#xff0c;所以&#xff0c;今天给大家讲解一下&#xff0c;达梦数据库的安装和试用&#xff0c;这样学完以后&#xff0c;就可以直接在公司里面用了。 首先&#xff0c;需要先注册账号&#xff0c;然…

怎么在家里远程控制公司电脑?

在家远程控制公司办公电脑需求渐增 在家工作也被称为远程办公&#xff0c;可以节省通勤时间&#xff0c;而且也为老板提供了对应的工作成果&#xff0c;是一个一举两得的好方法。 如果您想要在家远程控制公司电脑&#xff0c;先需要在公司的电脑上安装并运行相应的远程工具&a…

css设置选中文字和选中图片字的颜色

要改变页面中选中文字的颜色&#xff0c;可以使用 CSS 的 ::selection 伪元素来实现 *::selection {/* 改变选中文字的背景色 */background-color: #c42121;/* 改变选中文字的文本颜色 */color: #fff; } 用通配符选择器给所有元素都加上了 ::selection伪元素&#xff0c;用于…

CrossOver24软件免费电脑虚拟机,快速在Mac和Linux上运行Windows软件

当然&#xff0c;除了之前提到的核心技术、兼容性和性能优化外&#xff0c;CrossOver2024还具有其他一些值得关注的性能特点&#xff1a; CrossOver Mac-安装包下载如下&#xff1a;https://wm.makeding.com/iclk/?zoneid50028 CrossOver linux-安装包下载如下&#xff1a;ht…

工业界真实的推荐系统(小红书)-离散特征处理、矩阵补充模型、双塔模型

课程特点&#xff1a;系统、清晰、实用&#xff0c;原理和落地经验兼具 b站&#xff1a;https://www.bilibili.com/video/BV1HZ421U77y/?spm_id_from333.337.search-card.all.click&vd_sourceb60d8ab7e659b10ea6ea743ede0c5b48 讲义&#xff1a;https://github.com/wangsh…

linux系统创建私有容器仓库和docker容器的资源限制

私有仓库创建和资源限制 创建私有仓库docker资源限制系统压力测试工具stresscpu资源限制限制CPU Share限制CPU核数CPU绑定 mem资源限制限制IO 创建私有仓库 上传harbor压缩包 解压 下载docker-compose 进入解压后的目录 修改配置文件 mv harbor.yml.tmpl harbor.yml vim harb…

Unity3d Shader篇(十四)— 卡通着色

文章目录 前言一、什么是卡通着色&#xff1f;1. 卡通着色原理2. 卡通着色优缺点优点&#xff1a;缺点&#xff1a; 二、使用步骤1. Shader 属性定义2. SubShader 设置3. 卡通轮廓 Pass4. 卡通主 Pass 三、效果四、总结 前言 卡通着色是一种常见的图形渲染效果&#xff0c;它将…

大语言模型:Query Rewriting for Retrieval-Augmented Large Language Models

总体思路 作者首先指出大语言模型虽然取得了很好的效果&#xff0c;但是仍然存在幻觉和时间顺序混乱的问题&#xff0c;因此需要额外知识库和LLM内部知识库相结合&#xff0c;来修正&#xff1b;因此优化传统的retriever-reader的方案成为需要&#xff1b;目前的研究方案当中使…