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

记录学习《手动学习深度学习》这本书的笔记(五)

这一章是循环神经网络,太难了太难了,有很多卡壳的地方理解了好久,比如隐藏层和隐状态的区别、代码的含义(为此专门另写了一篇【笔记】记录对自主实现一个神经网络的步骤的理解)、梯度计算相关(【笔记】记录对python中.grad()的一些理解)。

第八章:循环神经网络

8.1 序列模型

之前介绍了卷积神经网络,了解了怎么将空间结构融入模型,这一章的循环神经网络就是介绍如何将时间序列结构融入模型当中。

通常,在一个有序列结构的模型预测中,对于下一个时间步我们是按:x_{t} \sim P\left \{ x_{t} | x_{t-1} , ... x_{1}\right \}来预测的。

但是这样的话,随着预测步数的推进,复杂度会上升得非常快,所以我们需要想出一些解决方法。

我们想出的方法(自回归模型)有两种:

  • 一种叫自回归模型,是规定取预测步数之前的 \tau 个步数对当前预测步数进行预测,也就是说不需要从 t 步取回第 1 步了,只需要从t步取到第 t-\tau 步,x_{t} \sim P\left \{ x_{t} | x_{t-1} , ... x_{t-\tau }\right \}
  • 一种叫隐变量自回归模型,是我们后面会一直介绍的方法,将第 t 步之前步数的数据用一个隐状态 h_{t} 表示然后预测下一步 t+1 时只要将 h_{t} 和 x_{t+1} 进行线性变化组合得到 h_{t+1} 再用 h_{t+1} 预测第 t+1 步。

 这一章初步实现了一个简单的自回归模型,利用sin函数加一些随机误差生成数据,再利用自回归模型进行训练预测。

内插法是根据现有数据预测单个步的数据,预测数据来自现有数据。

外推法是根据现有数据不断推出后面的数据,每步根据前几步预测出来的数据对未来进行预测。

实验结果表明内推法难度更小,准确率也更高。而外推法得到的结果非常容易偏离正确值,因为预测的错误容易“累计”,不断预测非常容易偏离实际结果。

实验使用k步预测,由k步之前的数据预测第k步的数据,跨度为k,实验结果表明随着k的增加,错误会积累得越多,预测质量急剧下降。

8.2 文本预处理

我们选取《时光机器》中的文本数据。

提取文本步骤包括:

  1. 将文本作为字符串加载到内存中。
  2. 将字符串拆分为词元
  3. 建立词表将词元映射为数字索引
  4. 将文本转换为数字索引

第1步:

#@save
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 = f.readlines()return [re.sub('[^A-Za-z]+', ' ', line).strip().lower() for line in lines]lines = read_time_machine()

读取数据,将除了字母以外的字符转为空格(re.sub()正则匹配),去除首位空格(.strip()),将大写转为小写(.lower())

第2步:

将文本行继续拆分为单个词元。

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)tokens = tokenize(lines)
for i in range(11):print(tokens[i])

这个函数实现了拆分单词和拆分字母两种方式,默认拆分单词。

返回一些列表,每个列表代表一行,每一行有若干个单词(或字母)。

第3步:

这一步要将词元构成字典的形式,建立一个class类,需要实现将输入的词元匹配上一个对应的数字索引。

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:if 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)def __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]def 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]return collections.Counter(tokens)

这个类大概是根据词元出现的频率排序,得出索引。

第4步:

执行:

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

就可以得到:

[('<unk>', 0), ('the', 1), ('i', 2), ('and', 3), ('of', 4), ('a', 5), ('to', 6), ('was', 7), ('in', 8), ('that', 9)]

执行:

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

就可以得到:

文本: ['the', 'time', 'machine', 'by', 'h', 'g', 'wells']
索引: [1, 19, 50, 40, 2183, 2184, 400]
文本: ['twinkled', 'and', 'his', 'usually', 'pale', 'face', 'was', 'flushed', 'and', 'animated', 'the']
索引: [2186, 3, 25, 1044, 362, 113, 7, 1421, 3, 1045, 1]

整合以上功能:

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]if max_tokens > 0:corpus = corpus[:max_tokens]return corpus, vocabcorpus, vocab = load_corpus_time_machine()
len(corpus), len(vocab)

加载数据,切分为字母,构造词典,整合成一个大列表,可选择是否取前max_tokens个字母。

8.3 语言模型和数据集

在构建模型之前,我们要了解一些关于自然语言处理的相关知识。

基本概率规则:比如 P(我想你) = P(你|我,想)P(想|我)P(我) ,为了得出一个句子的概率,我们需要知道单词出现的概率,以及单词在前几个单词出现的情况下出现的概率。

假设我们有一个非常大的语料库,对于上面式子的条件概率,我们可以通过 P(想|我) = P(我想) / P(我) 得到。

但是对于一些不常见的组合,语料库中出现的概率可能是零,于是就要利用拉普拉斯平滑,使所有语料库中没有出现过的组合概率不为零。

进行自然语言统计时,我们将之前的数据中频率最高的词汇打印出来,发现很多都是the、of、and之类的停用词,并且前几个出现的概率比后面的概率要高很多。

打印出图像可以看出词频从某个临界点开始就下降得特别快。

这意味着单词频率符合齐鲁夫定律。

如果采用之前的平滑方法,尾部数量就会大增。

我们再统计两个词汇组成的词组出现的频率、三个词汇组成的词组出现的频率:

可以看出都是这种情况。

说明拉普拉斯平滑并不适合语言建模,很多n元组很少出现,所以我们使用深度学习模型。

我们读取长序列数据,生成小批量数据作为特征,然后移动生成它的标签。

1.随机抽样:

def seq_data_iter_random(corpus, batch_size, num_steps):  #@save"""使用随机抽样生成一个小批量子序列"""# 从随机偏移量开始对序列进行分区,随机范围包括num_steps-1corpus = corpus[random.randint(0, num_steps - 1):]# 减去1,是因为我们需要考虑标签num_subseqs = (len(corpus) - 1) // num_steps# 长度为num_steps的子序列的起始索引initial_indices = list(range(0, num_subseqs * num_steps, num_steps))# 在随机抽样的迭代过程中,# 来自两个相邻的、随机的、小批量中的子序列不一定在原始序列上相邻random.shuffle(initial_indices)def data(pos):# 返回从pos位置开始的长度为num_steps的序列return corpus[pos: pos + num_steps]num_batches = num_subseqs // batch_sizefor i in range(0, batch_size * num_batches, batch_size):# 在这里,initial_indices包含子序列的随机起始索引initial_indices_per_batch = initial_indices[i: i + batch_size]X = [data(j) for j in initial_indices_per_batch]Y = [data(j + 1) for j in initial_indices_per_batch]yield np.array(X), np.array(Y)my_seq = list(range(35))
for X, Y in seq_data_iter_random(my_seq, batch_size=2, num_steps=5):print('X: ', X, '\nY:', Y)

生成特征和标签:

X:  [[22. 23. 24. 25. 26.][27. 28. 29. 30. 31.]]
Y: [[23. 24. 25. 26. 27.][28. 29. 30. 31. 32.]]
X:  [[ 7.  8.  9. 10. 11.][12. 13. 14. 15. 16.]]
Y: [[ 8.  9. 10. 11. 12.][13. 14. 15. 16. 17.]]
X:  [[17. 18. 19. 20. 21.][ 2.  3.  4.  5.  6.]]
Y: [[18. 19. 20. 21. 22.][ 3.  4.  5.  6.  7.]]

2.顺序分区:

def seq_data_iter_sequential(corpus, batch_size, num_steps):  #@save"""使用顺序分区生成一个小批量子序列"""# 从随机偏移量开始划分序列offset = random.randint(0, num_steps)num_tokens = ((len(corpus) - offset - 1) // batch_size) * batch_sizeXs = np.array(corpus[offset: offset + num_tokens])Ys = np.array(corpus[offset + 1: offset + 1 + num_tokens])Xs, Ys = Xs.reshape(batch_size, -1), Ys.reshape(batch_size, -1)num_batches = Xs.shape[1] // num_stepsfor i in range(0, num_steps * num_batches, num_steps):X = Xs[:, i: i + num_steps]Y = Ys[:, i: i + num_steps]yield X, Yfor X, Y in seq_data_iter_sequential(my_seq, batch_size=2, num_steps=5):print('X: ', X, '\nY:', Y)

生成特征和标签:

X:  [[ 0.  1.  2.  3.  4.][17. 18. 19. 20. 21.]]
Y: [[ 1.  2.  3.  4.  5.][18. 19. 20. 21. 22.]]
X:  [[ 5.  6.  7.  8.  9.][22. 23. 24. 25. 26.]]
Y: [[ 6.  7.  8.  9. 10.][23. 24. 25. 26. 27.]]
X:  [[10. 11. 12. 13. 14.][27. 28. 29. 30. 31.]]
Y: [[11. 12. 13. 14. 15.][28. 29. 30. 31. 32.]]

将两种方法打包:

class SeqDataLoader:  #@save"""加载序列数据的迭代器"""def __init__(self, batch_size, num_steps, use_random_iter, max_tokens):if use_random_iter:self.data_iter_fn = d2l.seq_data_iter_randomelse:self.data_iter_fn = d2l.seq_data_iter_sequentialself.corpus, self.vocab = d2l.load_corpus_time_machine(max_tokens)self.batch_size, self.num_steps = batch_size, num_stepsdef __iter__(self):return self.data_iter_fn(self.corpus, self.batch_size, self.num_steps)
def load_data_time_machine(batch_size, num_steps,  #@saveuse_random_iter=False, max_tokens=10000):"""返回时光机器数据集的迭代器和词表"""data_iter = SeqDataLoader(batch_size, num_steps, use_random_iter, max_tokens)return data_iter, data_iter.vocab

8.4 循环神经网络

循环神经网络将按照之前说的隐状态自回归模型,每一步根据上一步的状态h和当前读取数据进行预测。

隐状态H的作用是保留前面步的历史信息,相当于记忆一样。

这里书中提示了隐状态和隐藏层是不同的,想了老半天为什么,直到看到老师的ppt才懂:

其实两者指的是差不多的东西,只不过隐藏层是指那个层(箭头),而隐状态是指那个层输出的状态(h)。

没有隐状态就是普通神经网络,输入x输出y,中间的隐藏层不和前面的输入有关。

有隐状态就是隐藏层结合了前一个h,输出的是隐状态h,记录的前面的历史数据。

然后值得一提的是所有时间步是共享参数的,也就是h_{2}的计算和h_{3}是类似的这使得循环神经网络的开销不会随着预测步数的增大而增大。

预测值y的计算如下:

y_{t} = H_{t} W_{hq} + b_{q}

隐状态h的计算如下:

H_{t} = \phi (X_{t} W_{xh} + H_{t-1}W_{hh} + b_{h})

循环神经网络对于每个批量(比如you ar)和它的标签(ou are),对每个小批量(一个或多个字母)执行上述计算操作,这样就可以推出下一个字母,如此反复。

由上述隐状态的公式可以看出,我们可以将上一个隐状态和这一个输入横向合并(物理),将权重W纵向合并(物理),两者相乘加b得到的也是同样结果。

最后来看评判模型好坏的困惑度,就是判断这个字母在这个位置出现的合理性(概率),可以用如下方法计算:

\frac{1}{n}\prod_{n}^{t = 1}P(x_{t} | x_{t-1}, x_{t-2} ... x_{1})

累乘会导致数字过大或者过小,于是将其取对数:

exp(\frac{1}{n}\sum_{n}^{t = 1}-log P(x_{t} | x_{t-1}, x_{t-2} ... x_{1}))

这就是困惑度。最好情况为1,最坏情况为正无穷大。

8.5 循环神经网络的从零开始实现

这一节单独放在【笔记】记录对自主实现一个神经网络的步骤的理解里了,只需再介绍一个独热编码的实现:

F.one_hot(torch.tensor([0, 2]), len(vocab))

对0,1两个数字独热编码,长度为字母表长度。

运行结果是:

tensor([[1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0],[0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,0, 0, 0, 0]])

如果传入的是数组,也可以给出对应独热编码,结果上升一个维度。

8.6 循环神经网络的简洁实现

这一章我们构建一个隐藏单元为256的单隐藏层循环神经网络。

像之前那样读取数据:

batch_size, num_steps = 32, 35
train_iter, vocab = d2l.load_data_time_machine(batch_size, num_steps)

定义模型:

num_hiddens = 256
rnn_layer = nn.RNN(len(vocab), num_hiddens)

要注意的是,nn.RNN不是整个循环神经网络,而是只是隐藏层这部分,输出的是隐藏层的预测数据,我们还需要实现从隐状态到最后输出层的代码。

初始化隐状态:

state = torch.zeros((1, batch_size, num_hiddens))
state.shape

由于nn.RNN只包含隐藏层,我们还需要建输出层,并将两个层合并成一个完整的循环神经网络:

#@save
class RNNModel(nn.Module):"""循环神经网络模型"""def __init__(self, rnn_layer, vocab_size, **kwargs):super(RNNModel, self).__init__(**kwargs)self.rnn = rnn_layerself.vocab_size = vocab_sizeself.num_hiddens = self.rnn.hidden_size# 如果RNN是双向的(之后将介绍),num_directions应该是2,否则应该是1if not self.rnn.bidirectional:self.num_directions = 1self.linear = nn.Linear(self.num_hiddens, self.vocab_size)else:self.num_directions = 2self.linear = nn.Linear(self.num_hiddens * 2, self.vocab_size)def forward(self, inputs, state):X = F.one_hot(inputs.T.long(), self.vocab_size)X = X.to(torch.float32)Y, state = self.rnn(X, state)# 全连接层首先将Y的形状改为(时间步数*批量大小,隐藏单元数)# 它的输出形状是(时间步数*批量大小,词表大小)。output = self.linear(Y.reshape((-1, Y.shape[-1])))return output, statedef begin_state(self, device, batch_size=1):if not isinstance(self.rnn, nn.LSTM):# nn.GRU以张量作为隐状态return  torch.zeros((self.num_directions * self.rnn.num_layers,batch_size, self.num_hiddens),device=device)else:# nn.LSTM以元组作为隐状态return (torch.zeros((self.num_directions * self.rnn.num_layers,batch_size, self.num_hiddens), device=device),torch.zeros((self.num_directions * self.rnn.num_layers,batch_size, self.num_hiddens), device=device))

类接收一个隐藏层,词汇表大小作为参数,初始化传入参数,并且设置线性层作为由隐状态到输出的函数。

前向传播连接两个函数,先对输入进行独热编码,然后依次放入隐藏层和线性层中计算输出,输出为当前状态和当前输出。

begin_state函数初始化状态,每次新一轮预测就调用这个函数。

实现完整个模型,然后就可以将模型代入之前实现的预测和训练函数。

预测:

device = d2l.try_gpu()
net = RNNModel(rnn_layer, vocab_size=len(vocab))
net = net.to(device)
d2l.predict_ch8('time traveller', 10, net, vocab, device)

训练:

num_epochs, lr = 500, 1
d2l.train_ch8(net, train_iter, vocab, lr, num_epochs, device)

8.7 通过时间反向传播

这一节分析了循环神经网络的梯度传播。

画出流程图可以看出,越后面的步需要回溯越多,这也是循环神经网络容易梯度爆炸和梯度消失的原因。

这一节主要是在用链式计算第t步的梯度公式。

相关文章:

记录学习《手动学习深度学习》这本书的笔记(五)

这一章是循环神经网络&#xff0c;太难了太难了&#xff0c;有很多卡壳的地方理解了好久&#xff0c;比如隐藏层和隐状态的区别、代码的含义&#xff08;为此专门另写了一篇【笔记】记录对自主实现一个神经网络的步骤的理解&#xff09;、梯度计算相关&#xff08;【笔记】记录…...

【Qt】Qt+Visual Studio 2022环境开发

在使用Qt Creator的过程中&#xff0c;项目一大就会卡&#xff0c;所以我一般都是用VS开发Cmake开发&#xff0c; 在上一篇文章中&#xff0c;我已经安装了CMake&#xff0c;如果你没有安装就自己按一下。 记得配置Qt环境变量&#xff0c;不然CMake无法生成VS项目&#xff1a…...

云计算HCIP-OpenStack04

书接上回&#xff1a; 云计算HCIP-OpenStack03-CSDN博客 12.Nova计算管理 Nova作为OpenStack的核心服务&#xff0c;最重要的功能就是提供对于计算资源的管理。 计算资源的管理就包含了已封装的资源和未封装的资源。已封装的资源就包含了虚拟机、容器。未封装的资源就是物理机提…...

HCIA-Access V2.5_3_2_VLAN数据转发

802.1Q的转发原则--Access-Link 首先看一下Access,对于Access端口来说&#xff0c; 它只属于一个VLAN,它的VLANID等于PVID。 首先看一下接收方向&#xff0c;前面说过交换机内部一定要带标签转发&#xff0c;所以当交换机接收到一个不带tag的数据帧时&#xff0c;会给它打上端…...

transformer学习笔记-导航

本系列专栏&#xff0c;主要是对transformer的基本原理做简要笔记&#xff0c;目前也是主要针对个人比较感兴趣的部分&#xff0c;包括&#xff1a;神经网络基本原理、词嵌入embedding、自注意力机制、多头注意力、位置编码、RoPE旋转位置编码等部分。transformer涉及的知识体系…...

功能篇:JAVA后端实现跨域配置

在Java后端实现跨域配置&#xff08;CORS&#xff0c;Cross-Origin Resource Sharing&#xff09;有多种方法&#xff0c;具体取决于你使用的框架。如果你使用的是Spring Boot或Spring MVC&#xff0c;可以通过以下几种方式来配置CORS。 ### 方法一&#xff1a;全局配置 对于所…...

防火墙内局域网特殊的Nginx基于stream模块进行四层协议转发模块的监听443 端口并将所有接收转发到目标服务器

在一些特殊场合下, 公司内部网络防火墙限制, 不能做端口映射, 此时可以使用nginx的做从四层协议转发, 只走tcp/ip协议, 而不走http方式, 可以做waf设置, 就可以做443, 或其它端口, 从而达到被直接转发到远程服务器效果 机房只映射了一个IP:22280, 而需求是这个SDK只能通过…...

【Hive】-- hive 3.1.3 伪分布式部署(单节点)

1、环境准备 1.1、版本选择 apache hive 3.1.3 apache hadoop 3.1.0 oracle jdk 1.8 mysql 8.0.15 操作系统:Mac os 10.151.2、软件下载 https://archive.apache.org/dist/hive/ https://archive.apache.org/dist/hadoop/ 1.3、解压 tar -zxvf apache-hive-4.0.0-bin.tar…...

C++ STL 队列queue详细使用教程

序言 我们平常写广搜什么&#xff0c;上来就是一句 queue<XXX> qu; 说明队列时很重要的。 STL库中的queue把队列的各种操作封装成一个类&#xff0c;非常方便&#xff0c;信奥中使用它也是很有优势的。 目录 一、队列的定义 二、创建队列对象 三、队列的初始化 四、常…...

【前端】JavaScript 中的 filter() 方法的理论与实践深度解析

博客主页&#xff1a; [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: 前端 文章目录 &#x1f4af;前言&#x1f4af;filter() 方法的概念与原理1. 什么是 filter()&#xff1f;2. 基本工作原理3. 方法特点4. 用法格式参数解析 &#x1f4af;代码案例详解示例&#xff1a;筛选有效数字并…...

【机器学习算法】——决策树之集成学习:Bagging、Adaboost、Xgboost、RandomForest、XGBoost

集成学习 **集成学习(Ensemble learning)**是机器学习中近年来的一大热门领域。其中的集成方法是用多种学习方法的组合来获取比原方法更优的结果。 使用于组合的算法是弱学习算法&#xff0c;即分类正确率仅比随机猜测略高的学习算法&#xff0c;但是组合之后的效果仍可能高于…...

JVM运行时数据区内部结构

VM内部结构 对于jvm来说他的内部结构主要分成三个部分&#xff0c;分别是类加载阶段&#xff0c;运行时数据区&#xff0c;以及垃圾回收区域&#xff0c;类加载我们放到之后来总结&#xff0c;今天先复习一下类运行区域 首先这个区域主要是分成如下几个部分 下面举个例子来解释…...

Navicat for MySQL 查主键、表字段类型、索引

针对Navicat 版本11 &#xff0c;不同版本查询方式可能不同 1、主键查询 &#xff08;重点找DDL&#xff01;&#xff01;&#xff01;&#xff09; 方法&#xff08;1&#xff09; &#xff1a;右键 - 对象信息 - 选择要查的表 - DDL - PRIMARY KEY 方法&#xff08;2&…...

如何在谷歌浏览器中实现自定义主题

在数字化时代&#xff0c;个性化设置已成为提升用户体验的重要一环。对于广泛使用的谷歌浏览器而言&#xff0c;改变默认的浏览器主题不仅能够美化界面&#xff0c;还能在一定程度上提升使用效率和愉悦感。本文将详细介绍如何在谷歌浏览器中实现自定义主题&#xff0c;包括从官…...

visual studio 2022 c++使用教程

介绍 c开发windows一般都是visual studio&#xff0c;linux一般是vscode&#xff0c;但vscode调试c不方便&#xff0c;所以很多情况都是2套代码&#xff0c;在windows上用vs开发方便&#xff0c;在转到linux。 安装 1、官网下载vs2022企业版–选择桌面开发–安装位置–安装–…...

曝光三要素

一光圈 光圈越大&#xff0c;数值越小&#xff0c;画面越亮&#xff0c;背景越模糊 光圈越小&#xff0c;数值越大&#xff0c;画面越暗&#xff0c;背景越清晰 二 快门 快门最主要的作用是控制曝光时间的长短 快门速度的单位是秒&#xff0c;一般用 1秒&#xff0c;1/8秒&am…...

01-2 :PyCharm安装配置教程(图文结合-超详细)

一、PyCharm安装 PyCharm集成开发工具&#xff08;IDE&#xff09;&#xff0c;是当下全球Python开发者&#xff0c;使用最频繁的工具软件。 绝大多数的Python程序&#xff0c;都是在PyCharm工具内完成的开发。 本篇文章基于PyCharm软件工具进行描述&#xff0c;教你如何安装…...

类OCSP靶场-Kioptrix系列-Kioptrix Level 1

一、前情提要 二、实战打靶 1. 信息收集 1.1. 主机发现 1.2. 端口扫描 1.3 目录爆破 1.4. 敏感信息 2.根据服务搜索漏洞 2.1. 搜索exp 2.2. 编译exp 2.3. 查看exp使用方法&#xff0c;并利用 3. 提权 二、第二种方法 一、前情提要 Kioptrix Level是免费靶场&#x…...

Maven插件打包发布远程Docker镜像

dockerfile-maven-plugin插件的介绍 dockerfile-maven-plugin目前这款插件非常成熟&#xff0c;它集成了Maven和Docker&#xff0c;该插件的官方文档地址如下&#xff1a; 地址&#xff1a;https://github.com/spotify/dockerfile-maven 其他说明&#xff1a; dockerfile是用…...

VisualStudio vsix插件自动加载

本文介绍如何在Visual Studio扩展中实现PackageRegistration&#xff0c;包括设置UseManagedResourcesOnly为true&#xff0c;允许背景加载&#xff0c;并针对C#、VB、F#项目提供自动装载&#xff0c;附官方文档链接。增加以下特性即可…… [PackageRegistration(UseManagedRe…...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)

HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...

如何在看板中体现优先级变化

在看板中有效体现优先级变化的关键措施包括&#xff1a;采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中&#xff0c;设置任务排序规则尤其重要&#xff0c;因为它让看板视觉上直观地体…...

智能在线客服平台:数字化时代企业连接用户的 AI 中枢

随着互联网技术的飞速发展&#xff0c;消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁&#xff0c;不仅优化了客户体验&#xff0c;还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用&#xff0c;并…...

2023赣州旅游投资集团

单选题 1.“不登高山&#xff0c;不知天之高也&#xff1b;不临深溪&#xff0c;不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...

基于Java+MySQL实现(GUI)客户管理系统

客户资料管理系统的设计与实现 第一章 需求分析 1.1 需求总体介绍 本项目为了方便维护客户信息为了方便维护客户信息&#xff0c;对客户进行统一管理&#xff0c;可以把所有客户信息录入系统&#xff0c;进行维护和统计功能。可通过文件的方式保存相关录入数据&#xff0c;对…...

【Android】Android 开发 ADB 常用指令

查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...

逻辑回归暴力训练预测金融欺诈

简述 「使用逻辑回归暴力预测金融欺诈&#xff0c;并不断增加特征维度持续测试」的做法&#xff0c;体现了一种逐步建模与迭代验证的实验思路&#xff0c;在金融欺诈检测中非常有价值&#xff0c;本文作为一篇回顾性记录了早年间公司给某行做反欺诈预测用到的技术和思路。百度…...

华为OD最新机试真题-数组组成的最小数字-OD统一考试(B卷)

题目描述 给定一个整型数组,请从该数组中选择3个元素 组成最小数字并输出 (如果数组长度小于3,则选择数组中所有元素来组成最小数字)。 输入描述 行用半角逗号分割的字符串记录的整型数组,0<数组长度<= 100,0<整数的取值范围<= 10000。 输出描述 由3个元素组成…...

【Veristand】Veristand环境安装教程-Linux RT / Windows

首先声明&#xff0c;此教程是针对Simulink编译模型并导入Veristand中编写的&#xff0c;同时需要注意的是老用户编译可能用的是Veristand Model Framework&#xff0c;那个是历史版本&#xff0c;且NI不会再维护&#xff0c;新版本编译支持为VeriStand Model Generation Suppo…...

C++实现分布式网络通信框架RPC(2)——rpc发布端

有了上篇文章的项目的基本知识的了解&#xff0c;现在我们就开始构建项目。 目录 一、构建工程目录 二、本地服务发布成RPC服务 2.1理解RPC发布 2.2实现 三、Mprpc框架的基础类设计 3.1框架的初始化类 MprpcApplication 代码实现 3.2读取配置文件类 MprpcConfig 代码实现…...