当前位置: 首页 > news >正文

RNN详解及其实现

目录

  • 概述
  • 为什么需要 RNN?
  • RNN 理解及其简单实现
  • RNN 完成文本分类任务
  • RNN 存在的问题

概述

提及 RNN,绝大部分人都知道他是一个用于序列任务的神经网络,会提及他保存了时序信息,但是,为什么需要考虑时序的信息?为什么说 RNN 保存了时序的信息?RNN又存在哪些问题? 本文将按照以下顺序逐步带你摸清 RNN 的细节之处,并使用 PyTorch 来完成一个文本分类模型。

  1. 为什么需要 RNN?
  2. RNN 理解及其简单实现。
  3. 用 RNN 完成文本分类任务。
  4. RNN 存在的问题。
    在这里插入图片描述

为什么需要 RNN?

在现实生活的世界中,有很多的内容是有着前后关系的,比如你所阅读的这段文字,他并不是毫无理由的随机组合,而是我构思之后按顺序写下的一个个文字。除了文字之外,例如人的发音、物品的价格的曲线、温度变化等等,都是有着前后顺序存在的。

很明显,当知道了前面的信息,就可以对后面的信息进行合理的预测。比如,前十天温度都只有20度,明天的温度无论如何不可能零下;这个商品一年来价格都在30左右浮动,明天我去买他的时候,准备40就足够了;老师很好的表扬了你,紧跟着说了一个但是,你就知道他的内容要开始转折了。这就是隐藏在日常生活中的序列信息,因为已经知道了前面发生的内容,所以才可以推理后面的内容。

那么,可以用传统的多层感知机来处理序列问题吗?按照基本的多层感知机模型方案来实现,应该是这样的:将序列输入固定成一个 d d d 维向量,就可以送入多层感知机进行学习,形如公式:
H = ϕ ( X W x h + b h ) \mathbf{H} = \phi(\mathbf{X} \mathbf{W}_{xh} + \mathbf{b}_{h}) H=ϕ(XWxh+bh)
公式中, ϕ \phi ϕ 表示激活函数, X ∈ R n × d \mathbf{X} \in \mathbb{R}^{n \times d} XRn×d 表示一组小批量样本,其中 n n n 是样本大小, d d d 表示输入的特征维度。: W x h ∈ R d × h \mathbf{W}_{xh} \in \mathbb{R}^{d \times h} WxhRd×h表示模型权重参数, d ∈ R 1 × h d \in \mathbb{R}^{1 \times h} dR1×h表示模型偏置。最后可以得到隐藏层输入: H ∈ R n × h \mathbf{H} \in \mathbb{R}^{n \times h} HRn×h,其中 h h h 表示隐藏层大小。

紧接着,模型可以使用下面的公式进行计算,得到输出:
O = H W h q + b q \mathbf{O} = \mathbf{H}\mathbf{W}_{hq} + \mathbf{b}_q O=HWhq+bq
其中, O ∈ R n × q \mathbf{O} \in \mathbb{R}^{n \times q} ORn×q 为模型输出变量, q q q 表示输出层向量,由于本次的任务是一个文本分类任务,那这里 q q q 就表示文本类别,可以使用 S o f t m a x ( O ) \mathbf{Softmax(O)} Softmax(O) 来进行概率预测。

但是,上面的流程有一个很明显的前置条件:固定成 d d d 维向量,也就是说,传统的多层感知机,是不能对变长序列进行处理的。但是,在序列任务中,序列长短很明显是并不相同的,不仅需要用一天的数据预测明天的结果,也可能需要拿一年的数据预测明天的结果。在这样的情况下,如果还想要使用传统的多层感知机,就会面临着一个巨大的问题:如何将一天的内容与一年的内容变化成相同的 d d d 维向量?

除此之外,序列信息可能还有另外一个情况:某些信息可能出现在序列的不同位置。虽然信息出现在不同的位置,但是他可能表达出了相同的含义

举例来说:当我们和老师谈话时,如果他表扬了我们半小时,然后说:“但是…”,我们往往是不担心的,因为他可能只是为了指出一些小问题。如果他刚刚表扬了一句话,紧接着就说“但是”,那我们就必须做好面对半小时的狂风暴雨。还有另外一种可能,老师可能连续批评你很久,然后使用“但是”转折,你就会在这时候如释重负,因为你知道这场谈话就快要结束了。这就是我们根据前文(表扬的内容和时间),在老师说出"但是"的时候,所作出的判断。

上面提到的两个问题,使用多层感知机本身似乎难以解决,但是所幸,RNN 从一个更常规的思路出发来解决这个问题:记住之前看到的内容,并结合当前看到的内容,来预测之后可能的内容。

RNN 理解及其简单实现

根据开篇的内容,相信你已经可以简单的理解为什么传统的多层感知机无法很好的解决序列信息,接下来我们开始理解,RNN 如何记忆之前的内容的。

在这里,我先放出 RNN 的公式,请将其与多层感知机公式进行对比:
H t = ϕ ( X t W x h + H t − 1 W h h + b h ) . \mathbf{H}_t = \phi(\mathbf{X}_t \mathbf{W}_{xh} + \mathbf{H}_{t-1} \mathbf{W}_{hh} + \mathbf{b}_h). Ht=ϕ(XtWxh+Ht1Whh+bh).
可以看到,与上一个公式相比,这里最明显的一点是多了一个 H t − 1 W h h \mathbf{H}_{t-1} \mathbf{W}_{hh} Ht1Whh ,从公式上似乎很好理解, H t − 1 \mathbf{H}_{t-1} Ht1 表示着前一时刻的隐藏状态,表示的是之前看到的内容,然后加上当前时刻的输入 X t \mathbf{X}_t Xt,就可以输出当前时刻的隐藏结果 H t \mathbf{H}_{t} Ht。在得到隐藏结果后,它就可以被用于下一步的计算。

当然,这个迭代过程也可能随时终止,如果将得到的隐藏结果用于输出,便可以直接得到输出结果,公式表达为:
O = ϕ ( H t W h q + b q ) . \mathbf{O} = \phi(\mathbf{H}_{t} \mathbf{W}_{hq} + \mathbf{b}_q). O=ϕ(HtWhq+bq).

可以看到,公式四与公式二极其相似,仅有隐藏状态 H \mathbf{H} H 略有不同。

此时,根据以上公式及其理解,已经可以构建一个简单的 RNN 模型了:

class RNNDemo(nn.Module):def __init__(self, input_size, hidden_size, output_size):super(CharRNNClassify, self).__init__()self.hidden_size = hidden_size# 计算隐藏状态 H# 因为要用以下一次计算,所以输出维度应该是 hidden_sizeself.i2h = nn.Linear(input_size + hidden_size, hidden_size)# 输出结果 Oself.i2o = nn.Linear(input_size + hidden_size, output_size)self.softmax = nn.LogSoftmax(dim=1)def forward(self, input, hidden):# 将 X 和 Ht-1 合并combined = torch.cat((input, hidden), 1)# 计算 Hthidden = self.i2h(combined)# 计算当前情况下的输出output = self.i2o(combined)# 分类任务使用 softmax 进行概率预测output = self.softmax(output)# 返回预测结果 和 当前的隐藏状态return output, hiddendef initHidden(self):# 避免随机生成的 H0 干扰后续结果return torch.zeros(1, self.hidden_size)

辅助代码理解:根据公式三可知, W x h \mathbf{W}_{xh} Wxh W h h \mathbf{W}_{hh} Whh 在输入阶段时两者互不影响,所以在 self.i2h = nn.Linear(input_size + hidden_size, hidden_size) 中对输入的维度进行扩容,前 input_size 与公式 W x h \mathbf{W}_{xh} Wxh 对应,而后面的 hidden_size 则是和 W h h \mathbf{W}_{hh} Whh 对应。

阅读代码之后,请根据代码和公式,来回忆第一部分提出的两个问题,通过回答这两个问题,就可以进一步的分析 RNN。

第一个问题是对于不同的序列长度,如何进行处理其向量表示:

从公式中可以看到,RNN 并不要求不同的序列表示成相同的维度,而是要求序列中的每一个值,表示成为相同的维度,这样,我们可以将在 t t t 时刻输入的值视为的 X t \mathbf{X}_t Xt,并且结合之前时刻输入并计算得来的隐藏状态 H t − 1 \mathbf{H}_{t-1} Ht1,得到当前时刻的结果,这样无论序列实际长度如何,我们随时可以在想要中断的时候将隐藏状态转变成输出的结果,甚至我们可以在输入的同时,得到输出的结果。
【图片,待补充】

第二个问题,某些信息可能出现在序列的不同位置,但是其表达的含义是相同的:

对于这个问题,单独查看公式与代码可能不太好理解,但是可以从卷积神经网络中得到一定的灵感。

卷积神经网络具有平移等变性,也就是说输入的 X \mathbf{X} X 不会因为位置的变化而导致输出的不同,这得益于卷积核使用了参数共享,无论图片哪个位置进行输入,只要卷积核的参数不变,输入值就不变,其结果就不会发生变化。

扭回头来看 RNN 中,其 X \mathbf{X} X H \mathbf{H} H 所使用的权重矩阵一直是一个,也就是说 W x h \mathbf{W}_{xh} Wxh W h h \mathbf{W}_{hh} Whh 是参数共享的,那么无论从序列的哪个位置进行输入,只要输入内容完全一样,其输出结果也就是完全一样的的。

在理解了 RNN 来龙去脉之后,接下来开始从 RNN 的在实际文本分类中进行更深入的分析。

RNN 完成文本分类任务

完成一个基本的算法任务,有以下流程:数据分析、数据转换、构建模型、定义训练函数、执行训练、保存模型、评估模型。

在 notebook 第一个可执行 cell 中,首先定义了可用字符 all_letters 和 可用字符数量 n_letters 。同时,将下载的数据转为 ASCII 编码,使用 Dict l类型进行存储。其保存格式为:{language: [names ...]}

在第三个 cell 中,定义了三个方法,主要目的是将由 n n n 个字符组成的句子变成一个 n × d n \times d n×d 的向量,其中 d d d 表示字符特征,在这里使用 One-Hot 编码。由于 One-Hot 编码形为 1 × n _ l e t t e r s 1 \times n\_letters 1×n_letters,则最终形状为 n × 1 × n _ l e t t e r s n \times 1 \times n\_letters n×1×n_letters

第四个 Cell 中,定义了基本的 RNN 模型的代码与上方代码一致,并设置隐藏层大小为128。接下来的第五个和第六个可执行 Cell中,对于 RNN 进行简单的测试。

在这里,简单的讲解第六个 Cell,第六个 Cell 代码如下:

# 将 Albert 转为 6 * 1 * n_letters 的 Tensor
input = lineToTensor('Albert')
# 设置 h0 全零的原因在上面提到过
hidden = torch.zeros(1, n_hidden)
# 获取 output 和 h1
output, next_hidden = rnn(input[0], hidden)
print(output)

第三行中 rnn(input[0], hidden),输入了首字母 也就是 ‘A’ 的 One-Hot 编码,输出 output 是下一个字符可能是什么的概率,而 next-hidden 则是 用于搭配 input[1] 进行下一步输入训练的模型。

跳过七八九三个 Cell 后,我们再对 train 所在的 Cell 进行分析,下面是相关代码:

# 设置学习率
learning_rate = 0.005 
# 输入参数中, categor_tensor 表示类别,用以计算 loss
# line_tensor 是由一句话所转变的 tensor, shape: n * 1 * n_letter
def train(category_tensor, line_tensor):# 设置 H0hidden = rnn.initHidden()# 梯度清零rnn.zero_grad()# 将字符挨个输入for i in range(line_tensor.size()[0]):output, hidden = rnn(line_tensor[i], hidden)# 计算损失loss = criterion(output, category_tensor)# 梯度回传loss.backward()# Add parameters' gradients to their values, multiplied by learning rate# 这里其实是一个手动的优化器 optimizerfor p in rnn.parameters():p.data.add_(p.grad.data, alpha=-learning_rate)return output, loss.item()

结合注释,进一步观察代码,可以看到,对于一个变长序列,在输入最后一个字符之前,都使用 hidden 作为输出用于下一步的计算,也就是将历史信息带入下一轮训练中去,而在最后一个字符输入结束后,使用 outpt 作为输出,进行文本分类的预测。

train 中的代码进行了对一句话进行了单独的训练,而实际过程中,我们要对多个句子进行训练,在示例代码中,采用随机采样法,从全部数据中随机提取一句话进行训练,并得到最终结果:

import time
import math
# 迭代次数
n_iters = 100000
# 输出频率
print_every = 5000
# loss计算频率
plot_every = 1000# Keep track of losses for plotting
current_loss = 0
all_losses = []def timeSince(since):now = time.time()s = now - sincem = math.floor(s / 60)s -= m * 60return '%dm %ds' % (m, s)
# 开始时间
start = time.time()for iter in range(1, n_iters + 1):# 使用随机采样提取一句话及其标签category, line, category_tensor, line_tensor = randomTrainingExample()# 训练output, loss = train(category_tensor, line_tensor)# 计算losscurrent_loss += loss# Print iter number, loss, name and guess# 输出阶段结果if iter % print_every == 0:guess, guess_i = categoryFromOutput(output)correct = '✓' if guess == category else '✗ (%s)' % categoryprint('%d %d%% (%s) %.4f %s / %s %s' % (iter, iter / n_iters * 100, timeSince(start), loss, line, guess, correct))# Add current loss avg to list of losses# 保存阶段性 lossif iter % plot_every == 0:all_losses.append(current_loss / plot_every)current_loss = 0

到这里,RNN 训练的代码可以说讲解结束了,保存以及推理在理解了训练的过程上并不算难事,所以不再进行讲解。

接下来再根据文本分类任务对 RNN 进行一次分析。可以看到,在本次任务中,一个单独的词作为一个序列,每个词的长短不一并不会影响 RNN 的训练过程,而序列中的值,则是字符,每个字符都构成了相同的向量: 1 × d 1 \times d 1×d ,这使得训练的过程也比较的统一。

再简单的举一反三,可以结合之前所学的 word2vec、Glovec 等模型将词语转为向量,将一句话转为一个序列,每个词转为序列中的一个值,这样的话,就可以对一句话进行文本分类了。

RNN 存在的问题

前面讲解了 RNN 是如何解决简单神经网络无法处理序列问题的,但是 RNN 是否就完美无缺?能应用于全部的序列任务了呢?答案当然是否定的。

这是由于 RNN 存在一个巨大的缺陷:梯度爆炸与梯度消失。

重新审查代码与公式,可以很轻松的发现,在序列达到末尾时,我们才需要计算损失与进行梯度回传,此时将 H t \mathbf{H}_t Ht 展开,其内部存在 W h h × H t − 1 \mathbf{W}_{hh} \times \mathbf{H}_{t-1} Whh×Ht1。而将 H t − 1 \mathbf{H}_{t-1} Ht1 展开,也存在一个 W h h \mathbf{W}_{hh} Whh,那么很明显 如果 W h h \mathbf{W}_{hh} Whh 大于 1,在经过 t t t 次连乘之后会产生梯度爆炸,如果 W h h \mathbf{W}_{hh} Whh 小于 1,在经过 t t t 次连乘之后又会产生梯度消失。同理,在 W x h \mathbf{W}_{xh} Wxh 上,也存在这样的依赖关系,也会导致梯度爆炸或者消失。

梯度的消失也可以这样思考:前方节点的隐藏信息总和占了 0.5,而当前节点隐藏信息占了 0.5,随着序列长度的增加,位于开始部分节点的隐藏信息占比几乎是指数型下降,从 1/2 到 1/4 到 1/8,以此类推。可以参考下图尝试理解。因此,在 RNN 中,梯度消失就成了一个比梯度爆炸更关注的难题,因为这使得模型只能记得离自己最近的几个节点的状态,而很难考虑更远一步的状态,无法更好的关联上下文信息。

为了解决这个问题,我们可以考虑使用 梯度剪裁的方式保证梯度传递过程中不大于1,从而使得梯度不会爆炸,但是,我们无法阻止梯度的消失。当然,也可以查看下一篇,针对 RNN 进行优化的 LSTM、GRU 等算法

相关文章:

RNN详解及其实现

目录 概述为什么需要 RNN?RNN 理解及其简单实现RNN 完成文本分类任务RNN 存在的问题 概述 提及 RNN,绝大部分人都知道他是一个用于序列任务的神经网络,会提及他保存了时序信息,但是,为什么需要考虑时序的信息&#xf…...

SpringBoot开发——详细讲解 Spring Boot 项目中的 POM 配置

文章目录 一、POM 文件简介二、单模块项目的 POM 配置1. 创建基本的 Spring Boot 单模块项目2. 重点解析三、多模块项目的 POM 配置1. 多模块项目结构2. 父模块 POM 文件3. 子模块 POM 文件4. 重点解析结语在 Spring Boot 项目中,POM(Project Object Model)文件起着关键作用…...

数据仓库: 8- 数据仓库性能优化

CSDN 目录展示 目录 8- 数据仓库性能优化8.1 查询优化8.1.1 索引优化8.1.2 分区和分桶8.1.3 使用缓存8.1.4 查询简化与重写8.1.5 聚合优化8.1.6 并行化和分布式计算8.1.7 基于列存储的优化8.1.8 表的分区和数据清洗8.1.9 查询提示 (Hints)8.1.10 自动调优工具 8.2 索引设计8.2…...

如何使用GCC手动编译stm32程序

如何不使用任何IDE(集成开发环境)编译stm32程序? 集成开发环境将编辑器、编译器、链接器、调试器等开发工具集成在一个统一的软件中,使得开发人员可以更加简单、高效地完成软件开发过程。如果我们不使用KEIL,IAR等集成开发环境,…...

2023年MathorCup高校数学建模挑战赛—大数据竞赛B题电商零售商家需求预测及库存优化问题求解全过程文档及程序

2023年MathorCup高校数学建模挑战赛—大数据竞赛 B题 电商零售商家需求预测及库存优化问题 原题再现: 电商平台存在着上千个商家,他们会将商品货物放在电商配套的仓库,电商平台会对这些货物进行统一管理。通过科学的管理手段和智能决策&…...

不可分割的整体—系统思考的微妙法则

不可分割的整体——系统思考的微妙法则 作为企业领导者,我们经常需要做出决策,但有时候,我们会忽略一个事实:每个决策都不是孤立的,它背后都是一个复杂系统的一部分。 无论是市场动态、团队协作,还是产品…...

使用Grafana K6来测测你的系统负载能力

背景 近期我们有个号称会有很高很高并发的系统要上线,为了测试一下自己开发的系统的负载能力,准备了点海克斯科技,来看看抗不抗的住。 之前笔者写过用Apache JMeter进行压力测试的文章(传送门👉:https://…...

ENSP IPV6-over-IPV4

IPv6是网络层协议的第二代标准协议,一个IPv6地址同样可以分为网络前缀和主机ID两个部分。 可以将IPV4的网络看成IPV6的承载网,只有IPv4网络是连通的,则IPv6网络才有可能连通。所以配置的时候需要先配置IPv4网络的路由功能,再配IP…...

FLASH分区---FAT分区添加操作

1、板卡配置 注意:使用fat文件系统的时候,必须download进去一个fat系统的镜像 fat.img 0xee0000 注意:需要打开fat宏定义(涉及到底层,必须开,否则无法创建文件) 2、板卡.c 配置 修改分区大小、增…...

javax.xml.ws.soap.SOAPFaultException: ZONE_OFFSET

javax.xml.ws.soap.SOAPFaultException 表示 SOAP 调用过程中发生了错误,并且服务端返回了一个 SOAP Fault。 错误信息中提到的 ZONE_OFFSET 可能指的是时区偏移量。在日期和时间处理中,时区偏移量是指格林威治标准时间 (GMT) 的偏移量。如果服务期望特…...

针对解决conda环境BUG的个人笔记

1-conda学习&安装 安装视频: 零基础教程:基于Anaconda和PyCharm配置Pytorch环境_哔哩哔哩_bilibili 安装过程: MX250笔记本安装Pytorch、CUDA和cuDNN-CSDN博客 Win10MX250CUDA10.1cuDNNPytorch1.4安装测试全过程(吐血)_nvidia geforc…...

代理IP与百度在信息时代的交互

目录 一、代理IP的基本概念和工作原理 二、代理IP在百度搜索中的多重作用 解决网络延时问题,提高搜索速度 提高网络安全 隐藏用户的真实IP地址,保护个人隐私 突破访问限制,拓宽网络视野 三、代理IP在百度关键词排名优化中的应用 模拟…...

10、PyTorch autograd使用教程

文章目录 1. 相关思考2. 矩阵求导3. 两种方法求jacobian 1. 相关思考 2. 矩阵求导 假设我们有如下向量: y 1 3 x 1 5 [ w T ] 5 3 b 1 3 \begin{equation} y_{1\times3}x_{1\times5}[w^T]_{5\times3}b_{1\times3} \end{equation} y13​x15​[wT]53​b13​​…...

Flink随笔 20241129 流数据处理:以生产线烤鸡为例理解 Flink

流数据(streaming data)就像是一条永不停歇的生产线,源源不断地向前推进,带来新的数据。而 Apache Flink 就是这条生产线的核心,它负责对数据进行处理、分类、聚合和存储。为了更好地理解 Flink 的流处理,我…...

Web day02 Js Vue Ajax

目录 1.javascript: 1.js的引入方式: 2.js变量 & 数据类型 & 输出语句: 模板字符串: 3.函数 & 自定义对象: 4. json 字符串 & DOM操作: 5. js事件监听: 6.js的模块化导入或者导出&a…...

Vue的生命周期

Vue.js 的生命周期是指一个 Vue 实例从创建到销毁的整个过程。在这个过程中,Vue 会提供一系列的钩子函数(也称为生命周期钩子),开发者可以在这些钩子中执行特定的操作。理解 Vue 的生命周期对于编写高效、可维护的 Vue 应用至关重…...

【LeetCode热题100】优先级队列

这盘博客记录了关于优先级队列的几道题&#xff0c;包括最后一块石头的重量、数据流中的第K大元素、前K个高频单词、数据流的中位数。 class Solution { public:int lastStoneWeight(vector<int>& stones) {priority_queue<int> heap;for(auto s : stones) hea…...

用go语言写一个小服务

文章目录 简介重新想到go 小服务main.go部署测试 结束语 简介 golang的优势 响应速度&#xff1a; Go > Java > Python 内存占用&#xff1a; Go < Java < Python 从java转go&#xff0c;然后go又转java&#xff0c;感觉就是go虽然在编译、内存占用都强于java&am…...

shell编程练习巩固

一、用shell写出一个简单的计算器。 其实用shell写个简单的计算器还是很简单&#xff0c;我们不用构建那么复杂的计算功能&#xff0c;只需要复现出简单的加减乘除取余即可。 既然是计算器就要明确一下思路&#xff1a; 用户可以输入一个数字根据数字选择加、减、乘、除、取…...

pytest+allure生成报告显示loading和404

pytestallure执行测试脚本后&#xff0c;通常会在电脑的磁盘上建立一个临时文件夹&#xff0c;里面存放allure测试报告&#xff0c;但是这个测试报告index.html文件单独去打开&#xff0c;却显示loading和404, 这个时候就要用一些办法来解决这个报告显示的问题了。 用命令产生…...

从数据孤岛到数据协同:企业如何构建安全的数据共享生态?

聚焦数据协作与隐私保护技术&#xff0c;探索企业如何在共享中保持安全性。 导读 在数字经济时代&#xff0c;数据已成为企业最宝贵的战略资源。然而&#xff0c;传统的"数据孤岛"模式正阻碍企业价值创新。本文将深度解析如何突破数据壁垒&#xff0c;构建安全高效的…...

数据采集中,除了IP池的IP被封,还有哪些常见问题?

在数据采集的过程中&#xff0c;代理IP池的使用无疑为我们打开了一扇通往信息宝库的大门。然而&#xff0c;除了IP被封禁这一常见问题外&#xff0c;还有许多其他问题可能影响数据采集的效果。本文将探讨在数据采集中&#xff0c;除了IP被封之外&#xff0c;还可能遇到的一些常…...

数据结构--数组

目录 1 定义 1.1 数组内存结构 1.2二维数组 2 练习 2.1 将数组内两个区间内有序元素合并 2.2 leetcode88. 合并两个有序数组 3 缓存与局部性原理 1 定义 1.1 数组内存结构 1 2 3 5 6 给数组添加元素时&#xff0c;应将原来添加位置的元素和之后的元素进行复制 System…...

基础入门-Web应用架构搭建域名源码站库分离MVC模型解析受限对应路径

知识点&#xff1a; 1、基础入门-Web应用-域名上的技术要点 2、基础入门-Web应用-源码上的技术要点 3、基础入门-Web应用-数据上的技术要点 4、基础入门-Web应用-解析上的技术要点 5、基础入门-Web应用-平台上的技术要点 一、演示案例-域名差异-主站&分站&端口站&…...

屏幕触控支持指纹

一、前端navigator.maxTouchPoints获取屏幕是否支持触控。 二、navigator.maxTouchPoints c接口修改。 1、third_party\blink\renderer\core\events\navigator_events.idl // https://w3c.github.io/pointerevents/#extensions-to-the-navigator-interface[ImplementedAsNavi…...

大米中的虫子检测-检测储藏的大米中是否有虫子 支持YOLO,VOC,COCO格式标注,4070张图片的数据集

大米中的虫子检测-检测储藏的大米中是否有虫子 支持YOLO&#xff0c;VOC&#xff0c;COCO格式标注&#xff0c;4070张图片的数据集 数据集分割 4070总图像数 训练组 87&#xff05; 3551图片 有效集 9&#xff05; 362图片 测试集 4% 157图片 预处理 自动定向…...

力扣第 74 题是 搜索二维矩阵

题目描述 给定一个 m x n 的矩阵 matrix 和一个目标值 target&#xff0c;请你编写一个函数来判断目标值 target 是否在矩阵中。 每行的元素按升序排列。每列的元素按升序排列。 示例 1 输入&#xff1a; matrix [[1, 4, 7, 11],[2, 5, 8, 12],[3, 6, 9, 16],[10, 13, 14…...

JavaScript实用工具lodash库

Lodash中文文档: Lodash 简介 | Lodash中文文档 | Lodash中文网 Lodash是一个功能强大、易于使用的JavaScript实用工具库&#xff0c;它提供了丰富的函数和工具&#xff0c;能够方便地处理集合、字符串、数值、函数等多种数据类型。通过使用Lodash&#xff0c;开发者可以大幅…...

MySQL之JDBC

我们在学习完了数据库的基本操作后&#xff0c;希望和我们的Java程序建立连接&#xff0c;那么我们今天就来一探究竟JDBC是如何让Java程序与数据库建立连接的 1. 什么是JDBC JDBC&#xff08;Java Data Base Connectivity, Java数据库连接&#xff09; 是Java程序和数据库之间…...

家校通小程序实战教程04教师管理

目录 1 创建数据源2 搭建管理后台3 搭建查询条件4 功能测试总结 我们上一篇介绍了如何将学生加入班级&#xff0c;学生加入之后就需要教师加入了。教师分为任课老师和班主任&#xff0c;班主任相当于一个班级的管理员&#xff0c;日常可以发布各种任务&#xff0c;发布接龙&…...

vitess使用记录:vtctldclient,设置分表规则

继续探索未完成的事情。 vitess使用记录系列已经写了好几篇了&#xff0c;记录了在测试过程中遇到的各种问题。《vitess使用&#xff1a;从部署到go客户端连接查询》、《vitess使用记录&#xff1a;vtctldclient》、《vitess使用&#xff1a;基于源码运行vtctldclient工具》整…...

Windows利用conda安装gpu版本Faiss + Ubuntu源码安装Faiss-gpu 记录(待更新~)

前言 由于在cpu上使用对向量检索算法时&#xff0c;发现面对数据量较大时&#xff0c;批量匹配耗时会显著增加&#xff0c;影响业务整体响应。便尝试使用GPU来实现检索计算&#xff0c;限于本人技术有限&#xff0c;写不出好算法。便取巧利用Faiss-gpu来检索(* ^ ▽ ^ *) 以下…...

react学习记录

目录结构react优秀代码之react目录结构简洁之道React 作为一个库&#xff0c;不会决定你如何组织项目的结构。这是件好事&#xff0c;因为这样 - 掘金【React】项目的目录结构全面指南_react项目结构-CSDN博客 生命周期【React 面经】生命周期详解&#xff1a;不同阶段与方法解…...

MaskRCNN训练自己的数据集

一. 数据标注 1. 安装labelme软件 conda install labelme2. 运行labelme # 命令行中直接输入 labelme3. 标注 二、训练数据处理 1. 在根目录下创建datasets/demo1文件夹&#xff0c;创建如下几个文件夹 2. 将标注好的.json文件放在json文件夹中 3. 原图放在pic文件夹中 4. …...

metawrap bin_refinement输入checkm数据库地址

这是运行metawrap bin_refinement -o bin_refinement -t 30 -A binning/metabat2_bins/ -B binning/maxbin2_bins/ -C binning/concoct_bins/ -c 50 -x 10 时遇到的报错&#xff08;在命令行跑的时候遇到的&#xff09; 参考metaGEM使用小记(解决各种问题)2024 2&#xff08;三…...

Spring Web MVC其他扩展(详解下)

文章目录 Spring MVC其他扩展&#xff08;下&#xff09;异常处理异常处理机制声明式异常好处基于注解异常声明异常处理 拦截器拦截器概念拦截器使用拦截器作用位置图解拦截器案例拦截器工作原理源码 参数校验校验概述操作演示SpringMVC自定义参数验证ValueObject(VO) 文件上传…...

深度学习之 SegNet

可训练的图像分割引擎&#xff0c;包含一个encoder网络&#xff0c;一个对应的decoder网络&#xff0c;衔接像素级分类层&#xff0c;解码网络与VGG16的13层卷积层相同。解码网络是将低分辨率的编码特征图映射到全分辨率的特征图。解码网络使用最大池化层的池化索引进行非线性上…...

Taro React小程序开发框架 总结

目录 一、安装 二、目录结构 三、创建一个自定义页面 四、路由 1、API 2、传参 3、获取路由参数 4、设置TabBar 五、组件 六、API Taro非常好用的小程序框架&#xff0c;React开发者无缝衔接上。 一、安装 官方文档&#xff1a;Taro 文档 注意&#xff0c;项目创建…...

《Django 5 By Example》阅读笔记:p339-p358

《Django 5 By Example》学习第12天&#xff0c;p339-p358总结&#xff0c;总计20页。 一、技术总结 1.项目(购物网站) django-admin startproject myshop 虽然这里只是示例&#xff0c;但我觉得这种命名为 myxxx 的习惯非常不好&#xff0c;因为在实际应用中&#xff0c;是…...

CSS:Web美学的革新之旅

自HTML的诞生之日起&#xff0c;Web页面设计便踏上了一段不断进化的旅程。起初&#xff0c;HTML作为构建网页的骨架&#xff0c;仅承载着最基本的文本结构与少量显示属性。然而&#xff0c;随着互联网的蓬勃发展和用户对视觉体验需求的日益增长&#xff0c;HTML开始不堪重负&am…...

java全栈day10--后端Web基础(基础知识)之续集

一、Servlet执行流程 二、Http协议&#xff08;相对Tomcat和servlet重要一点&#xff09; 2.1Http-概叙 2.2Http-请求协议 2.2.3请求数据格式 2.2.3请求数据获取 先启动服务器 访问/hello Servlet 访问浏览器端Http协议数据 查看数据...

MySQL 与 MongoDB 存储差异分析

MySQL 与 MongoDB 存储差异分析&#xff1a;为什么随机生成数据的存储空间不同&#xff1f; 在实际应用中&#xff0c;我们常常需要选择合适的数据库系统来处理不同类型的数据。在这个过程中&#xff0c;数据库的 存储机制 和 性能优化 起着至关重要的作用。对于很多开发者来说…...

【ArcGIS Pro实操第10期】统计某个shp文件中不同区域内的站点数

统计某个shp文件中不同区域内的站点数 方法 1&#xff1a;使用“空间连接 (Spatial Join)”工具方法 2&#xff1a;使用“点计数 (Point Count)”工具方法 3&#xff1a;通过“选择 (Select by Location)”统计方法 4&#xff1a;通过“Python 脚本 (ArcPy)”实现参考 在 ArcGI…...

Django-Vue3-Admin - 现代化的前后端分离权限管理系统

项目介绍 Django-Vue3-Admin是一个基于RBAC&#xff08;Role-Based Access Control&#xff09;模型的综合性基础开发平台&#xff0c;专注于权限控制&#xff0c;支持列级别的细粒度权限管理。该项目采用前后端分离架构&#xff0c;技术栈包括: 后端: Django Django REST …...

【Java基础入门篇】二、控制语句和递归算法

Java基础入门篇 二、控制语句和递归算法 2.1 switch-case多分支选择语句 switch执行case语句块时&#xff0c;若没有遇到break&#xff0c;则运行下一个case直到遇到break&#xff0c;最后的default表示当没有case与之匹配时&#xff0c;默认执行的内容&#xff0c;代码示例如…...

PS的功能学习

背景差色较大&#xff0c;就魔棒 魔棒的连续就是倒水点的跨越问题 魔棒的容差的选择就有点看经验了&#xff0c;看颜色的统一程度选择 Ctrl D 取消当前所有的选区 至于快速选择工具&#xff0c;和对象选择工具也差不多&#xff0c;只不过控制范围变成了一块一块的&#x…...

yolov8的深度学习环境安装(cuda12.4、ubuntu22.04)

目录 一、先安装基础环境包 1.首先给Ubuntu安装Chrome浏览器&#xff08;搜索引擎换成百度即可&#xff09; 2、ubuntu 22.04中文输入法安装 3、安装 terminator 4、安装WPS for Linux 5、安装其它之前需要先安装anaconda 6、安装配置anaconda 7、安装完成anaconda后创建…...

《JavaEat:探索 Java 在美食世界的奇妙之旅》

在当今数字化的时代&#xff0c;编程语言的应用领域不断拓展&#xff0c;而 Java 作为一种广泛使用且功能强大的编程语言&#xff0c;其影响力早已超越了传统的软件开发范畴。当我们将目光聚焦在美食领域时&#xff0c;会惊喜地发现 Java 也能在其中发挥独特而重要的作用。本文…...

将excel文件中的信息读取后批量生成word文件

在日常办公过程中&#xff0c;可能需要把excel文件中的信息批量生成成百上千份word文档&#xff0c;便于打印、发邮件或存档等&#xff0c;比如根据excel中的合格人员招聘信息生成word合同文件&#xff0c;或是根据excel中的参会人员名单生成word参会通知等。 首先需要制作wor…...

Android 图形系统之三:SurfaceControl

在 Android 系统中&#xff0c;SurfaceControl 是一个关键的类&#xff0c;用于管理应用窗口和屏幕上的显示内容。它与 SurfaceFlinger 紧密交互&#xff0c;通过 BufferQueue 提供高效的图形缓冲区管理能力。SurfaceControl 是 Android 的显示架构中不可或缺的部分&#xff0c…...