12 循环神经网络(基础篇) Basic RNN
文章目录
- 问题引入
- 关于权重
- 权重共享
- RNN Cell
- RNN原理
- RNN计算过程
- 代码实现
- RNN Cell
- 维度说明
- 代码
- RNN
- 维度说明
- NumLayers
- 说明
- 计算过程
- 代码
- 参考实例
- 问题分析
- 多分类问题
- 代码
- RNN Cell
- RNN
- 改进
- Embedding
- 网络结构
- Embedding说明
- Linear说明
- 代码
课程来源: 链接
课程文本参考:Birandaの
问题引入
在前篇中所提到的线性网络,大致上都是稠密网络(DNN)这种网络的输入大多是样本的多维度的特征,以此来得到一个想要的输出。
显然,面对序列问题,即处理视频流、预测天气、自然语言等等问题时,此时输入的x1⋯xnx_1 \cdots x_nx1⋯xn实际上是一组有序列性即存在前后关系的样本。每个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_nx1⋯xn,为一组序列信息,每一个xix_ixi都至少应包含xi−1x_{i-1}xi−1的信息。也就是说,针对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}ht−1 | 隐藏层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}ht−1进行线性计算,再进行求和,对所得到的一维向量,利用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+Whhht−1+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} Whhht−1+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)
维度说明
为说明输入输出维度大小,假定当前有如下配置的数据
参数 | 值 | 说明 |
---|---|---|
BatchSize | 1 | 批量大小 |
SeqLen | 3 | 样本数目x1x_1x1x2x_2x2x3x_3x3 |
InputSize | 4 | 输入维度 |
HiddenSize | 2 | 隐藏层(输出)维度 |
对于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)
维度说明
为说明输入输出维度大小,假定当前有如下配置的数据
参数 | 值 | 说明 |
---|---|---|
BatchSize | 1 | 批量大小 |
SeqLen | 5 | 样本数目x1x_1x1x2x_2x2x3x_3x3x4x_4x4x5x_5x5 |
InputSize | 4 | 输入维度 |
HiddenSize | 2 | 隐藏层(输出)维度 |
numLayers | 3 | RNN层数 |
对于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)(seq→seq)的任务,比如将“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其余为0
- 独热编码是硬编码,编码情况与数据特征无关
综上所述,需要一种低维度的、稠密的、可学习数据的编码方式
Embedding
目的是为了对数据进行降维
若从Input_Size转化为Embedding_Size,以下图为例,即需要把四维的向量转换为5维,则仅需要如下图所示的矩阵,将独热编码的向量与Embedding的矩阵相乘即可。
即将上图矩阵转置,再右乘向量即可
如此即可将原先四维的One-Hot编码变为五维的Embedding编码
网络结构
增加Embedding层实现降维,增加线性层使之在处理输入输出维度不同的情况下更加稳定。
其中的Embedding层的输入必须是LongTensor类型。
Embedding说明
字段 | 类型 | 说明 |
---|---|---|
num_embedding | torch.nn.Embedding的参数 | 表示输入的独热编码的维数 |
embedding_dim | torch.nn.Embedding的参数 | 表示需要转换成的维数 |
Input | torch.nn.Embedding的输入量 | LongTensor类型 |
Output | torch.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说明代码课程来源: 链接课程文本参考…...
【C语言必经之路——第11节】初阶指针(2)
五、指针的运算1、指针与整数相加减看一下下面的代码:#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就不在记录了,好像时间不太够了,但是springmvc作为javaweb的升级学一学对于springboot还是有较大的帮助的。 首先我们需要引入依赖,但是请注意,其中的一个不算是依赖,写法有所不同 首先需要引入 <…...
什么是热迁移?90%的企业都理解错误
科技的发展,新冠的冲击,让市场竞争愈发激烈。尽管云计算服务为企业免除了基础硬件的建设和维护成本,当企业需要进行业务跨架调整、升级维护、环境测试等场景而进行云迁移,其过程中所带来的停机时间,就变得尤为头疼了。…...
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日开班
系统集成项目管理工程师是全国计算机技术与软件专业技术资格(水平)考试(简称软考)项目之一,是由国家人力资源和社会保障部、工业和信息化部共同组织的国家级考试,既属于国家职业资格考试,又是职…...
YOLO-V5轻松上手
之前介绍了YOLO-V1~V4版本各做了哪些事以及相较于之前版本的改进。有的人或许会想“直接学习最近版本的算法不好吗”,在我看来,每一个年代的版本/算法都凝聚着当年学术界的智慧,即便是它被淘汰了也依旧有值得思考的地方,或是可以使…...
CSS的优先级理解
权重 的 4个等级定义我们把特殊性分为4个等级,每一个等级代表一类选择器,每个等级的值相加得出选择器的权重。4个等级的定义如下:第一等级:代表内联样式,如style"",权值为 1000第二等级ÿ…...
前端工程师leetcode算法面试必备-二分搜索算法(中)
一、前言 二分搜索算法本身并不是特别复杂,核心点主要集中在: 有序数组:指的是一个递增或者递减的区间(特殊情况如:【852. 山脉数组的峰顶索引】); 中间数:用来确定搜索目标落在左…...
【数据库】MySQL 单表查询,多表查询
目录 单表查询 一,创建表worker 1,创建表worker的sql代码如下: 2,向worker表中插入信息 二, 按要求进行单表查询 1、显示所有职工的基本信息。 2、查询所有职工所属部门的部门号,不显示重复的部门号。 …...
【c++】vector实现(源码剖析+手画图解)
vector是我接触的第一个容器,好好对待,好好珍惜! 目录 文章目录 前言 二、vector如何实现 二、vector的迭代器(原生指针) 三、vector的数据结构 图解: 四、vector的构造及内存管理 1.push_back() …...
VScode查看python f.write()的文件乱码
VScode查看python f.write()的文件乱码 在使用 VScode 编写 python 代码, print(),汉字正常显示, 使用 with open()as f: f.write()文件后, 在 …...
excel应用技巧:如何用函数制作简易抽奖动图
利用INDEX函数和随机整数函数RANDBETWEEN配合,在Excel中做一个简单的抽奖器,可以随机抽取姓名或者奖品。有兴趣的伙伴可以做出来试试,撞撞2023年好运气。每次年会大家最期待的就是抽奖环节。为了看看自己今年运气怎么样,会不会获奖…...
CSI Tool 安装及配置记录
一、Ubuntu安装 1.下载Ubuntu 首先安装Ubuntu 14.04 LTS 64位下载地址(页面中第一个链接) 2.制作启动盘(注意备份) 可以使用官方的工具Rufus,下载地址:https://rufus.ie/ 打开Rufus,先备份…...
华为OD机试 - 最低位排序(Python)| 真题+思路+代码
最低位排序 题目 给定一个非空数组(列表),起元素数据类型为整型, 请按照数组元素十进制最低位从小到大进行排序, 十进制最低位相同的元素,相对位置保持不变, 当数组元素为负值时,十进制最低为等同于去除符号位后对应十进制值最低位。 输入 给定一个非空数组(列表) 其…...
C#开发的OpenRA使用TrimExcess方法
C#开发的OpenRA使用TrimExcess方法 当你在细看OpenRA的代码,就会发现在下面这段代码添加了一个方法: foreach (var nodes in levels) nodes.TrimExcess(); 在上面代码里遍历整个节点列表,把所有节点都调用TrimExcess方法处理一下, 这样做的意义何在?为什么我们在一般的代码…...
ImageMagick任意文件读取漏洞(CVE-2022-44268)
0x00 前提 前几天爆出一个 ImageMagick 漏洞 ,可以造成一个任意文件读取的危害比较可观,最近有时间来复现学习一下 主要是影响的范围很大,很多地方都有这个问题,需要来学习一下 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素材中文网...
RT-Thread MSH_CMD_EXPORT分析
RT-Thread MSH_CMD_EXPORT分析 1. 源码分析 在rt-thread中,使用FinSH,可以支持命令行。在源码中,使用MSH_CMD_EXPORT导出函数到对应命令。 extern void rt_show_version(void); long version(void) {rt_show_version();return 0; } MSH_CM…...
电脑麦克风没声音怎么办?这3招就可以解决!
最近有用户在使用电脑麦克风进行视频录制时,发现麦克风没有声音。这是什么原因?电脑麦克风没有声音怎么办?关于解决方案,我专门整理了三种方法来帮你们,一起来看看吧! 操作环境: 演示机型&#…...
【C++】运算符重载
运算符重载 C为了增强代码的可读性引入了运算符重载,运算符重载是具有特殊函数名的函数,也具有其返回值类型,函数名以及参数列表。其返回值类型和参数列表与普通的函数类型。 函数名字为:关键字operator后面接需要重载的运算符号…...
什么是眼图?(扫盲向)
什么是眼图?(扫盲向) Ref: What’s eye diagram? 1 基础图示 眼图 2 用途 常用于评估差分链路中的信号传输质量 "眼睛"张得越开,链路信号质量越好 3 观测原理 眼图是传输信号序列在时域上的叠加 4 观测参数 4…...
【C++】类与对象(二)
前言 在前一章时我们已经介绍了类与对象的基本知识,包括类的概念与定义,以及类的访问限定符,类的实例化,类的大小的计算,以及C语言必须传递的this指针(C中不需要我们传递,编译器自动帮我们实现&…...
【软考】系统集成项目管理工程师(二十一)项目收尾管理
1. 项目验收2. 项目总结3. 系统维护4. 项目后评价补充:人员转移和资源遣散广义的系统集成项目收尾管理工作通常包含四类典型的工作:项目验收工作、项目总结工作、系统维护工作 以及 项目后评价工作,此外项目团队成员的后续工作也应在收尾管理时妥善安排;狭义的系统集成项目…...
关于公钥与私钥的一点看法
故事的起源 私密性 之前,用户a想给用户b发消息,a希望他自己发出现的消息,只能被b读懂。也就是说a希望发出去的数据是被加密过的,收到消息的人可以是b,c,d,e等等。但是只有b能被读懂。 这个需求…...
深入React源码揭开渲染更新流程的面纱
转前端一年半了,平时接触最多的框架就是React。在熟悉了其用法之后,避免不了想深入了解其实现原理,网上相关源码分析的文章挺多的,但是总感觉不如自己阅读理解来得深刻。于是话了几个周末去了解了一下常用的流程。也是通过这篇文章…...
32个关于FPGA的学习网站
语言类学习网站 1、HDLbits 网站地址:https://hdlbits.01xz.net/wiki/Main_Page 在线作答、编译的学习Verilog的网站,题目很多,内容丰富。非常适合初学Verilog的人!!! 2、牛客网 网站地址:http…...
5分钟快速上手Promise使用
promise 是处理异步编程的一种处理方式,可以将异步操作按照同步操作的方式编写。是一个对象或者构造函数,里面存放着某个未来才会执行的结果的方法(一般就是异步操作) 自己身上有all、reject、resolve这几个方法,原型上…...
潍坊网站制作公司/营销伎巧第一季
2019独角兽企业重金招聘Python工程师标准>>> 硬件支持层 硬件支持层(Hardware support layer),介于操作系统与硬件之间。为什么要有硬件支持层?是为了隔离不同的硬件架构,并且是操作系统能够移植方便。 在v…...
网站建设报价方案下载/百度关键词优化排名
近几天可算是过了把贼瘾,纯手工玩了一把内核的二进制hook。 在本系列的最后一篇文章中,我演示了一个实际的例子,统计了在INPUT链上iptables规则DROP掉的数据包的数量计数: Linux内核二进制hook的手艺-实际的例子计数iptables DRO…...
做网站需准备些什么软件/传统营销和网络营销的区别
在设计中,为了减少管脚,在有些工业标准中的数据总线设计为复用的方式,既输入输出在物理上是同一个管脚,为了避免输入输出信号的冲突,双向端口采用了使能信号对输出进行控制。 与三态端口相类似的,FPGA内部没…...
网站开发颜色代码/搜索引擎调词软件
那到底什么是数据分析呢? 说说数据哥的理解:数据分析是基于商业目的,有目的的进行收集、整理、加工和分析数据,提炼有价信息的一个过程。 其过程概括起来主要包括:明确分析目的与框架、数据收集、数据处理、数据分析、数据展现和…...
阅读网站建设/今天大事件新闻
『 风云说:能分享自己职位的知识的领导是个好领导。 』运行环境:JDK 7 或 8,Maven 3.0技术栈:SpringBoot 1.5, Spring Data Elasticsearch 1.5 ,ElasticSearch 2.3.2本文提纲一、spring-data-elasticsearc…...
长春模板网站建设企业/百度应用
一、 Web平台的安全审计评审方法分别从黑盒和白盒两方面考虑。黑盒着重从几种常用的攻击手段入手谈谈如何防御。白盒方面,谈谈从代码级做好防御,这方面的攻击往往不太容易,但也要防范于未然。 1)、黑盒攻击及防御Web入侵分为两个步…...