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

12 循环神经网络(基础篇) Basic RNN

文章目录

    • 问题引入
      • 关于权重
      • 权重共享
    • RNN Cell
      • RNN原理
      • RNN计算过程
      • 代码实现
        • RNN Cell
        • 维度说明
        • 代码
    • RNN
      • 维度说明
      • NumLayers
        • 说明
        • 计算过程
        • 代码
    • 参考实例
      • 问题分析
      • 多分类问题
      • 代码
      • RNN Cell
      • RNN
      • 改进
        • Embedding
        • 网络结构
        • Embedding说明
        • Linear说明
        • 代码

课程来源: 链接
课程文本参考:Birandaの

问题引入

在前篇中所提到的线性网络,大致上都是稠密网络(DNN)这种网络的输入大多是样本的多维度的特征,以此来得到一个想要的输出。
在这里插入图片描述
显然,面对序列问题,即处理视频流、预测天气、自然语言等等问题时,此时输入的x1⋯xnx_1 \cdots x_nx1xn实际上是一组有序列性即存在前后关系的样本。每个xix_ixi为一个样本的所包含的特征元组。

针对这样的问题,我们也会想到利用线性的全连接网络来进行处理,但事实上,全连接网络所需要计算的权重太多,并不能够解决问题。

关于权重

对于一张128通道的图片,若想要利用5×55 \times 55×5的卷积核将它转换成一张64通道的图片,则需要计算的权重有大约20W个
128×52×64=204800128 \times 5^2 \times 64 = 204800 128×52×64=204800
即卷积层的权重数目只与通道数以及卷积核大小有关,但全连接层的权重数与转成一维向量以后的整个数据量有关
若转为一维向量以后,输入为4096个元素,输出为1024个元素,则需要计算的权重大约有400W个
4096×1024=41943044096 \times 1024 = 4194304 4096×1024=4194304
显然,全连接层所需要计算的权重远多于卷积层

权重共享

给定一张输入图片,用一个固定大小的卷积核去对图片进行处理,卷积核内的参数即为权重,而卷积核是对输入图片进行步长为stride的扫描计算,也就是说原图中的每一个像素都会参与到卷积计算中,因此,对于整个卷积核而言,权重都是一样的,即共享。

权重共享,实际上是计划通过将输入图片的一个局部特征映射成输出图片的一个像素点而发挥作用的,也就是通过卷积核,使得输出层的每一个像素只与输入层一个局部的方块相连接,这就避免了在全连接情形下的,输出层的每个像素都在或多或少的被输入层的任意一个像素影响这一复杂的情况。

另外,图像信息的特征:图片底层特征与特征在图片中的位置无关,也是权重共享的一个依据。例如对于图像的边缘特征,无论边缘处在图像的什么位置,都是以同样的方法定义,作为同样的特征进行区别的。

因此,为了能够较好地解决序列问题,也要利用到权重共享的思路方法,来减少在计算过程中所需要的权重。因此产生了RNN

RNN Cell

RNN原理

模块名称作用
xtx_txt表时刻ttt时的输入数据
RNN Cell本质上是一个线性层
hth_tht表时刻ttt时得到的输出(隐含层)

在这里插入图片描述
本质上,RNN Cell为一个线性层Linear,在ttt时刻下的NNN维向量,经过Cell后即可变为一个MMM维的向量hth_tht,而与其他线性层不同,RNN Cell为一个共享的线性层。即重复利用,权重共享。将上图展开来看如下。

在这里插入图片描述
由于x1⋯xnx_1 \cdots x_nx1xn,为一组序列信息,每一个xix_ixi都至少应包含xi−1x_{i-1}xi1的信息。也就是说,针对x2x_2x2的操作所得到的h2h_2h2中,应当包含x1x_1x1的信息,因此在设计中,把x1x_1x1处理后得到的h1h_1h1一并向下传递。
上图中的h0h_0h0是一种前置信息。例如若实现图像到文本的转换,可以利用CNN+FC对图像进行操作,再将输出的向量作为h0h_0h0参与到RNN的运算中。
若没有可获知的前置信息,可将h0h_0h0设置为与xix_ixi同维度的零向量。
图中的RNN Cell为同一个Linear,即让设计好的Linear反复参与运算,实现权重共享。

RNN计算过程

在这里插入图片描述
对上图中的符号做出解释如下

符号标注
hth_ththt−1h_{t-1}ht1隐藏层hidden的结果向量
xtx_txt输入层的输入向量
Rhidden_sizeR ^{hidden\_size}Rhidden_size表隐藏层的向量维度
Rinput_sizeR^{input\_size}Rinput_size表输入层的向量维度
WihW_{ih}Wih用于计算输入的权重,维度大小为hidden_size×input_sizehidden\_size \times input\_sizehidden_size×input_size
bihb_{ih}bih用于计算输入时的偏置量
WhhW_{hh}Whh用于计算隐藏层的权重,维度大小为hidden_size×hidden_sizehidden\_size \times hidden\_sizehidden_size×hidden_size
bhhb_{hh}bhh用于计算隐藏层时的偏置量
tanh激活函数,值域为(−1,+1)(-1, +1)(1,+1)
+求和模块

在RNN计算过程中,分别对输入xtx_txt以及前文的隐藏层输出ht−1h_{t-1}ht1进行线性计算,再进行求和,对所得到的一维向量,利用tanh激活函数进行激活,由此可以得到当前隐藏层的输出hth_tht,其计算过程如下:
ht=tanh(Wihxt+bih+Whhht−1+bhh)h_t = tanh(W_{ih}x_t + b_{ih} + W_{hh}h_{t-1} + b_{hh}) ht=tanh(Wihxt+bih+Whhht1+bhh)
实际上,在框中的RNN Cell,的计算过程中为线性计算。
Whhht−1+Wihxt=[WhhWih][hx]W_{hh}h_{t-1}+W_{ih}x_{t} = \begin{bmatrix} {W_{hh}}&{W_{ih}} \end{bmatrix} \begin{bmatrix} h\\ x \end{bmatrix} Whhht1+Wihxt=[WhhWih][hx]
即在实际运算的过程中,这两部分是拼接到一起形成矩阵再计算求和的,最终形成一个大小为hidden_size×1hidden\_size \times 1hidden_size×1的张量。

代码实现

代码实现有两种模式,一是实现自己的RNN Cell,再自己重写循环调用等逻辑。二是直接调用RNN的网络。

重点在于控制其输入输出的维度。

RNN Cell

#输入维度input_size,隐藏层维度hidden_size
cell = torch.nn.RNNCell(input_size = input_size, hidden_size = hidden_size)#输入的input 的维度(B*input_size), hidden的维度(B*hidden_size)
#输出的hidden维度(B*hidden_szie)
hidden = cell(input, hidden)

维度说明

为说明输入输出维度大小,假定当前有如下配置的数据

参数说明
BatchSize1批量大小
SeqLen3样本数目x1x_1x1x2x_2x2x3x_3x3
InputSize4输入维度
HiddenSize2隐藏层(输出)维度

对于RNN Cell而言在hidden = cell(input, hidden)中

参数说明
input([1, 4])input.shape=(batch_size,input_size)input.shape = (batch\_size, input\_size)input.shape=(batch_size,input_size)
hidden([1, 2])output.shape=(batch_size,hidden_size)output.shape = (batch\_size, hidden\_size)output.shape=(batch_size,hidden_size)

而整个数据集的维度应为
dataset.shape=(seqLen,batch_size,input_size)dataset.shape = (seqLen, batch\_size, input\_size) dataset.shape=(seqLen,batch_size,input_size)

代码

import torchbatch_size = 1
seq_len = 3
input_size = 4
hidden_size =2cell = torch.nn.RNNCell(input_size = input_size, hidden_size = hidden_size)
#维度最重要
dataset = torch.randn(seq_len,batch_size,input_size)
#初始化时设为零向量
hidden = torch.zeros(batch_size, hidden_size)for idx,input in enumerate(dataset):print('=' * 20,idx,'=' * 20)print('Input size:', input.shape)hidden = cell(input, hidden)print('outputs size: ', hidden.shape)print(hidden)

在这里插入图片描述

RNN

#说明input维度,hidden维度,以及RNN层数
#RNN计算耗时大,不建议层数过深
cell = torch.nn.RNN(input_size = input_size, hidden_size = hidden_size, num_layers = num_layers)#inputs指的是X1……Xn的整个输入序列
#hidden指的是前置条件H0
#out指的是每一次迭代的H1……Hn隐藏层序列
#hidden_out指的是最后一次迭代得到输出Hn
out, hidden_out = cell(inputs, hidden)

维度说明

为说明输入输出维度大小,假定当前有如下配置的数据

参数说明
BatchSize1批量大小
SeqLen5样本数目x1x_1x1x2x_2x2x3x_3x3x4x_4x4x5x_5x5
InputSize4输入维度
HiddenSize2隐藏层(输出)维度
numLayers3RNN层数

对于RNN而言,在out, hidden_out = cell(inputs, hidden)

参数说明
input([5, 1, 4])input.shape=(seqLen,batch_size,input_size)input.shape = (seqLen, batch\_size, input\_size)input.shape=(seqLen,batch_size,input_size)
hidden([3, 1, 2])hidden.shape=(numLayers,batch_size,hidden_size)hidden.shape = (numLayers, batch\_size,hidden\_size)hidden.shape=(numLayers,batch_size,hidden_size)
out([5, 1, 2])out.shape=(seqLen,batch_size,hidden_size)out.shape = (seqLen, batch\_size,hidden\_size)out.shape=(seqLen,batch_size,hidden_size)
hidden_out([3, 1, 2])hidden_out.shape=(numLayers,batch_size,hidden_size)hidden\_out.shape = (numLayers, batch\_size,hidden\_size)hidden_out.shape=(numLayers,batch_size,hidden_size)

NumLayers

说明

在这里插入图片描述
其中,左侧及下侧为输入部分,右侧及上侧为输出部分。

左侧是每一层RNN的前置条件,下侧为输入序列。右侧为每一层的隐藏层最终输出,上侧为隐藏层输出序列。

计算过程

在输入序列中的第jjj个样本经过第iii层RNN Cell计算过后,所产生的隐藏层输出记为hjih^i_jhji,该输出分别向更深层的Cell即i+1i+1i+1层RNN Cell,以及更靠后的序列即第j+1j+1j+1个样本进行传递。
iii为最后一层,则作为该样本的最终结果out_put输出。否则将继续向第i+1i+1i+1层RNN传递。
jjj为序列中最后一个样本,则作为本层RNN的隐藏层最终结果hidden_out输出。否则将继续向第j+1j+1j+1个样本传递。
图示是一张展开图,实际上,每一层的RNN Cell是同一个网络,以此来实现权重共享。

代码

import torchbatch_size = 1
seq_len = 5
input_size = 4
hidden_size =2
num_layers = 3
#其他参数
#batch_first=True 维度从(SeqLen*Batch*input_size)变为(Batch*SeqLen*input_size)
cell = torch.nn.RNN(input_size = input_size, hidden_size = hidden_size, num_layers = num_layers)inputs = torch.randn(seq_len, batch_size, input_size)
hidden = torch.zeros(num_layers, batch_size, hidden_size)out, hidden = cell(inputs, hidden)print("Output size: ", out.shape)
print("Output: ", out)
print("Hidden size: ", hidden.shape)
print("Hidden: ", hidden)

输出结果:
在这里插入图片描述

参考实例

假定现在有一个序列到序列(seq→seq)(seq \to seq)seqseq的任务,比如将“hello”转换为“ohlol”。

即利用RNN实现如下输出

在这里插入图片描述

问题分析

原输入“hello”并不是一个向量,需要将其转变为一组数字向量。

对输入序列的每一个字符(单词)构造字典(词典),此时每一个字符都会有一个唯一的数字与其一一对应。即将字符向量转换为数字向量。之后利用独热编码(One-Hot)的思想,即可将每个数字转换为一个向量。

在这里插入图片描述
对输出序列按照上述要求构造字典。

多分类问题

对于序列中的每一个输入,都有一个数字输出与其对应,即本质上是在求当前输入所映射到输出字典中最大概率的值。即变为多分类问题。而此时的输出维度为3。

在这里插入图片描述
其中RNNCell的输出维度为4,经过Softmax求得映射之后的概率分别是多少,再利用输出对应的独热向量,计算NLLLoss。

代码

RNN Cell

import torchinput_size = 4
hidden_size = 3
batch_size = 1#构建输入输出字典
idx2char_1 = ['e', 'h', 'l', 'o']
idx2char_2 = ['h', 'l', 'o']
x_data = [1, 0, 2, 2, 3]
y_data = [2, 0, 1, 2, 1]
# y_data = [3, 1, 2, 2, 3]
one_hot_lookup = [[1, 0, 0, 0],[0, 1, 0, 0],[0, 0, 1, 0],[0, 0, 0, 1]]
#构造独热向量,此时向量维度为(SeqLen*InputSize)
x_one_hot = [one_hot_lookup[x] for x in x_data]
#view(-1……)保留原始SeqLen,并添加batch_size,input_size两个维度
inputs = torch.Tensor(x_one_hot).view(-1, batch_size, input_size)
#将labels转换为(SeqLen*1)的维度
labels = torch.LongTensor(y_data).view(-1, 1)class Model(torch.nn.Module):def __init__(self, input_size, hidden_size, batch_size):super(Model, self).__init__()self.batch_size = batch_sizeself.input_size = input_sizeself.hidden_size = hidden_sizeself.rnncell = torch.nn.RNNCell(input_size = self.input_size,hidden_size = self.hidden_size)def forward(self, input, hidden):# RNNCell input = (batchsize*inputsize)# RNNCell hidden = (batchsize*hiddensize)hidden = self.rnncell(input, hidden)return hidden#初始化零向量作为h0,只有此处用到batch_sizedef init_hidden(self):return torch.zeros(self.batch_size, self.hidden_size)net = Model(input_size, hidden_size, batch_size)criterion = torch.nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(net.parameters(), lr=0.1)for epoch in range(15):#损失及梯度置0,创建前置条件h0loss = 0optimizer.zero_grad()hidden = net.init_hidden()print("Predicted string: ",end="")#inputs=(seqLen*batchsize*input_size) labels = (seqLen*1)#input是按序列取的inputs元素(batchsize*inputsize)#label是按序列去的labels元素(1)for input, label in zip(inputs, labels):hidden = net(input, hidden)#序列的每一项损失都需要累加loss += criterion(hidden, label)#多分类取最大_, idx = hidden.max(dim=1)print(idx2char_2[idx.item()], end='')loss.backward()optimizer.step()print(", Epoch [%d/15] loss = %.4f" % (epoch+1, loss.item()))

在这里插入图片描述

RNN

import torchinput_size = 4
hidden_size = 3
batch_size = 1
num_layers = 1
seq_len = 5
#构建输入输出字典
idx2char_1 = ['e', 'h', 'l', 'o']
idx2char_2 = ['h', 'l', 'o']
x_data = [1, 0, 2, 2, 3]
y_data = [2, 0, 1, 2, 1]
# y_data = [3, 1, 2, 2, 3]
one_hot_lookup = [[1, 0, 0, 0],[0, 1, 0, 0],[0, 0, 1, 0],[0, 0, 0, 1]]x_one_hot = [one_hot_lookup[x] for x in x_data]inputs = torch.Tensor(x_one_hot).view(seq_len, batch_size, input_size)
#labels(seqLen*batchSize,1)为了之后进行矩阵运算,计算交叉熵
labels = torch.LongTensor(y_data)class Model(torch.nn.Module):def __init__(self, input_size, hidden_size, batch_size, num_layers=1):super(Model, self).__init__()self.batch_size = batch_size #构造H0self.input_size = input_sizeself.hidden_size = hidden_sizeself.num_layers = num_layersself.rnn = torch.nn.RNN(input_size = self.input_size,hidden_size = self.hidden_size,num_layers=num_layers)def forward(self, input):hidden = torch.zeros(self.num_layers,self.batch_size,self.hidden_size)out, _ = self.rnn(input, hidden)#reshape成(SeqLen*batchsize,hiddensize)便于在进行交叉熵计算时可以以矩阵进行。return out.view(-1, self.hidden_size)net = Model(input_size, hidden_size, batch_size, num_layers)criterion = torch.nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(net.parameters(), lr=0.05)#RNN中的输入(SeqLen*batchsize*inputsize)
#RNN中的输出(SeqLen*batchsize*hiddensize)
#labels维度 hiddensize*1
for epoch in range(15):optimizer.zero_grad()outputs = net(inputs)loss = criterion(outputs, labels)loss.backward()optimizer.step()_, idx = outputs.max(dim=1)idx = idx.data.numpy()print('Predicted string: ',''.join([idx2char_2[x] for x in idx]), end = '')print(", Epoch [%d/15] loss = %.3f" % (epoch+1, loss.item()))

在这里插入图片描述

改进

独热编码在实际问题中容易引起很多问题:

  1. 独热编码向量维度过高,每增加一个不同的数据,就要增加一维
  2. 独热编码向量稀疏,每个向量是一个为1其余为0
  3. 独热编码是硬编码,编码情况与数据特征无关

综上所述,需要一种低维度的、稠密的、可学习数据的编码方式

Embedding

目的是为了对数据进行降维

在这里插入图片描述
若从Input_Size转化为Embedding_Size,以下图为例,即需要把四维的向量转换为5维,则仅需要如下图所示的矩阵,将独热编码的向量与Embedding的矩阵相乘即可。

在这里插入图片描述
即将上图矩阵转置,再右乘向量即可

在这里插入图片描述
如此即可将原先四维的One-Hot编码变为五维的Embedding编码

网络结构

增加Embedding层实现降维,增加线性层使之在处理输入输出维度不同的情况下更加稳定。

在这里插入图片描述
其中的Embedding层的输入必须是LongTensor类型。

Embedding说明

字段类型说明
num_embeddingtorch.nn.Embedding的参数表示输入的独热编码的维数
embedding_dimtorch.nn.Embedding的参数表示需要转换成的维数
Inputtorch.nn.Embedding的输入量LongTensor类型
Outputtorch.nn.Embedding的输出量为数据增加一个维度(embedding_dim)

Linear说明

对于线性层,输入和输出的第一个维度(Batch)一直到倒数第二个维度都会保持不变。但会对最后一个维度(in_features)做出改变(out_features)

在这里插入图片描述

代码

import torchinput_size = 4
num_class = 4
hidden_size = 8
embedding_size =10
batch_size = 1
num_layers = 2
seq_len = 5idx2char_1 = ['e', 'h', 'l', 'o']
idx2char_2 = ['h', 'l', 'o']x_data = [[1, 0, 2, 2, 3]]
y_data = [3, 1, 2, 2, 3]#inputs 作为交叉熵中的Inputs,维度为(batchsize,seqLen)
inputs = torch.LongTensor(x_data)
#labels 作为交叉熵中的Target,维度为(batchsize*seqLen)
labels = torch.LongTensor(y_data)class Model(torch.nn.Module):def __init__(self):super(Model, self).__init__()self .emb = torch.nn.Embedding(input_size, embedding_size)self.rnn = torch.nn.RNN(input_size = embedding_size,hidden_size = hidden_size,num_layers=num_layers,batch_first = True)self.fc = torch.nn.Linear(hidden_size, num_class)def forward(self, x):hidden = torch.zeros(num_layers, x.size(0), hidden_size)x = self.emb(x)x, _ = self.rnn(x, hidden)x = self.fc(x)return x.view(-1, num_class)net = Model()criterion = torch.nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(net.parameters(), lr=0.05)for epoch in range(15):optimizer.zero_grad()outputs = net(inputs)loss = criterion(outputs, labels)loss.backward()optimizer.step()_, idx = outputs.max(dim=1)idx = idx.data.numpy()print('Predicted string: ',''.join([idx2char_1[x] for x in idx]), end = '')print(", Epoch [%d/15] loss = %.3f" % (epoch+1, loss.item()))

输出结果:
在这里插入图片描述

相关文章:

12 循环神经网络(基础篇) Basic RNN

文章目录问题引入关于权重权重共享RNN CellRNN原理RNN计算过程代码实现RNN Cell维度说明代码RNN维度说明NumLayers说明计算过程代码参考实例问题分析多分类问题代码RNN CellRNN改进Embedding网络结构Embedding说明Linear说明代码课程来源: 链接课程文本参考&#xf…...

【C语言必经之路——第11节】初阶指针(2)

五、指针的运算1、指针与整数相加减看一下下面的代码&#xff1a;#include<stdio.h> int my_strlen(char* str) {int count0;while(*str!\0){count;str;//指针加减整数}return count; } int main() {int lenmy_strlen("abcdef");printf("%d\n",len);…...

SpringBoot学习(1)第一个SpringBoot程序

之前的SpringMVc就不在记录了&#xff0c;好像时间不太够了&#xff0c;但是springmvc作为javaweb的升级学一学对于springboot还是有较大的帮助的。 首先我们需要引入依赖&#xff0c;但是请注意&#xff0c;其中的一个不算是依赖&#xff0c;写法有所不同 首先需要引入 <…...

什么是热迁移?90%的企业都理解错误

科技的发展&#xff0c;新冠的冲击&#xff0c;让市场竞争愈发激烈。尽管云计算服务为企业免除了基础硬件的建设和维护成本&#xff0c;当企业需要进行业务跨架调整、升级维护、环境测试等场景而进行云迁移&#xff0c;其过程中所带来的停机时间&#xff0c;就变得尤为头疼了。…...

Scratch少儿编程案例-丝滑版贪吃蛇

专栏分享 点击跳转=>Unity3D特效百例点击跳转=>案例项目实战源码点击跳转=>游戏脚本-辅助自动化点击跳转=>Android控件全解手册点击跳转=>Scratch编程案例👉关于作者...

Linux系统之网卡子接口配置方法

Linux系统之网卡子接口配置方法一、本地系统环境检查1.检查系统版本2.检查系统内核版本3.检查本地IP地址二、网卡子接口介绍1.网卡子接口简介2.网卡子接口的优点3.网卡子接口的缺点三 加载802.1q 模块1.查看系统802.1q 模块信息2.加载802.1q 模块3.检查802.1q 模块加载状态四、…...

2023上半年软考中级系统集成项目管理工程师2月25日开班

系统集成项目管理工程师是全国计算机技术与软件专业技术资格&#xff08;水平&#xff09;考试&#xff08;简称软考&#xff09;项目之一&#xff0c;是由国家人力资源和社会保障部、工业和信息化部共同组织的国家级考试&#xff0c;既属于国家职业资格考试&#xff0c;又是职…...

YOLO-V5轻松上手

之前介绍了YOLO-V1~V4版本各做了哪些事以及相较于之前版本的改进。有的人或许会想“直接学习最近版本的算法不好吗”&#xff0c;在我看来&#xff0c;每一个年代的版本/算法都凝聚着当年学术界的智慧&#xff0c;即便是它被淘汰了也依旧有值得思考的地方&#xff0c;或是可以使…...

CSS的优先级理解

权重 的 4个等级定义我们把特殊性分为4个等级&#xff0c;每一个等级代表一类选择器&#xff0c;每个等级的值相加得出选择器的权重。4个等级的定义如下&#xff1a;第一等级&#xff1a;代表内联样式&#xff0c;如style""&#xff0c;权值为 1000第二等级&#xff…...

前端工程师leetcode算法面试必备-二分搜索算法(中)

一、前言 二分搜索算法本身并不是特别复杂&#xff0c;核心点主要集中在&#xff1a; 有序数组&#xff1a;指的是一个递增或者递减的区间&#xff08;特殊情况如&#xff1a;【852. 山脉数组的峰顶索引】&#xff09;&#xff1b; 中间数&#xff1a;用来确定搜索目标落在左…...

【数据库】MySQL 单表查询,多表查询

目录 单表查询 一&#xff0c;创建表worker 1&#xff0c;创建表worker的sql代码如下&#xff1a; 2&#xff0c;向worker表中插入信息 二&#xff0c; 按要求进行单表查询 1、显示所有职工的基本信息。 2、查询所有职工所属部门的部门号&#xff0c;不显示重复的部门号。 …...

【c++】vector实现(源码剖析+手画图解)

vector是我接触的第一个容器&#xff0c;好好对待&#xff0c;好好珍惜&#xff01; 目录 文章目录 前言 二、vector如何实现 二、vector的迭代器&#xff08;原生指针&#xff09; 三、vector的数据结构 图解&#xff1a; 四、vector的构造及内存管理 1.push_back() …...

VScode查看python f.write()的文件乱码

VScode查看python f.write()的文件乱码 在使用 VScode 编写 python 代码&#xff0c; print&#xff08;&#xff09;&#xff0c;汉字正常显示&#xff0c; 使用 with open&#xff08;&#xff09;as f&#xff1a; f.write&#xff08;&#xff09;文件后&#xff0c; 在 …...

excel应用技巧:如何用函数制作简易抽奖动图

利用INDEX函数和随机整数函数RANDBETWEEN配合&#xff0c;在Excel中做一个简单的抽奖器&#xff0c;可以随机抽取姓名或者奖品。有兴趣的伙伴可以做出来试试&#xff0c;撞撞2023年好运气。每次年会大家最期待的就是抽奖环节。为了看看自己今年运气怎么样&#xff0c;会不会获奖…...

CSI Tool 安装及配置记录

一、Ubuntu安装 1.下载Ubuntu 首先安装Ubuntu 14.04 LTS 64位下载地址&#xff08;页面中第一个链接&#xff09; 2.制作启动盘&#xff08;注意备份&#xff09; 可以使用官方的工具Rufus&#xff0c;下载地址&#xff1a;https://rufus.ie/ 打开Rufus&#xff0c;先备份…...

华为OD机试 - 最低位排序(Python)| 真题+思路+代码

最低位排序 题目 给定一个非空数组(列表),起元素数据类型为整型, 请按照数组元素十进制最低位从小到大进行排序, 十进制最低位相同的元素,相对位置保持不变, 当数组元素为负值时,十进制最低为等同于去除符号位后对应十进制值最低位。 输入 给定一个非空数组(列表) 其…...

C#开发的OpenRA使用TrimExcess方法

C#开发的OpenRA使用TrimExcess方法 当你在细看OpenRA的代码,就会发现在下面这段代码添加了一个方法: foreach (var nodes in levels) nodes.TrimExcess(); 在上面代码里遍历整个节点列表,把所有节点都调用TrimExcess方法处理一下, 这样做的意义何在?为什么我们在一般的代码…...

ImageMagick任意文件读取漏洞(CVE-2022-44268)

0x00 前提 前几天爆出一个 ImageMagick 漏洞 &#xff0c;可以造成一个任意文件读取的危害比较可观&#xff0c;最近有时间来复现学习一下 主要是影响的范围很大&#xff0c;很多地方都有这个问题&#xff0c;需要来学习一下 0x01 介绍 ImageMagick 是一个免费的开源软件套…...

第十九篇 ResNet——论文翻译

文章目录 摘要1 引言2 相关工作3 深度残差学习3.1 残差学习3.2 快捷恒等映射3.3 网络架构3.4 实现4 实验4.1 ImageNet 分类4.2 CIFAR-10 和分析4.3 PASCAL 和 MS COCO 上的物体检测🐇🐇🐇🐇🐇🐇 🐇 欢迎阅读 【AI浩】 的博客🐇 👍 阅读完毕,可以动动小手赞一…...

RiProRiProV2主题美化顶部增加一行导航header导航通知

背景: 有些网站的背景顶部有一行罪行公告,样式不错,希望自己的网站也借鉴过来,本教程将指导如何操作,并调整成自己想要的样式。 比如网友搭的666资源站 xd素材中文网...

VB.net复制Ntag213卡写入UID

本示例使用的发卡器&#xff1a;https://item.taobao.com/item.htm?ftt&id615391857885 一、读取旧Ntag卡的UID和数据 Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click轻松读卡技术支持:网站:Dim i, j As IntegerDim cardidhex, …...

Java多线程实现之Callable接口深度解析

Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...

拉力测试cuda pytorch 把 4070显卡拉满

import torch import timedef stress_test_gpu(matrix_size16384, duration300):"""对GPU进行压力测试&#xff0c;通过持续的矩阵乘法来最大化GPU利用率参数:matrix_size: 矩阵维度大小&#xff0c;增大可提高计算复杂度duration: 测试持续时间&#xff08;秒&…...

CMake 从 GitHub 下载第三方库并使用

有时我们希望直接使用 GitHub 上的开源库,而不想手动下载、编译和安装。 可以利用 CMake 提供的 FetchContent 模块来实现自动下载、构建和链接第三方库。 FetchContent 命令官方文档✅ 示例代码 我们将以 fmt 这个流行的格式化库为例,演示如何: 使用 FetchContent 从 GitH…...

什么?连接服务器也能可视化显示界面?:基于X11 Forwarding + CentOS + MobaXterm实战指南

文章目录 什么是X11?环境准备实战步骤1️⃣ 服务器端配置(CentOS)2️⃣ 客户端配置(MobaXterm)3️⃣ 验证X11 Forwarding4️⃣ 运行自定义GUI程序(Python示例)5️⃣ 成功效果![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/55aefaea8a9f477e86d065227851fe3d.pn…...

DeepSeek 技术赋能无人农场协同作业:用 AI 重构农田管理 “神经网”

目录 一、引言二、DeepSeek 技术大揭秘2.1 核心架构解析2.2 关键技术剖析 三、智能农业无人农场协同作业现状3.1 发展现状概述3.2 协同作业模式介绍 四、DeepSeek 的 “农场奇妙游”4.1 数据处理与分析4.2 作物生长监测与预测4.3 病虫害防治4.4 农机协同作业调度 五、实际案例大…...

Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement

Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement 1. LAB环境2. L2公告策略2.1 部署Death Star2.2 访问服务2.3 部署L2公告策略2.4 服务宣告 3. 可视化 ARP 流量3.1 部署新服务3.2 准备可视化3.3 再次请求 4. 自动IPAM4.1 IPAM Pool4.2 …...

Elastic 获得 AWS 教育 ISV 合作伙伴资质,进一步增强教育解决方案产品组合

作者&#xff1a;来自 Elastic Udayasimha Theepireddy (Uday), Brian Bergholm, Marianna Jonsdottir 通过搜索 AI 和云创新推动教育领域的数字化转型。 我们非常高兴地宣布&#xff0c;Elastic 已获得 AWS 教育 ISV 合作伙伴资质。这一重要认证表明&#xff0c;Elastic 作为 …...

TJCTF 2025

还以为是天津的。这个比较容易&#xff0c;虽然绕了点弯&#xff0c;可还是把CP AK了&#xff0c;不过我会的别人也会&#xff0c;还是没啥名次。记录一下吧。 Crypto bacon-bits with open(flag.txt) as f: flag f.read().strip() with open(text.txt) as t: text t.read…...

深入理解 React 样式方案

React 的样式方案较多,在应用开发初期,开发者需要根据项目业务具体情况选择对应样式方案。React 样式方案主要有: 1. 内联样式 2. module css 3. css in js 4. tailwind css 这些方案中,均有各自的优势和缺点。 1. 方案优劣势 1. 内联样式: 简单直观,适合动态样式和…...