深度学习----------------------文本预处理

目录

  • 文本预处理
    • 读取数据集
    • 词源化
    • 词表
      • 该部分总代码
      • 该部分总代码
    • 整合所有功能
      • 该部分总代码

文本预处理

文本预处理:把文本当作一个时序序列

将解析文本的常见预处理步骤。 这些步骤通常包括:

①将文本作为字符串加载到内存中。
②将字符串拆分为词元(如单词和字符)。
③建立一个词表,将拆分的词元映射到数字索引。
④将文本转换为数字索引序列,方便模型操作。

import collections
import re
from d2l import torch as d2l



读取数据集

将数据集读取到由多条文本行组成的列表中

import re
from d2l import torch as d2l# @save
# 字典的值是一个元组,包含数据集的URL(d2l.DATA_URL + 'timemachine.txt')和数据的哈希值('090b5e7e70c295757f55df93cb0a180b9691891a')
# 用于验证下载数据的完整性。
d2l.DATA_HUB['time_machine'] = (d2l.DATA_URL + 'timemachine.txt','090b5e7e70c295757f55df93cb0a180b9691891a')def read_time_machine():  # @save"""将时间机器数据集加载到文本行的列表中"""with open(d2l.download('time_machine'), 'r') as f:# 打开文件取所有行到lines列表中。lines = f.readlines()# re.sub('[^A-Za-z]+', ' ', line)是将非字母字符替换为空格,这里是为了去掉标点符号# .strip()是去掉提取的字符串两端的空白# .lower()是将所有字母都设置为小写字母return [re.sub('[^A-Za-z]+', ' ', line).strip().lower() for line in lines]lines = read_time_machine()
print(f'# 文本总行数: {len(lines)}')
# 看一下列表中的第1行内容和第11行内容
print(lines[0])
print(lines[10])

在这里插入图片描述




词源化

每个文本序列又被拆分成一个标记列表

文本行列表(lines)作为输入,列表中的每个元素是一个文本序列(如一条文本行)。每个文本序列又被拆分成一个词元列表,词元(token)是文本的基本单位。最后,返回一个由词元列表组成的列表,其中的每个词元都是一个字符串(string)。

import re
from d2l import torch as d2l# @save
# 字典的值是一个元组,包含数据集的URL(d2l.DATA_URL + 'timemachine.txt')和数据的哈希值('090b5e7e70c295757f55df93cb0a180b9691891a')
# 用于验证下载数据的完整性。
d2l.DATA_HUB['time_machine'] = (d2l.DATA_URL + 'timemachine.txt','090b5e7e70c295757f55df93cb0a180b9691891a')def read_time_machine():  # @save"""将时间机器数据集加载到文本行的列表中"""with open(d2l.download('time_machine'), 'r') as f:# 打开文件取所有行,并将每行存储在列表 lines 中lines = f.readlines()# re.sub('[^A-Za-z]+', ' ', line)是将非字母字符替换为空格,这里是为了去掉标点符号# .strip()是去掉提取的字符串两端的空白# .lower()是将所有字母都设置为小写字母return [re.sub('[^A-Za-z]+', ' ', line).strip().lower() for line in lines]def tokenize(lines, token='word'):  # @save"""将文本行拆分为单词或字符词元"""if token == 'word':# 以空格为分隔符将每行字符串拆分为单词列表return [line.split() for line in lines]elif token == 'char':# 将每行字符串拆分为字符列表return [list(line) for line in lines]else:print('错误:未知词元类型:' + token)lines = read_time_machine()
# 对 lines 进行分词处理,使用默认的 'word' 令牌类型
tokens = tokenize(lines)
# 打印前11行的分词结果
for i in range(11):# 空列表表示空行print(tokens[i])

在这里插入图片描述




词表

词元的类型是字符串,而模型需要的输入是数字,因此这种类型不方便模型使用。所以构建一个字典,通常也叫做词表(vocabulary),用来将字符串类型的词元映射到从0开始的数字索引中

我们先将训练集中的所有文档合并在一起,对它们的唯一词元进行统计,得到的统计结果称之为语料(corpus)。然后根据每个唯一词元的出现频率,为其分配一个数字索引。很少出现的词元通常被移除,这可以降低复杂性。 另外,语料库中不存在或已删除的任何词元都将映射到一个特定的未知词元。我们可以选择增加一个列表,用于保存那些被保留的词元。

例如:填充词元(“<pad>”); 序列开始词元(“<bos>”); 序列结束词元(“<eos>”)
class Vocab:  #@save"""文本词表"""def __init__(self, tokens=None, min_freq=0, reserved_tokens=None):if tokens is None:tokens = []if reserved_tokens is None:reserved_tokens = []# 按出现频率排序counter = count_corpus(tokens)self._token_freqs = sorted(counter.items(), key=lambda x: x[1],reverse=True)# 未知词元的索引为0self.idx_to_token = ['<unk>'] + reserved_tokensself.token_to_idx = {token: idxfor idx, token in enumerate(self.idx_to_token)}for token, freq in self._token_freqs:# 出现频率< min_freq的token去掉,min_freq=0时表示包括所有tokenif freq < min_freq:breakif token not in self.token_to_idx:self.idx_to_token.append(token)self.token_to_idx[token] = len(self.idx_to_token) - 1def __len__(self):return len(self.idx_to_token)# 返回给定tokens的indexsdef __getitem__(self, tokens):if not isinstance(tokens, (list, tuple)):return self.token_to_idx.get(tokens, self.unk)return [self.__getitem__(token) for token in tokens]# 返回给定indexs对于的tokensdef to_tokens(self, indices):if not isinstance(indices, (list, tuple)):return self.idx_to_token[indices]return [self.idx_to_token[index] for index in indices]@propertydef unk(self):  # 未知词元的索引为0return 0@propertydef token_freqs(self):return self._token_freqsdef count_corpus(tokens):  #@save"""统计词元的频率"""# 这里的tokens是1D列表或2D列表if len(tokens) == 0 or isinstance(tokens[0], list):# 将词元列表展平成一个列表tokens = [token for line in tokens for token in line]# Counter 对象内部使用字典来存储元素及其对应的计数,元素作为键,计数作为值return collections.Counter(tokens)

首先使用时光机器数据集作为语料库来构建词表,然后打印前几个高频词元及其索引。

vocab = Vocab(tokens)
print(list(vocab.token_to_idx.items())[:10])



该部分总代码

import collections
import re
from d2l import torch as d2lclass Vocab:  # @save"""文本词表"""# 接受三个参数:tokens(词元列表,默认为空列表)、min_freq(最小词频,默认为0)、reserved_tokens(保留词元列表,默认为空列表)。def __init__(self, tokens=None, min_freq=0, reserved_tokens=None):if tokens is None:tokens = []if reserved_tokens is None:reserved_tokens = []# 按出现频率排序# 统计tokens中每个词元的频率,并将结果存储在counter中。counter = count_corpus(tokens)# 对counter中的项按频率降序排序,并将排序后的列表存储在_token_freqs属性中。self._token_freqs = sorted(counter.items(), key=lambda x: x[1], reverse=True)# 未知词元的索引为0# 初始化一个列表,其中包含未知词元(<unk>)和保留词元(reserved_tokens),该列表用于将索引映射到词元。self.idx_to_token = ['<unk>'] + reserved_tokens# 创建一个字典,将idx_to_token列表中的词元映射到其索引。self.token_to_idx = {token: idxfor idx, token in enumerate(self.idx_to_token)}for token, freq in self._token_freqs:# 出现频率< min_freq的token去掉,min_freq=0时表示包括所有tokenif freq < min_freq:breakif token not in self.token_to_idx:self.idx_to_token.append(token)self.token_to_idx[token] = len(self.idx_to_token) - 1def __len__(self):# 返回idx_to_token列表的长度,即词表的大小。return len(self.idx_to_token)# 返回给定tokens的indexsdef __getitem__(self, tokens):# 检查tokens是否是列表或元组,如果不是,则假设它是一个单个词元。if not isinstance(tokens, (list, tuple)):# 如果tokens是单个词元,尝试从token_to_idx中获取其索引,如果未找到,则返回未知词元的索引(self.unk)。return self.token_to_idx.get(tokens, self.unk)return [self.__getitem__(token) for token in tokens]# 返回给定indexs对于的tokensdef to_tokens(self, indices):# 将单个索引转换为单个词元。if not isinstance(indices, (list, tuple)):return self.idx_to_token[indices]# 将索引列表转换为对应的词元列表return [self.idx_to_token[index] for index in indices]@propertydef unk(self):  # 未知词元的索引为0return 0@propertydef token_freqs(self):# 返回按频率排序的词元频率列表。return self._token_freqs# 统计给定词元列表中每个词元的频率。
def count_corpus(tokens):  # @save"""统计词元的频率"""# 这里的tokens是1D列表或2D列表# 检查tokens是否为空或第一个元素是否为列表,以确定是否需要展平。if len(tokens) == 0 or isinstance(tokens[0], list):# 将词元列表展平成一个列表tokens = [token for line in tokens for token in line]# 统计展平后词元列表中每个词元的频率# Counter 对象内部使用字典来存储元素及其对应的计数,元素作为键,计数作为值return collections.Counter(tokens)def read_time_machine():  # @save"""将时间机器数据集加载到文本行的列表中"""with open(d2l.download('time_machine'), 'r') as f:# 打开文件取所有行,并将每行存储在列表 lines 中lines = f.readlines()# re.sub('[^A-Za-z]+', ' ', line)是将非字母字符替换为空格,这里是为了去掉标点符号# .strip()是去掉提取的字符串两端的空白# .lower()是将所有字母都设置为小写字母return [re.sub('[^A-Za-z]+', ' ', line).strip().lower() for line in lines]def tokenize(lines, token='word'):  # @save"""将文本行拆分为单词或字符词元"""if token == 'word':# 以空格为分隔符将每行字符串拆分为单词列表return [line.split() for line in lines]elif token == 'char':# 将每行字符串拆分为字符列表return [list(line) for line in lines]else:print('错误:未知词元类型:' + token)# @save
# 字典的值是一个元组,包含数据集的URL(d2l.DATA_URL + 'timemachine.txt')和数据的哈希值('090b5e7e70c295757f55df93cb0a180b9691891a')
# 用于验证下载数据的完整性。
d2l.DATA_HUB['time_machine'] = (d2l.DATA_URL + 'timemachine.txt','090b5e7e70c295757f55df93cb0a180b9691891a')
lines = read_time_machine()
# 对 lines 进行分词处理,使用默认的 'word' 令牌类型
tokens = tokenize(lines)
vocab = Vocab(tokens)
# vocab.token_to_idx是字典属性,键是词汇(tokens),值是它们对应的索引(indices)
# 将items()返回的视图对象转换成一个列表(list)
print(list(vocab.token_to_idx.items())[:10])

在这里插入图片描述


将每一条文本行转换成一个数字索引列表

for i in [0, 10]:print('文本:', tokens[i])print('索引:', vocab[tokens[i]])

该部分总代码

import collections
import re
from d2l import torch as d2lclass Vocab:  # @save"""文本词表"""# 接受三个参数:tokens(词元列表,默认为空列表)、min_freq(最小词频,默认为0)、reserved_tokens(保留词元列表,默认为空列表)。def __init__(self, tokens=None, min_freq=0, reserved_tokens=None):if tokens is None:tokens = []if reserved_tokens is None:reserved_tokens = []# 按出现频率排序# 统计tokens中每个词元的频率,并将结果存储在counter中。counter = count_corpus(tokens)# 对counter中的项按频率降序排序,并将排序后的列表存储在_token_freqs属性中。self._token_freqs = sorted(counter.items(), key=lambda x: x[1], reverse=True)# 未知词元的索引为0# 初始化一个列表,其中包含未知词元(<unk>)和保留词元(reserved_tokens),该列表用于将索引映射到词元。self.idx_to_token = ['<unk>'] + reserved_tokens# 创建一个字典,将idx_to_token列表中的词元映射到其索引。self.token_to_idx = {token: idxfor idx, token in enumerate(self.idx_to_token)}for token, freq in self._token_freqs:# 出现频率< min_freq的token去掉,min_freq=0时表示包括所有tokenif freq < min_freq:breakif token not in self.token_to_idx:self.idx_to_token.append(token)self.token_to_idx[token] = len(self.idx_to_token) - 1def __len__(self):# 返回idx_to_token列表的长度,即词表的大小。return len(self.idx_to_token)# 返回给定tokens的indexsdef __getitem__(self, tokens):# 检查tokens是否是列表或元组,如果不是,则假设它是一个单个词元。if not isinstance(tokens, (list, tuple)):# 如果tokens是单个词元,尝试从token_to_idx中获取其索引,如果未找到,则返回未知词元的索引(self.unk)。return self.token_to_idx.get(tokens, self.unk)return [self.__getitem__(token) for token in tokens]# 返回给定indexs对于的tokensdef to_tokens(self, indices):# 将单个索引转换为单个词元。if not isinstance(indices, (list, tuple)):return self.idx_to_token[indices]# 将索引列表转换为对应的词元列表return [self.idx_to_token[index] for index in indices]@propertydef unk(self):  # 未知词元的索引为0return 0@propertydef token_freqs(self):# 返回按频率排序的词元频率列表。return self._token_freqs# 统计给定词元列表中每个词元的频率。
def count_corpus(tokens):  # @save"""统计词元的频率"""# 这里的tokens是1D列表或2D列表# 检查tokens是否为空或第一个元素是否为列表,以确定是否需要展平。if len(tokens) == 0 or isinstance(tokens[0], list):# 将词元列表展平成一个列表tokens = [token for line in tokens for token in line]# 统计展平后词元列表中每个词元的频率# Counter 对象内部使用字典来存储元素及其对应的计数,元素作为键,计数作为值return collections.Counter(tokens)def read_time_machine():  # @save"""将时间机器数据集加载到文本行的列表中"""with open(d2l.download('time_machine'), 'r') as f:# 打开文件取所有行,并将每行存储在列表 lines 中lines = f.readlines()# re.sub('[^A-Za-z]+', ' ', line)是将非字母字符替换为空格,这里是为了去掉标点符号# .strip()是去掉提取的字符串两端的空白# .lower()是将所有字母都设置为小写字母return [re.sub('[^A-Za-z]+', ' ', line).strip().lower() for line in lines]def tokenize(lines, token='word'):  # @save"""将文本行拆分为单词或字符词元"""if token == 'word':# 以空格为分隔符将每行字符串拆分为单词列表return [line.split() for line in lines]elif token == 'char':# 将每行字符串拆分为字符列表return [list(line) for line in lines]else:print('错误:未知词元类型:' + token)# @save
# 字典的值是一个元组,包含数据集的URL(d2l.DATA_URL + 'timemachine.txt')和数据的哈希值('090b5e7e70c295757f55df93cb0a180b9691891a')
# 用于验证下载数据的完整性。
d2l.DATA_HUB['time_machine'] = (d2l.DATA_URL + 'timemachine.txt','090b5e7e70c295757f55df93cb0a180b9691891a')
lines = read_time_machine()
# 对 lines 进行分词处理,使用默认的 'word' 令牌类型
tokens = tokenize(lines)
vocab = Vocab(tokens)
for i in [0, 10]:print('文本:', tokens[i])print('索引:', vocab[tokens[i]])

在这里插入图片描述



整合所有功能

将所有功能打包到load_corpus_time_machine函数中,该函数返回corpus词元索引列表)和vocab时光机器语料库的词表)。 我们在这里所做的改变是:

为了简化后面章节中的训练,我们使用字符(而不是单词)实现文本词元化

时光机器数据集中的每个文本行不一定是一个句子或一个段落,还可能是一个单词,因此返回的corpus仅处理为单个列表,而不是使用多词元列表构成的一个列表。

def load_corpus_time_machine(max_tokens=-1):  #@save"""返回时光机器数据集的词元索引列表和词表"""lines = read_time_machine()tokens = tokenize(lines, 'char')vocab = Vocab(tokens)# 因为时光机器数据集中的每个文本行不一定是一个句子或一个段落,# 所以将所有文本行展平到一个列表中corpus = [vocab[token] for line in tokens for token in line]# max_tokens>0意为限制返回的词元数量,为-1即为返回所有词元if max_tokens > 0: corpus = corpus[:max_tokens]return corpus, vocabcorpus, vocab = load_corpus_time_machine()
len(corpus), len(vocab)

该部分总代码

import collections
import re
from d2l import torch as d2lclass Vocab:  # @save"""文本词表"""# 接受三个参数:tokens(词元列表,默认为空列表)、min_freq(最小词频,默认为0)、reserved_tokens(保留词元列表,默认为空列表)。def __init__(self, tokens=None, min_freq=0, reserved_tokens=None):if tokens is None:tokens = []if reserved_tokens is None:reserved_tokens = []# 按出现频率排序# 统计tokens中每个词元的频率,并将结果存储在counter中。counter = count_corpus(tokens)# 对counter中的项按频率降序排序,并将排序后的列表存储在_token_freqs属性中。self._token_freqs = sorted(counter.items(), key=lambda x: x[1], reverse=True)# 未知词元的索引为0# 初始化一个列表,其中包含未知词元(<unk>)和保留词元(reserved_tokens),该列表用于将索引映射到词元。self.idx_to_token = ['<unk>'] + reserved_tokens# 创建一个字典,将idx_to_token列表中的词元映射到其索引。self.token_to_idx = {token: idxfor idx, token in enumerate(self.idx_to_token)}for token, freq in self._token_freqs:# 出现频率< min_freq的token去掉,min_freq=0时表示包括所有tokenif freq < min_freq:breakif token not in self.token_to_idx:self.idx_to_token.append(token)self.token_to_idx[token] = len(self.idx_to_token) - 1def __len__(self):# 返回idx_to_token列表的长度,即词表的大小。return len(self.idx_to_token)# 返回给定tokens的indexsdef __getitem__(self, tokens):# 检查tokens是否是列表或元组,如果不是,则假设它是一个单个词元。if not isinstance(tokens, (list, tuple)):# 如果tokens是单个词元,尝试从token_to_idx中获取其索引,如果未找到,则返回未知词元的索引(self.unk)。return self.token_to_idx.get(tokens, self.unk)return [self.__getitem__(token) for token in tokens]# 返回给定indexs对于的tokensdef to_tokens(self, indices):# 将单个索引转换为单个词元。if not isinstance(indices, (list, tuple)):return self.idx_to_token[indices]# 将索引列表转换为对应的词元列表return [self.idx_to_token[index] for index in indices]@propertydef unk(self):  # 未知词元的索引为0return 0@propertydef token_freqs(self):# 返回按频率排序的词元频率列表。return self._token_freqs# 统计给定词元列表中每个词元的频率。
def count_corpus(tokens):  # @save"""统计词元的频率"""# 这里的tokens是1D列表或2D列表# 检查tokens是否为空或第一个元素是否为列表,以确定是否需要展平。if len(tokens) == 0 or isinstance(tokens[0], list):# 将词元列表展平成一个列表tokens = [token for line in tokens for token in line]# 统计展平后词元列表中每个词元的频率# Counter 对象内部使用字典来存储元素及其对应的计数,元素作为键,计数作为值return collections.Counter(tokens)def read_time_machine():  # @save"""将时间机器数据集加载到文本行的列表中"""with open(d2l.download('time_machine'), 'r') as f:# 打开文件取所有行,并将每行存储在列表 lines 中lines = f.readlines()# re.sub('[^A-Za-z]+', ' ', line)是将非字母字符替换为空格,这里是为了去掉标点符号# .strip()是去掉提取的字符串两端的空白# .lower()是将所有字母都设置为小写字母return [re.sub('[^A-Za-z]+', ' ', line).strip().lower() for line in lines]def tokenize(lines, token='word'):  # @save"""将文本行拆分为单词或字符词元"""if token == 'word':# 以空格为分隔符将每行字符串拆分为单词列表return [line.split() for line in lines]elif token == 'char':# 将每行字符串拆分为字符列表return [list(line) for line in lines]else:print('错误:未知词元类型:' + token)def load_corpus_time_machine(max_tokens=-1):  # @save"""返回时光机器数据集的词元索引列表和词表"""lines = read_time_machine()tokens = tokenize(lines, 'char')vocab = Vocab(tokens)# 因为时光机器数据集中的每个文本行不一定是一个句子或一个段落,# 所以将所有文本行展平到一个列表中corpus = [vocab[token] for line in tokens for token in line]# max_tokens>0意为限制返回的词元数量,为-1即为返回所有词元if max_tokens > 0:corpus = corpus[:max_tokens]return corpus, vocabcorpus, vocab = load_corpus_time_machine()
print(len(corpus))
print(len(vocab))

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

【数据结构篇】~链表算法题3(环形链表)

链表算法题3&#xff08;环形链表&#xff09; 环形链表的证明1. 环形链表I​1) 思路2&#xff09;代码实现 2. 环形链表II​1) 思路11) 思路22&#xff09;代码实现 环形链表的证明 1. 环形链表I​ https://leetcode.cn/problems/linked-list-cycle/description/ 1) 思路 判断…

Nginx搭建直播服务器,并用rtmp,http-flv,hls三种模式拉流观看直播的流程

一、首先搭建直播服务器 环境widows&#xff0c;并且已经集成了 &#xff1a;nginx-http-flv-module模块 nginx.conf配置如下&#xff1a; worker_processes 1;#error_log logs/error.log; #error_log logs/error.log notice; #error_log logs/error.log info; #error…

计算机人工智能前沿进展-大语言模型方向-2024-09-15

计算机人工智能前沿进展-大语言模型方向-2024-09-15 1. Towards the holistic design of alloys with large language models Z Pei, J Yin, J Neugebauer, A Jain - Nature Reviews Materials, 2024 利用大型语言模型实现合金的全面设计 摘要 文章讨论了大型语言模型在材料…

nginx服务器安装和部署代理

文章目录 Linux下面安装nginx nginx下载官网: [nginx: download](https://nginx.org/en/download.html) 使用yum命令安装gcc环境 yum install -y wget gcc-c pcre-devel zlib-devel openssl-devel//安装多个环境 wget gcc pcre-devel 支持正则表达式 zlib-devel提供了压缩和…

CleanClip vs 传统剪贴板:究竟谁更胜一筹?

在日常工作和生活中,复制粘贴可以说是我们使用最频繁的操作之一。传统的剪贴板功能虽然简单易用,但在功能性和效率上还有很大的提升空间。今天,我们就来比较一下新兴的剪贴板增强工具CleanClip与传统剪贴板,看看到底谁更胜一筹。 1. 剪贴历史管理 传统剪贴板只能存储最后一次…

Java项目实战II基于Java+Spring Boot+MySQL的图书管理系统的设计与实现 (源码+数据库+文档)

目录 一、前言 二、技术介绍 三、系统实现 四、论文参考 五、核心代码 六、源码获取 全栈码农以及毕业设计实战开发&#xff0c;CSDN平台Java领域新星创作者&#xff0c;专注于大学生项目实战开发、讲解和毕业答疑辅导。获取源码联系方式请查看文末 一、前言 在信息爆炸…

【图虫创意-注册安全分析报告-无验证方式导致安全隐患】

前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 1. 暴力破解密码&#xff0c;造成用户信息泄露 2. 短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉 3. 带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大&#xff0c;造…

用来用去还是用回了ueditor-Vue富文本编辑器二次扩展

用来用去还是用回了ueditor-Vue富文本编辑器二次扩展。我们使用用过UEditor、TinyMCE、CKEditor、wangEditor、Tiptap、Quill项目经历过多次富文本的编辑器的选型使用&#xff0c;发现现在新的富文本编辑总感觉还是没达到我们的要求&#xff0c;果然改回了ueditor。 UEditor 是…

PMP与CMMI:两种管理方法的对比

PMP与CMMI&#xff1a;两种管理方法的对比 PMP&#xff1a;专注于项目管理CMMI&#xff1a;组织过程改进的框架总结&#xff1a;互补而非替代 在现代企业管理中&#xff0c;项目管理和组织能力成熟度模型集成&#xff08;CMMI&#xff09;是两个经常被提及的概念。虽然它们都是…

java线程池编程示例

程序功能 这段代码展示了如何使用 Java 线程池 来并发执行多个任务。通过创建一个固定大小为 3 的线程池&#xff0c;程序提交了 5 个任务&#xff0c;并让线程池中的线程并发处理这些任务。每个任务模拟了一个耗时操作&#xff0c;最后程序等待所有任务完成后关闭线程池。 …

『功能项目』按G键持续显示对话内容【61】

本章项目成果展示 我们打开上一篇60靠近Npc显示可对话标识的项目&#xff0c; 本章要做的事情是当靠近Npc按G键显示内容后&#xff0c;再按G键实现两个人的对话显示功能 首先将以下资源图片放进Art文件夹中并设置为精灵模式 在桌面上创建一个文本 讲一下对话内容复制到文本中 …

day22JS-npm中的部分插件使用方法

1. 静态资源目录 静态资源目录就是访问服务器的某些路劲时候&#xff0c;服务器可以吐出一个写好的指定页面。 实现思路&#xff1a; 1、先判断要找的路径是否是文件&#xff0c;如果是文件&#xff0c;就加载发给对方。 2、如果是文件夹&#xff0c;找到这个文件夹所在路径中…

『功能项目』窗口可拖拽脚本【59】

本章项目成果展示 我们打开上一篇58第三职业弓弩的平A的项目&#xff0c; 本章要做的事情是给坐骑界面挂载一个脚本让其显示出来的时候可以进行拖拽 创建脚本&#xff1a;DraggableWindow.cs using UnityEngine; using UnityEngine.EventSystems; public class DraggableWindo…

Tesseract:在线高性能表结构变更方法(VLDB23)

文章目录 背景表结构变更的必要性现有技术的不足Tesseract&#xff08;超立方体&#xff09;&#xff1a;一种在MVCC系统中支持非阻塞、事务性的表结构变更的方法动机 基础的DDaM&#xff08;被作为数据修改的数据定义&#xff09;对DDL操作的分类的两个维度表结构版本&#xf…

探索未来游戏边界:AI驱动的开放世界RPG引擎与UGC平台

在游戏产业的浩瀚星空中,一项革命性的技术正悄然升起,它不仅重塑了游戏开发的传统模式,更将玩家的创造力推向了前所未有的高度。今天,让我们一同走进这个由AI驱动的开放世界RPG游戏引擎与UGC(用户生成内容)平台的奇幻世界,探索其背后的无限可能。 产品定位:AI赋能,重…

信息安全工程师(8)网络新安全目标与功能

前言 网络新安全目标与功能在当前的互联网环境中显得尤为重要&#xff0c;它们不仅反映了网络安全领域的最新发展趋势&#xff0c;也体现了对网络信息系统保护的不断加强。 一、网络新安全目标 全面防护与动态应对&#xff1a; 目标&#xff1a;建立多层次、全方位的网络安全防…

《沈阳体育学院学报》

《沈阳体育学院学报》创刊于1982年&#xff0c;是由沈阳体育学院主办&#xff0c;面向国内外公开发行的体育类学术期刊&#xff1b;国际标准刊号为ISSN 1004-0560&#xff0c;国内刊号为CN 21-1081/G8&#xff1b;双月刊&#xff0c;单月中旬出版。 《沈阳体育学院学报》是中文…

使用CUBE_MX使用I2C通信,实现对EEPROM的读写

一、使用CUBE_MX配置 1.配置I2C 2.配置USART1 3.重中之重(在KEIL5打开串口使用的库) 二、KEIL5配置 #include "main.h" #include "i2c.h" #include "gpio.h" #include "usart.h"#include <stdio.h>void SystemClock_Config(vo…

【他山之石】优化 JavaScript 的乐趣与价值(上)

前言 这是前几天偶然看到的一篇硬核推文。作者一口气分了 12 个主题探讨了 JavaScript 在优化时应该注意的要点&#xff0c;读后深受启发。由于篇幅较长&#xff0c;分两篇发表。本篇为上篇。 文章目录 Optimizing Javascript for fun and for profit0. Avoid work1. Avoid str…

苍穹外卖Day01-2

导入接口文档 yApi接口管理平台http://api.doc.jiyou-tech.com/ 创建项目 导入接口文件 导入结果界面 Swagger 介绍 使用Swagger你只需要按照它的规范去定义接口及接口相关的信息&#xff0c;就可以做到生成接口文档&#xff0c;以及在线接口调试页面。 官网&#xff1a;ht…