深度学习入门(六十二)循环神经网络——双向循环神经网络

news2024/11/25 2:45:18

深度学习入门(六十二)循环神经网络——双向循环神经网络

  • 前言
  • 循环神经网络——双向循环神经网络
    • 课件
      • 未来很重要
      • 双向RNN
      • 推理
      • 总结
    • 教材
      • 1 隐马尔可夫模型中的动态规划
      • 2 双向模型
        • 2.1 定义
        • 2.2 模型的计算代价及其应用
      • 3 双向循环神经网络的错误应用
      • 4 小结

前言

核心内容来自博客链接1博客连接2希望大家多多支持作者
本文记录用,防止遗忘

循环神经网络——双向循环神经网络

课件

未来很重要

I am _____
I am _____ very hungry,
I am _____ very hungry, I could eat half a pig.

I am happy.
I am not very hungry,
I am very very hungry, I could eat half a pig.

  • 取决于过去和未来的上下文,可以填很不一样的词
  • 目前为止RNN只看过去
  • 在填空的时候,我们也可以看未来

双向RNN

在这里插入图片描述

  • —个前向RNN隐层
  • 一个后向RNN隐层
  • 合并两个隐状态得到输出
    在这里插入图片描述

推理

在这里插入图片描述

总结

  • 双向循环神经网络通过反向更新的隐藏层来利用方向时间信息
  • 通常用来对序列抽取特征、填空,而不是预测未来

教材

在序列学习中,我们以往假设的目标是: 在给定观测的情况下 (例如,在时间序列的上下文中或在语言模型的上下文中), 对下一个输出进行建模。 虽然这是一个典型情景,但不是唯一的。 还可能发生什么其它的情况呢? 我们考虑以下三个在文本序列中填空的任务。

我___。
我___饿了。
我___饿了,我可以吃半头猪。

根据可获得的信息量,我们可以用不同的词填空, 如“很高兴”(”happy”)、“不”(”not”)和“非常”(”very”)。 很明显,每个短语的“下文”传达了重要信息(如果有的话), 而这些信息关乎到选择哪个词来填空, 所以无法利用这一点的序列模型将在相关任务上表现不佳。 例如,如果要做好命名实体识别 (例如,识别“Green”指的是“格林先生”还是绿色), 不同长度的上下文范围重要性是相同的。 为了获得一些解决问题的灵感,让我们先迂回到概率图模型。

1 隐马尔可夫模型中的动态规划

这一小节是用来说明动态规划问题的, 具体的技术细节对于理解深度学习模型并不重要, 但它有助于我们思考为什么要使用深度学习, 以及为什么要选择特定的架构。

如果我们想用概率图模型来解决这个问题, 可以设计一个隐变量模型: 在任意时间步 t t t,假设存在某个隐变量 h t h_t ht, 通过概率 P ( x t ∣ h t ) P(x_t \mid h_t) P(xtht)控制我们观测到的 x t x_t xt。 此外,任何 h t → h t + 1 h_t \to h_{t+1} htht+1转移 都是由一些状态转移概率 P ( h t + 1 ∣ h t ) P(h_{t+1} \mid h_{t}) P(ht+1ht)给出。 这个概率图模型就是一个隐马尔可夫模型(hidden Markov model,HMM), 如图所示。
在这里插入图片描述
因此,对于有 T T T个观测值的序列, 我们在观测状态和隐状态上具有以下联合概率分布:
P ( x 1 , … , x T , h 1 , … , h T ) = ∏ t = 1 T P ( h t ∣ h t − 1 ) P ( x t ∣ h t ) ,  where  P ( h 1 ∣ h 0 ) = P ( h 1 ) . P(x_1, \ldots, x_T, h_1, \ldots, h_T) = \prod_{t=1}^T P(h_t \mid h_{t-1}) P(x_t \mid h_t), \text{ where } P(h_1 \mid h_0) = P(h_1). P(x1,,xT,h1,,hT)=t=1TP(htht1)P(xtht), where P(h1h0)=P(h1).

现在,假设我们观测到所有的 x i x_i xi,除了 x j x_j xj, 并且我们的目标是计算 P ( x j ∣ x − j ) P(x_j \mid x_{-j}) P(xjxj), 其中 x − j = ( x 1 , … , x j − 1 , x j + 1 , … , x T ) x_{-j} = (x_1, \ldots, x_{j-1}, x_{j+1}, \ldots, x_{T}) xj=(x1,,xj1,xj+1,,xT)。 由于 P ( x j ∣ x − j ) P(x_j \mid x_{-j}) P(xjxj)中没有隐变量, 因此我们考虑对 h 1 , … , h T h_1, \ldots, h_T h1,,hT选择构成的 所有可能的组合进行求和。 如果任何 h i h_i hi可以接受 k k k个不同的值(有限的状态数), 这意味着我们需要对 k T k^T kT个项求和, 这个任务显然难于登天。 幸运的是,有个巧妙的解决方案:动态规划(dynamic programming)。

要了解动态规划的工作方式, 我们考虑对隐变量 h 1 , … , h T h_1, \ldots, h_T h1,,hT依次求和。 根据上式,将得出:
P ( x 1 , … , x T ) = ∑ h 1 , … , h T P ( x 1 , … , x T , h 1 , … , h T ) = ∑ h 1 , … , h T ∏ t = 1 T P ( h t ∣ h t − 1 ) P ( x t ∣ h t ) = ∑ h 2 , … , h T [ ∑ h 1 P ( h 1 ) P ( x 1 ∣ h 1 ) P ( h 2 ∣ h 1 ) ] ⏟ π 2 ( h 2 ) = d e f P ( x 2 ∣ h 2 ) ∏ t = 3 T P ( h t ∣ h t − 1 ) P ( x t ∣ h t ) = ∑ h 3 , … , h T [ ∑ h 2 π 2 ( h 2 ) P ( x 2 ∣ h 2 ) P ( h 3 ∣ h 2 ) ] ⏟ π 3 ( h 3 ) = d e f P ( x 3 ∣ h 3 ) ∏ t = 4 T P ( h t ∣ h t − 1 ) P ( x t ∣ h t ) = … = ∑ h T π T ( h T ) P ( x T ∣ h T ) . \begin{split}\begin{aligned} &P(x_1, \ldots, x_T) \\ =& \sum_{h_1, \ldots, h_T} P(x_1, \ldots, x_T, h_1, \ldots, h_T) \\ =& \sum_{h_1, \ldots, h_T} \prod_{t=1}^T P(h_t \mid h_{t-1}) P(x_t \mid h_t) \\ =& \sum_{h_2, \ldots, h_T} \underbrace{\left[\sum_{h_1} P(h_1) P(x_1 \mid h_1) P(h_2 \mid h_1)\right]}_{\pi_2(h_2) \stackrel{\mathrm{def}}{=}} P(x_2 \mid h_2) \prod_{t=3}^T P(h_t \mid h_{t-1}) P(x_t \mid h_t) \\ =& \sum_{h_3, \ldots, h_T} \underbrace{\left[\sum_{h_2} \pi_2(h_2) P(x_2 \mid h_2) P(h_3 \mid h_2)\right]}_{\pi_3(h_3)\stackrel{\mathrm{def}}{=}} P(x_3 \mid h_3) \prod_{t=4}^T P(h_t \mid h_{t-1}) P(x_t \mid h_t)\\ =& \dots \\ =& \sum_{h_T} \pi_T(h_T) P(x_T \mid h_T). \end{aligned}\end{split} ======P(x1,,xT)h1,,hTP(x1,,xT,h1,,hT)h1,,hTt=1TP(htht1)P(xtht)h2,,hTπ2(h2)=def [h1P(h1)P(x1h1)P(h2h1)]P(x2h2)t=3TP(htht1)P(xtht)h3,,hTπ3(h3)=def [h2π2(h2)P(x2h2)P(h3h2)]P(x3h3)t=4TP(htht1)P(xtht)hTπT(hT)P(xThT).

通常,我们将前向递归(forward recursion)写为:
π t + 1 ( h t + 1 ) = ∑ h t π t ( h t ) P ( x t ∣ h t ) P ( h t + 1 ∣ h t ) . \pi_{t+1}(h_{t+1}) = \sum_{h_t} \pi_t(h_t) P(x_t \mid h_t) P(h_{t+1} \mid h_t). πt+1(ht+1)=htπt(ht)P(xtht)P(ht+1ht).
递归被初始化为 π 1 ( h 1 ) = P ( h 1 ) \pi_1(h_1) = P(h_1) π1(h1)=P(h1)。 符号简化,也可以写成 π t + 1 = f ( π t , x t ) \pi_{t+1} = f(\pi_t, x_t) πt+1=f(πt,xt), 其中 f f f是一些可学习的函数。 这看起来就像我们在循环神经网络中讨论的隐变量模型中的更新方程。

与前向递归一样,我们也可以使用后向递归对同一组隐变量求和。这将得到:
P ( x 1 , … , x T ) = ∑ h 1 , … , h T P ( x 1 , … , x T , h 1 , … , h T ) = ∑ h 1 , … , h T ∏ t = 1 T − 1 P ( h t ∣ h t − 1 ) P ( x t ∣ h t ) ⋅ P ( h T ∣ h T − 1 ) P ( x T ∣ h T ) = ∑ h 1 , … , h T − 1 ∏ t = 1 T − 1 P ( h t ∣ h t − 1 ) P ( x t ∣ h t ) ⋅ [ ∑ h T P ( h T ∣ h T − 1 ) P ( x T ∣ h T ) ] ⏟ ρ T − 1 ( h T − 1 ) = d e f = ∑ h 1 , … , h T − 2 ∏ t = 1 T − 2 P ( h t ∣ h t − 1 ) P ( x t ∣ h t ) ⋅ [ ∑ h T − 1 P ( h T − 1 ∣ h T − 2 ) P ( x T − 1 ∣ h T − 1 ) ρ T − 1 ( h T − 1 ) ] ⏟ ρ T − 2 ( h T − 2 ) = d e f = … = ∑ h 1 P ( h 1 ) P ( x 1 ∣ h 1 ) ρ 1 ( h 1 ) . \begin{split}\begin{aligned} & P(x_1, \ldots, x_T) \\ =& \sum_{h_1, \ldots, h_T} P(x_1, \ldots, x_T, h_1, \ldots, h_T) \\ =& \sum_{h_1, \ldots, h_T} \prod_{t=1}^{T-1} P(h_t \mid h_{t-1}) P(x_t \mid h_t) \cdot P(h_T \mid h_{T-1}) P(x_T \mid h_T) \\ =& \sum_{h_1, \ldots, h_{T-1}} \prod_{t=1}^{T-1} P(h_t \mid h_{t-1}) P(x_t \mid h_t) \cdot \underbrace{\left[\sum_{h_T} P(h_T \mid h_{T-1}) P(x_T \mid h_T)\right]}_{\rho_{T-1}(h_{T-1})\stackrel{\mathrm{def}}{=}} \\ =& \sum_{h_1, \ldots, h_{T-2}} \prod_{t=1}^{T-2} P(h_t \mid h_{t-1}) P(x_t \mid h_t) \cdot \underbrace{\left[\sum_{h_{T-1}} P(h_{T-1} \mid h_{T-2}) P(x_{T-1} \mid h_{T-1}) \rho_{T-1}(h_{T-1}) \right]}_{\rho_{T-2}(h_{T-2})\stackrel{\mathrm{def}}{=}} \\ =& \ldots \\ =& \sum_{h_1} P(h_1) P(x_1 \mid h_1)\rho_{1}(h_{1}). \end{aligned}\end{split} ======P(x1,,xT)h1,,hTP(x1,,xT,h1,,hT)h1,,hTt=1T1P(htht1)P(xtht)P(hThT1)P(xThT)h1,,hT1t=1T1P(htht1)P(xtht)ρT1(hT1)=def [hTP(hThT1)P(xThT)]h1,,hT2t=1T2P(htht1)P(xtht)ρT2(hT2)=def hT1P(hT1hT2)P(xT1hT1)ρT1(hT1) h1P(h1)P(x1h1)ρ1(h1).

因此,我们可以将后向递归(backward recursion)写为:
ρ t − 1 ( h t − 1 ) = ∑ h t P ( h t ∣ h t − 1 ) P ( x t ∣ h t ) ρ t ( h t ) , \rho_{t-1}(h_{t-1})= \sum_{h_{t}} P(h_{t} \mid h_{t-1}) P(x_{t} \mid h_{t}) \rho_{t}(h_{t}), ρt1(ht1)=htP(htht1)P(xtht)ρt(ht),
初始化 ρ T ( h T ) = 1 \rho_T(h_T) = 1 ρT(hT)=1。 前向和后向递归都允许我们对 T T T个隐变量在 O ( k T ) \mathcal{O}(kT) O(kT)(线性而不是指数)时间内对 ( h 1 , … , h T ) (h_1, \ldots, h_T) (h1,,hT)的所有值求和。 这是使用图模型进行概率推理的巨大好处之一。 它也是通用消息传递算法的一个非常特殊的例子。 结合前向和后向递归,我们能够计算
P ( x j ∣ x − j ) ∝ ∑ h j π j ( h j ) ρ j ( h j ) P ( x j ∣ h j ) . P(x_j \mid x_{-j}) \propto \sum_{h_j} \pi_j(h_j) \rho_j(h_j) P(x_j \mid h_j). P(xjxj)hjπj(hj)ρj(hj)P(xjhj).
因为符号简化的需要,后向递归也可以写为 ρ t − 1 = g ( ρ t , x t ) \rho_{t-1} = g(\rho_t, x_t) ρt1=g(ρt,xt), 其中 g g g是一个可以学习的函数。 同样,这看起来非常像一个更新方程, 只是不像我们在循环神经网络中看到的那样前向运算,而是后向计算。 事实上,知道未来数据何时可用对隐马尔可夫模型是有益的。

2 双向模型

如果我们希望在循环神经网络中拥有一种机制, 使之能够提供与隐马尔可夫模型类似的前瞻能力, 我们就需要修改循环神经网络的设计。 幸运的是,这在概念上很容易, 只需要增加一个“从最后一个词元开始从后向前运行”的循环神经网络, 而不是只有一个在前向模式下“从第一个词元开始运行”的循环神经网络。 双向循环神经网络(bidirectional RNNs) 添加了反向传递信息的隐藏层,以便更灵活地处理此类信息。下图描述了具有单个隐藏层的双向循环神经网络的架构。
在这里插入图片描述
事实上,这与隐马尔可夫模型中的动态规划的前向和后向递归没有太大区别。 其主要区别是,在隐马尔可夫模型中的方程具有特定的统计意义。 双向循环神经网络没有这样容易理解的解释, 我们只能把它们当作通用的、可学习的函数。 这种转变集中体现了现代深度网络的设计原则: 首先使用经典统计模型的函数依赖类型,然后将其参数化为通用形式。

2.1 定义

双向循环神经网络是由 (Schuster and Paliwal, 1997)提出的。 让我们看看这样一个网络的细节。

对于任意时间步 t t t,给定一个小批量的输入数据 X t ∈ R n × d \mathbf{X}_t \in \mathbb{R}^{n \times d} XtRn×d(样本数 n n n,每个示例中的输入数 d d d), 并且令隐藏层激活函数为 ϕ \phi ϕ。 在双向架构中,我们设该时间步的前向和反向隐状态分别为 H → t ∈ R n × h \overrightarrow{\mathbf{H}}_t \in \mathbb{R}^{n \times h} H tRn×h H ← t ∈ R n × h \overleftarrow{\mathbf{H}}_t \in \mathbb{R}^{n \times h} H tRn×h, 其中 h h h是隐藏单元的数目。 前向和反向隐状态的更新如下:
H → t = ϕ ( X t W x h ( f ) + H → t − 1 W h h ( f ) + b h ( f ) ) , H ← t = ϕ ( X t W x h ( b ) + H ← t + 1 W h h ( b ) + b h ( b ) ) , \begin{split}\begin{aligned} \overrightarrow{\mathbf{H}}_t &= \phi(\mathbf{X}_t \mathbf{W}_{xh}^{(f)} + \overrightarrow{\mathbf{H}}_{t-1} \mathbf{W}_{hh}^{(f)} + \mathbf{b}_h^{(f)}),\\ \overleftarrow{\mathbf{H}}_t &= \phi(\mathbf{X}_t \mathbf{W}_{xh}^{(b)} + \overleftarrow{\mathbf{H}}_{t+1} \mathbf{W}_{hh}^{(b)} + \mathbf{b}_h^{(b)}), \end{aligned}\end{split} H tH t=ϕ(XtWxh(f)+H t1Whh(f)+bh(f)),=ϕ(XtWxh(b)+H t+1Whh(b)+bh(b)),
其中,权重 W x h ( f ) ∈ R d × h , W h h ( f ) ∈ R h × h , W x h ( b ) ∈ R d × h , W h h ( b ) ∈ R h × h \mathbf{W}_{xh}^{(f)} \in \mathbb{R}^{d \times h}, \mathbf{W}_{hh}^{(f)} \in \mathbb{R}^{h \times h}, \mathbf{W}_{xh}^{(b)} \in \mathbb{R}^{d \times h}, \mathbf{W}_{hh}^{(b)} \in \mathbb{R}^{h \times h} Wxh(f)Rd×h,Whh(f)Rh×h,Wxh(b)Rd×h,Whh(b)Rh×h和偏置 b h ( f ) ∈ R 1 × h , b h ( b ) ∈ R 1 × h \mathbf{b}_h^{(f)} \in \mathbb{R}^{1 \times h}, \mathbf{b}_h^{(b)} \in \mathbb{R}^{1 \times h} bh(f)R1×h,bh(b)R1×h都是模型参数。

接下来,将前向隐状态 H → t \overrightarrow{\mathbf{H}}_t H t和反向隐状态 H ← t \overleftarrow{\mathbf{H}}_t H t连接起来, 获得需要送入输出层的隐状态 H t ∈ R n × 2 h \mathbf{H}_t \in \mathbb{R}^{n \times 2h} HtRn×2h。 在具有多个隐藏层的深度双向循环神经网络中, 该信息作为输入传递到下一个双向层。 最后,输出层计算得到的输出为 O t ∈ R n × q \mathbf{O}_t \in \mathbb{R}^{n \times q} OtRn×q q q q是输出单元的数目):
O t = H t W h q + b q . \mathbf{O}_t = \mathbf{H}_t \mathbf{W}_{hq} + \mathbf{b}_q. Ot=HtWhq+bq.
这里,权重矩阵 W h q ∈ R 2 h × q \mathbf{W}_{hq} \in \mathbb{R}^{2h \times q} WhqR2h×q和偏置 b q ∈ R 1 × q \mathbf{b}_q \in \mathbb{R}^{1 \times q} bqR1×q是输出层的模型参数。 事实上,这两个方向可以拥有不同数量的隐藏单元。

2.2 模型的计算代价及其应用

双向循环神经网络的一个关键特性是:使用来自序列两端的信息来估计输出。 也就是说,我们使用来自过去和未来的观测信息来预测当前的观测。 但是在对下一个词元进行预测的情况中,这样的模型并不是我们所需的。 因为在预测下一个词元时,我们终究无法知道下一个词元的下文是什么, 所以将不会得到很好的精度。 具体地说,在训练期间,我们能够利用过去和未来的数据来估计现在空缺的词; 而在测试期间,我们只有过去的数据,因此精度将会很差。 下面的实验将说明这一点。

另一个严重问题是,双向循环神经网络的计算速度非常慢。 其主要原因是网络的前向传播需要在双向层中进行前向和后向递归, 并且网络的反向传播还依赖于前向传播的结果。 因此,梯度求解将有一个非常长的链。

双向层的使用在实践中非常少,并且仅仅应用于部分场合。 例如,填充缺失的单词、词元注释(例如,用于命名实体识别) 以及作为序列处理流水线中的一个步骤对序列进行编码(例如,用于机器翻译)。

3 双向循环神经网络的错误应用

由于双向循环神经网络使用了过去的和未来的数据, 所以我们不能盲目地将这一语言模型应用于任何预测任务。 尽管模型产出的困惑度是合理的, 该模型预测未来词元的能力却可能存在严重缺陷。 我们用下面的示例代码引以为戒,以防在错误的环境中使用它们。

import torch
from torch import nn
from d2l import torch as d2l

# 加载数据
batch_size, num_steps, device = 32, 35, d2l.try_gpu()
train_iter, vocab = d2l.load_data_time_machine(batch_size, num_steps)
# 通过设置“bidirective=True”来定义双向LSTM模型
vocab_size, num_hiddens, num_layers = len(vocab), 256, 2
num_inputs = vocab_size
lstm_layer = nn.LSTM(num_inputs, num_hiddens, num_layers, bidirectional=True)
model = d2l.RNNModel(lstm_layer, len(vocab))
model = model.to(device)
# 训练模型
num_epochs, lr = 500, 1
d2l.train_ch8(model, train_iter, vocab, lr, num_epochs, device)

输出:

perplexity 1.1, 109857.9 tokens/sec on cuda:0
time travellerererererererererererererererererererererererererer
travellerererererererererererererererererererererererererer

4 小结

  • 在双向循环神经网络中,每个时间步的隐状态由当前时间步的前后数据同时决定。

  • 双向循环神经网络与概率图模型中的“前向-后向”算法具有相似性。

  • 双向循环神经网络主要用于序列编码和给定双向上下文的观测估计。

  • 由于梯度链更长,因此双向循环神经网络的训练代价非常高。

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

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

相关文章

排序算法之直接选择排序(图文详解)

文章目录一、选择排序思想二、排序过程详解2.1 排序的次数2.2 排序演示三、代码范例3.1 SelectSort函数3.2 整体代码实现3.3 结果展示四、选择排序分析4.1 稳定性4.2 复杂度4.3适用场景五、选泽排序优化总结一、选择排序思想 选择排序(Selection sort)是…

ABBYY15免费版直接编辑PDF格式文件

日常生活中,我们常常使用PDF格式的文件。其优点就是PDF的文本内容不会随着软件版本、电脑字体的变化而变化,保证了其完整性。但也正因为这一点,如果没有源文件,我们就很难对PDF文档的内容进行编辑了。今天,我就向大家展…

前端一面必会vue面试题(边面边更)

为什么要使用异步组件 节省打包出的结果,异步组件分开打包,采用jsonp的方式进行加载,有效解决文件过大的问题。核心就是包组件定义变成一个函数,依赖import() 语法,可以实现文件的分割加载。 components:{ AddCustom…

关于GitHub的.gitignore无法忽略 “default-2021.dwlt“ 文件的问题

问题描述 我在使用sourcetree往github提交工程时,UserSettings/Layouts/default-2021.dwlt文件无缘无故每次都被暂存。 尽管我在.gitignore文件中反复修改忽略路径,该文件始终无法被屏蔽。如下图 解决办法 在网上找了很多资料,最终找到了…

Qt扫盲-QListWidget理论总结

QListWidget理论总结1. 概念2. 添加列表项3. 列表其他属性4. 常用信号5. 槽函数6. QListWidgetItem 简述1. 概念 QListWidget 是一个继承自 QListView 的类,其实就是 QListView 的一个很经典的 列表 交互控件,在QListWidget 里面提供了非常方便的基于 每…

银树开花精美甘特图:VARCHART_XGantt_5.2_167_ActiveX

增强您的计划用户体验 使用交互式甘特图提供惊人的视觉调度体验 与时间和资源相关的计划数据(例如工作、任务、订单、活动和能力)最好显示在甘特图中。 在智能甘特图中,计划人员可以随手采取纠正措施。 加快您的开发并 创建引人入胜、易于使用…

爬虫学习-深入了解爬虫

爬虫深入 使用场景分类 通用爬虫:抓取系统的重要组成部分,抓取的是一整张页面数据聚焦爬虫:建立在通用爬虫的基础之上,抓取的是页面中特定的局部内容增量式爬虫:检测网站中数据更新的情况,只会抓取网站中最…

一起学习用Verilog在FPGA上实现CNN----(三)激活层设计

1 激活层设计 LeNet-5网络的激活函数是双曲正切函数(TanH),项目中tanh函数模块由完整的层UsingTheTanh构成,该层由较小的处理单元HyperBolicTangent组成 1.1 HyperBolicTangent 处理单元HyperBolicTangent,对每个输入执行Tanh操作&#xf…

jsp+ssm计算机毕业设计动物救助平台【附源码】

项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: JSPSSM mybatis Maven等等组成,B/S模式 Mave…

实训任务4:Hadoop综合操作

文章目录1. 启动Hadoop服务2. 创建文本文件3. 上传文本文件4. 显示文件内容5. 完成排序任务6. 计算最大利润和平均利润1. 启动Hadoop服务 在master虚拟机上执行命令:start-all.sh 2. 创建文本文件 在master虚拟机上创建本地文件students.txt 李晓文 女 20 张晓航 男…

【Redis集群专题】「集群技术三部曲」分析一下相关的Redis集群模式下的脑裂问题(问题篇)

技术格言 世界上并没有完美的程序,但是我们并不因此而沮丧,因为写程序就是一个不断追求完美的过程。 什么是脑裂 字面含义 首先,脑裂从字面上理解就是脑袋裂开了,就是思想分家了,就是有了两个山头,就是有…

电脑调用 iPhone 摄像头全过程(iVCam)

最近不是停课不停学吗,令人“深恶痛绝”的钉钉又进入了我们学生的生活。但是初中的网课相比小学的又增加了一个要求:全程摄像头拍摄。但是,我这笔记本没有摄像头啊!突然想起来好像手机的摄像头可以给电脑调用。话不多说&#xff0…

3D数学基础 学习笔记

左手坐标系:DX、3DMax 右手坐标系:OpenGL 世界坐标系、物体坐标系、摄像机坐标系 向量和点在数学上是等价的,向量是有大小和方向的有向线段,向量没有位置,只有大小和方向 向量运算: 零向量:…

【看源码】@Cacheable和@CacheEvict的原理, 批量key过期失效的原因分析

Cacheable和CacheEvict的坑, 批量key过期失效的原因分析前言测试代码源码put缓存时最终key的产生看不同情况下, 是否能匹配Evict过期缓存1. 没有入参没有指定key的情况2. 有入参的情况3. 配置了allEntries的情况总结补充前言 最近发现自己搭的一个项目返回的数据不太准确, 第一…

网工Python之路——Netmiko模块实验(思科)

小白网工的python之路 「Python 网络自动化」Netmiko 实验环境 我的实验环境是GNS3搭建拓扑图,用云桥接到在VMware Workstation 16运行的CentOS 7, CentOS 7上搭建好了python3.8, 所有交换机已经预配好了SSH服务,ssh登录账号为python&…

paddle

paddle预测库 git config --global http.postBuffer 1048576000 git clone --recursive https://github.com/PaddlePaddle/Paddle.git 修改CMakeLists.txt mkdir build cd buildcmake -DWITH_CONTRIBOFF -DWITH_MKLOFF -DWITH_MKLDNNOFF -DWITH_TESTINGOFF -DCMAKE_BUILD_TY…

DBCO-PEG-Ferrocene,Ferrocene-PEG-DBCO,DBCO偶联修饰二茂铁

DBCO-PEG-Ferrocene ,Ferrocene-PEG-DBCO,二苯并环辛炔-聚乙二醇-二茂铁,DBCO偶联修饰二茂铁产品规格: 1.CAS号:N/A 2.分子量MV:1000、2000、3400、5000、10000、20000等可按需进行定制 3.包装规格&#xf…

数据结构与算法_空间复杂度

同时间复杂度一样,空间复杂度也是数学的函数表达式。 空间复杂度不是程序占用了多少 bytes的空间,因为这个也没太大意义,所以空间复杂度算的是运行的过程中临时的、额外的变量的个数。 空间复杂度计算规则基本跟实践 复杂度类似&#xff0c…

Flutter For App——一个简单的豆瓣APP

一个简单的豆瓣APP效果视频功能简述功能第三方库接口简述底部导航栏效果图实现初始化BottomNavigationBarItembottomNavigationBar切换页面导致bottomNavigationBar子页面重绘Top250榜单效果图实现Widget树FutureBuilder异常ListView上拉加载电影详情效果图实现高斯模糊网络数据…

设计模式原则 - 单一职责原则(一)

单一职责原则一 官方定义基本介绍二 案例演示普通方式实现解决方案解决方案一解决方案案例分析解决方案二解决方案案例分析案例总结三 注意事项&细节四 如何遵守单一职责原则?一 官方定义 单一职责原则(Single Responsibility Principle, SRP&#x…