深度学习笔记之Seq2Seq(一)基本介绍

news2024/11/27 15:31:36

深度学习笔记之Seq2seq——基本介绍

引言

从本节开始,将介绍 Seq2seq \text{Seq2seq} Seq2seq

回顾:经典循环神经网络结构

经典循环神经网络
在循环神经网络——循环神经网络思想中,我们介绍了经典循环神经网络结构。它的主要思想是:序列信息作为媒介,给定序列数据 x ( 1 ) , x ( 2 ) , ⋯   , x ( T − 1 ) x^{(1)},x^{(2)},\cdots,x^{(\mathcal T-1)} x(1),x(2),,x(T1),求解下一时刻信息 x ( T ) x^{(\mathcal T)} x(T)后验概率结果

  • 整个序列的联合概率分布 P ( X ) \mathcal P(\mathcal X) P(X)可表示为:
    P ( x ( 1 ) , x ( 2 ) , ⋯   , x ( T ) ) = P ( x ( 1 ) ) ⋅ ∏ t = 2 T P ( x ( t ) ∣ x ( 1 ) , ⋯   , x ( t − 1 ) ) \mathcal P(x^{(1)},x^{(2)},\cdots,x^{(\mathcal T)}) = \mathcal P(x^{(1)}) \cdot \prod_{t=2}^{\mathcal T} \mathcal P(x^{(t)} \mid x^{(1)},\cdots,x^{(t-1)}) \\ P(x(1),x(2),,x(T))=P(x(1))t=2TP(x(t)x(1),,x(t1))
  • 其中分解后的每一项(除去第一项),借助隐变量单元 h h h
    { P ( h ( t ) ∣ x ( t − 1 ) , h ( t − 1 ) ) P ( x ( t ) ∣ x ( t − 1 ) , h ( t ) ) t = 2 , 3 , ⋯   , T \begin{cases} \mathcal P(h^{(t)} \mid x^{(t-1)},h^{(t-1)}) \\ \mathcal P(x^{(t)} \mid x^{(t-1)},h^{(t)}) \end{cases} \quad t=2,3,\cdots,\mathcal T {P(h(t)x(t1),h(t1))P(x(t)x(t1),h(t))t=2,3,,T

对应地,它的前馈计算过程表示如下:
{ h ~ ( t + 1 ) = W h ( t ) ⇒ h ( t + 1 ) ⋅ h ( t ) + W x ( t ) ⇒ h ( t + 1 ) ⋅ x ( t ) + b h h ( t + 1 ) = σ ( h ~ ( t + 1 ) ) O ( t + 1 ) = ϕ ( W h ( t + 1 ) ⇒ O ( t + 1 ) ⋅ h ( t + 1 ) + b O ) \begin{cases} \begin{aligned} & \widetilde{h}^{(t+1)} = \mathcal W_{h^{(t)} \Rightarrow h^{(t+1)}} \cdot h^{(t)} + \mathcal W_{x^{(t)} \Rightarrow h^{(t+1)}} \cdot x^{(t)} + b_h \\ & h^{(t+1)} = \sigma(\widetilde{h}^{(t+1)}) \\ & \mathcal O^{(t+1)} = \phi(\mathcal W_{h^{(t+1)} \Rightarrow \mathcal O^{(t+1)}} \cdot h^{(t+1)} + b_{\mathcal O}) \end{aligned} \end{cases} h (t+1)=Wh(t)h(t+1)h(t)+Wx(t)h(t+1)x(t)+bhh(t+1)=σ(h (t+1))O(t+1)=ϕ(Wh(t+1)O(t+1)h(t+1)+bO)
这仅仅是 t ⇒ t + 1 t \Rightarrow t+1 tt+1时刻的前馈计算过程,已知一段序列信息 X ∈ R n x × m × T \mathcal X \in \mathbb R^{n_x \times m \times \mathcal T} XRnx×m×T
这里使用的是 pytorch \text{pytorch} pytorch的向量格式。其中 n x n_x nx表示序列单元 x t ( t = 1 , 2 , ⋯   , T ) x_t(t=1,2,\cdots,\mathcal T) xt(t=1,2,,T)的特征维数; m m m表示 BatchSize \text{BatchSize} BatchSize大小; T \mathcal T T表示序列单元的数量/序列长度。
X = [ x ( 1 ) , x ( 2 ) , ⋯   , x ( T ) ] T \mathcal X = [x^{(1)},x^{(2)},\cdots,x^{(\mathcal T)}]^T X=[x(1),x(2),,x(T)]T
对应循环神经网络的输出 O \mathcal O O表示为:
这里的 n O n_{\mathcal O} nO表示经过神经元输出的特征维数。
O = [ O ( 1 ) , O ( 2 ) , ⋯ O ( T ) ] T ∈ R n O × m × T \mathcal O = [\mathcal O^{(1)},\mathcal O^{(2)},\cdots\mathcal O^{(\mathcal T)}]^T \in \mathbb R^{n_{\mathcal O} \times m \times \mathcal T} O=[O(1),O(2),O(T)]TRnO×m×T
关于 LSTM,GRU \text{LSTM,GRU} LSTM,GRU网络结构同理,可以发现:输入输出在序列维度上存在相同长度

关于循环神经网络的更多引用

  • One to one \text{One to one} One to one模型结构。其网络结构表示如下:
    OnetoOne模型结构
    这里所说的 One to one \text{One to one} One to one是指序列信息并没有发生循环,相当于直接对输入数据进行分析并预测。可将视作一个全连接神经网络,相关任务如:图像分类

  • One to many \text{One to many} One to many模型结构。其网络结构表示如下:
    Onetomany模型结构
    隐藏状态发生循环的条件下,仅使用一个输入去预测一组序列输出。这类模型结构主要包含两种形式:

    • 唯一一个输入信息仅在初始时刻输入一次。代表任务如:文本生成
    • 唯一一个输入信息在每一时刻均输入一次。代表任务如:图像描述——将图像输入,并得到关于该图像的文字描述(文字序列)
  • Many to one \text{Many to one} Many to one模型结构。其网络结构表示如下:
    Manytoone模型结构
    这种网络结构的特点在于:一个序列的输入得到最后时刻的输出,这使得该输出包含完整序列的特征信息。通过根据该信息执行判别任务。如:文本分类、情感分析等。

  • Many to many \text{Many to many} Many to many模型结构。其网络结构表示如下:
    Manytomany模型结构
    该网络结构的特点在于:基于一个序列的输入,生成另一个关联序列的输出。相关任务如:问答系统、机器翻译等。
    其中输入序列和输出序列之间的关系不能狭隘地仅理解为语义相同,它也有可能存在‘语义之间存在因果关系’。像问答系统。

Seq2seq \text{Seq2seq} Seq2seq网络结构

网络结构的角度观察, Seq2seq \text{Seq2seq} Seq2seq模型是由两个 RNN \text{RNN} RNN网络组成的网络结构。该模型广泛应用于自然语言处理的一些领域。如:机器翻译、文字识别等等。 Seq2seq \text{Seq2seq} Seq2seq任务可理解为:从一个序列数据映射到另一个序列数据。相比于循环神经网络 Seq2seq \text{Seq2seq} Seq2seq的思想可表示为:

已知序列数据 X = ( x ( 1 ) , x ( 2 ) , ⋯   , x ( T ) ) \mathcal X = (x^{(1)},x^{(2)},\cdots,x^{(\mathcal T)}) X=(x(1),x(2),,x(T))为条件,关于序列数据 Y = ( y ( 1 ) , y ( 2 ) , ⋯   , y ( T ′ ) ) \mathcal Y = (y^{(1)},y^{(2)},\cdots,y^{(\mathcal T')}) Y=(y(1),y(2),,y(T))后验概率可表示为如下形式:
P ( y ( 1 ) , ⋯   , y ( T ′ ) ∣ x ( 1 ) , ⋯   , x ( T ) ) = P ( y ( 1 ) ∣ X ) ⋅ ∏ t = 2 T ′ P ( y ( t ) ∣ X , y ( 1 ) , ⋯   , y ( t − 1 ) ) \mathcal P(y^{(1)},\cdots,y^{(\mathcal T')} \mid x^{(1)},\cdots,x^{(\mathcal T)}) = \mathcal P(y^{(1)} \mid \mathcal X) \cdot \prod_{t=2}^{\mathcal T'} \mathcal P(y^{(t)} \mid \mathcal X,y^{(1)},\cdots,y^{(t-1)}) P(y(1),,y(T)x(1),,x(T))=P(y(1)X)t=2TP(y(t)X,y(1),,y(t1))
上述公式可以看出, Seq2seq \text{Seq2seq} Seq2seq结构与循环神经网络的一个显著区别在于:关于输出序列 ( y ( 1 ) , y ( 2 ) , ⋯   , y ( T ′ ) ) (y^{(1)},y^{(2)},\cdots,y^{(\mathcal T')}) (y(1),y(2),,y(T))与输入序列,它们的序列长度可以不同

Seq2seq \text{Seq2seq} Seq2seq结构描述

使用两个 RNN \text{RNN} RNN网络组成的 Seq2seq \text{Seq2seq} Seq2seq结构,一个被称作编码器 ( Encoder ) (\text{Encoder}) (Encoder),另一个被称作解码器 ( Decoder ) (\text{Decoder}) (Decoder)
这里使用基于 PyTorch \text{PyTorch} PyTorch深度学习框架的代码进行描述。

  • 关于编码器部分一般使用普通的 RNN \text{RNN} RNN系列结构,给定一组序列数据 { x ( 1 ) , x ( 2 ) , ⋯   , x ( T ) } \{x^{(1)},x^{(2)},\cdots,x^{(\mathcal T)}\} {x(1),x(2),,x(T)},最终目标是将其表征为固定长度 Context \text{Context} Context向量 C \mathcal C C
    这里的 Context \text{Context} Context向量就是 Encoder \text{Encoder} Encoder RNN \text{RNN} RNN结构最终时刻的状态信息。它的大小与各时刻的隐藏状态大小相同。
    该代码来自:序列到序列学习(Seq2seq)【动手学深度学习v2】
class Seq2SeqEncoder(nn.Module):

    def __init__(self,VocabSize,EmbedSize,NumHiddens,NumLayers,Dropout):
        super(Seq2SeqEncoder,self).__init__()

        self.VocabSize = VocabSize
        self.EmbedSize = EmbedSize
        self.Embedding = nn.Embedding(self.VocabSize,self.EmbedSize)
        self.RNN = nn.GRU(self.EmbedSize,NumHiddens,NumLayers,dropout=Dropout)

    def forward(self,x):
        x = self.Embedding(x)
        x = x.permute(1,0,2)
        Output,ContextState = self.RNN(x)
        return Output,ContextState

当然,上述的 Context \text{Context} Context向量仅是其中一种计算方式,这种计算方式并不唯一,根据不同情况的需要进行选择:

  • 也可以对上述代码中的 Output,ContextState \text{Output,ContextState} Output,ContextState构建一个单独的神经元,从而在中间过程增加一个关于 Output,ContextState \text{Output,ContextState} Output,ContextState的复杂函数。并使用相应权重信息进行学习。
  • 其中 h ( T ) h^{(\mathcal T)} h(T)表示 Encoder \text{Encoder} Encoder结构中最后时刻 T \mathcal T T生成的序列信息;函数 f ( ⋅ ) f(\cdot) f()则表示由神经元构建的复杂函数。
    { C = h ( T ) C = f [ h ( T ) ] C = f [ h ( 1 ) , h ( 2 ) , ⋯   , h ( T ) ] \begin{cases} \begin{aligned} & \mathcal C = h^{(\mathcal T)} \\ & \mathcal C = f[h^{(\mathcal T)}] \\ & \mathcal C = f[h^{(1)},h^{(2)},\cdots,h^{(\mathcal T)}] \end{aligned} \end{cases} C=h(T)C=f[h(T)]C=f[h(1),h(2),,h(T)]

关于解码器则负责基于 Context \text{Context} Context向量生成指定序列。它同样存在几种解码器结构。

  • 编码器中产生的 Context \text{Context} Context向量——仅将其作为唯一的输入信息,并且该信息仅作用于初始时刻,并且不再添加其他额外信息。该解码器的网络结构表示如下:

该类型来源于博客Seq2Seq 模型详解,个人认为结构过于简单,甚至都不是循环神经网络的结构:

  • 仅使用 Context \text{Context} Context信息作为输入,后续仅使用前一时刻的 Hidden State \text{Hidden State} Hidden State进行更新;

欢迎小伙伴们讨论。

第1种解码器结构
它的隐藏状态更新过程以及各时刻输出表示如下:
其中符号 h D ( t ) ( t = 1 , 2 , ⋯   , T ′ ) h_{\mathcal D}^{(t)}(t=1,2,\cdots,\mathcal T') hD(t)(t=1,2,,T)表示 Decoder \text{Decoder} Decoder各时刻的隐藏层状态; y D ( t ) ( t = 1 , 2 , ⋯   , T ′ ) y_{\mathcal D}^{(t)}(t=1,2,\cdots,\mathcal T') yD(t)(t=1,2,,T)表示 Decoder \text{Decoder} Decoder各时刻的输出结果,下同。
Hidden state Update :  { h D ( 1 ) = σ ( W C ⇒ h D ( 1 ) ⋅ C + b h D ) h D ( t ) = σ ( W h D ( t − 1 ) ⇒ h D ( t ) ⋅ h D ( t − 1 ) + b h D ) Output :  y D ( t ) = σ ( W h D ( t ) ⇒ y D ( t ) ⋅ h D ( t ) + b y D ) \begin{aligned} & \text{Hidden state Update : }\begin{cases} h_{\mathcal D}^{(1)} = \sigma \left(\mathcal W_{\mathcal C \Rightarrow h_{\mathcal D}^{(1)}} \cdot \mathcal C + b_{h_{\mathcal D}} \right) \\ h_{\mathcal D}^{(t)} = \sigma \left(\mathcal W_{h_{\mathcal D}^{(t-1)} \Rightarrow h_{\mathcal D}^{(t)}} \cdot h_{\mathcal D}^{(t-1)} + b_{h_{\mathcal D}}\right) \end{cases} \\ & \text{Output : } y_{\mathcal D}^{(t)} = \sigma \left(\mathcal W_{h_{\mathcal D}^{(t)} \Rightarrow y_{\mathcal D}^{(t)}} \cdot h_{\mathcal D}^{(t)} + b_{y_{\mathcal D}}\right) \end{aligned} Hidden state Update :  hD(1)=σ(WChD(1)C+bhD)hD(t)=σ(WhD(t1)hD(t)hD(t1)+bhD)Output : yD(t)=σ(WhD(t)yD(t)hD(t)+byD)

  • 和第一种情况相似—— Context \text{Context} Context向量依然作为唯一的输入信息,并且仅作用于初始时刻,区别在于各时刻的输出结果作为下一时刻的输入信息。其解码器网络结果表示如下:
    Seq2seq网络结构
    对应的隐藏状态更新过程以及各时刻输出表示如下:
    Hidden state Update :  { h D ( 1 ) = σ ( W C ⇒ h D ( 1 ) ⋅ C + W ⟨ start ⟩ ⇒ h D ( 1 ) ⋅ ⟨ start ⟩ + b h D ) h D ( t ) = σ ( W y D ( t − 1 ) ⇒ h D ( t ) ⋅ y D ( t − 1 ) + W h D ( t − 1 ) ⇒ h D ( t ) ⋅ h D ( t − 1 ) + b h D ) Output :  y D ( t ) = σ ( W h D ( t ) ⇒ y D ( t ) ⋅ h D ( t ) + b y D ) \begin{aligned} & \text{Hidden state Update : }\begin{cases} h_{\mathcal D}^{(1)} = \sigma \left(\mathcal W_{\mathcal C \Rightarrow h_{\mathcal D}^{(1)}} \cdot \mathcal C + \mathcal W_{\left\langle\text{start}\right\rangle \Rightarrow h_{\mathcal D}^{(1)}} \cdot \left\langle \text{start}\right\rangle + b_{h_{\mathcal D}}\right) \\ h_{\mathcal D}^{(t)} = \sigma \left(\mathcal W_{y_{\mathcal D}^{(t-1)} \Rightarrow h_{\mathcal D}^{(t)}} \cdot y_{\mathcal D}^{(t-1)} + \mathcal W_{h_{\mathcal D}^{(t-1)} \Rightarrow h_{\mathcal D}^{(t)}} \cdot h_{\mathcal D}^{(t-1)} + b_{h_{\mathcal D}}\right) \end{cases} \\ & \text{Output : } y_{\mathcal D}^{(t)} = \sigma \left(\mathcal W_{h_{\mathcal D}^{(t)} \Rightarrow y_{\mathcal D}^{(t)}} \cdot h_{\mathcal D}^{(t)} + b_{y_{\mathcal D}}\right) \end{aligned} Hidden state Update :  hD(1)=σ(WChD(1)C+WstarthD(1)start+bhD)hD(t)=σ(WyD(t1)hD(t)yD(t1)+WhD(t1)hD(t)hD(t1)+bhD)Output : yD(t)=σ(WhD(t)yD(t)hD(t)+byD)
  • 第三种解码器结构—— Context \text{Context} Context向量依然作为唯一的的输入信息,与之前不同的是,该向量作用于解码过程中的任意时刻。其解码器网络结构表示如下:
    它可看作是‘第一种’的延伸。
    第3种解码器结构

对应的隐藏状态更新过程以及各时刻输出表示如下:
{ Hidden State Update :  h D ( t ) = σ ( W C ⇒ h D ( t ) ⋅ C + W h D ( t − 1 ) ⇒ h D ( t ) ⋅ h D ( t − 1 ) + b h D ) Output :  y D ( t ) = σ ( W h D ( t ) ⇒ y D ( t ) ⋅ h D ( t ) + b y D ) \begin{aligned} \begin{cases} &\text{Hidden State Update : } h_{\mathcal D}^{(t)} = \sigma \left(\mathcal W_{\mathcal C \Rightarrow h_{\mathcal D}^{(t)}} \cdot \mathcal C + \mathcal W_{h_{\mathcal D}^{(t-1)} \Rightarrow h_{\mathcal D}^{(t)}} \cdot h_{\mathcal D}^{(t-1)} + b_{h_{\mathcal D}}\right) \\ & \text{Output : } y_{\mathcal D}^{(t)} = \sigma \left(\mathcal W_{h_{\mathcal D}^{(t)} \Rightarrow y_{\mathcal D}^{(t)}} \cdot h_{\mathcal D}^{(t)} + b_{y_{\mathcal D}}\right) \end{cases} \end{aligned} Hidden State Update : hD(t)=σ(WChD(t)C+WhD(t1)hD(t)hD(t1)+bhD)Output : yD(t)=σ(WhD(t)yD(t)hD(t)+byD)

  • 第四种解码器结构——第三种的基础上,将各时刻的输出信息作为下一时刻的输入信息。其解码器网络结构表示如下:
    第二种与第三种的结合版。
    第4种解码器结构
    对应的隐藏状态更新过程以及各时刻输出表示如下:
    { Hidden State Update :  h D ( t ) = σ ( W C ⇒ h D ( t ) ⋅ C + W h D ( t − 1 ) ⇒ h D ( t ) ⋅ h D ( t − 1 ) + W y D ( t − 1 ) ⇒ h D ( t ) ⋅ y D ( t − 1 ) + b h D ) Output :  y D ( t ) = σ ( W h D ( t ) ⇒ y D ( t ) ⋅ h D ( t ) + b y D ) \begin{aligned} \begin{cases} &\text{Hidden State Update : } h_{\mathcal D}^{(t)} = \sigma \left(\mathcal W_{\mathcal C \Rightarrow h_{\mathcal D}^{(t)}} \cdot \mathcal C + \mathcal W_{h_{\mathcal D}^{(t-1)} \Rightarrow h_{\mathcal D}^{(t)}} \cdot h_{\mathcal D}^{(t-1)} + \mathcal W_{y_{\mathcal D}^{(t-1)} \Rightarrow h_{\mathcal D}^{(t)}} \cdot y_{\mathcal D}^{(t-1)} + b_{h_{\mathcal D}}\right) \\ & \text{Output : } y_{\mathcal D}^{(t)} = \sigma \left(\mathcal W_{h_{\mathcal D}^{(t)} \Rightarrow y_{\mathcal D}^{(t)}} \cdot h_{\mathcal D}^{(t)} + b_{y_{\mathcal D}}\right) \end{cases} \end{aligned} Hidden State Update : hD(t)=σ(WChD(t)C+WhD(t1)hD(t)hD(t1)+WyD(t1)hD(t)yD(t1)+bhD)Output : yD(t)=σ(WhD(t)yD(t)hD(t)+byD)
  • 还有一种解码器结构,来自于序列到序列学习(Seq2seq)【动手学深度学习v2】中沐神的代码解读。其思路是: Context \text{Context} Context向量复制成与解码器序列长度相同的数量,并将 Encoder \text{Encoder} Encoder的输入依次与 Context \text{Context} Context向量做拼接 (Concatenate) \text{(Concatenate)} (Concatenate),并将拼接结果作为输入的一部分,另一部分依然是 Context \text{Context} Context自身。对应解码器网络结构表示如下:
    第5种解码器结构

对应代码表示如下:

class Seq2SeqDecoder(nn.Module):
    def __init__(self,VocabSize,EmbedSize,Numhiddens,NumLayer,Dropout):
        super(Seq2SeqDecoder,self).__init__()

        self.VocabSize = VocabSize
        self.EmbedSize = EmbedSize
        self.Numhiddens = Numhiddens
        self.Numlayer = NumLayer

        self.Embedding = nn.Embedding(self.VocabSize,self.EmbedSize)
        self.RNN = nn.GRU(self.EmbedSize + self.Numhiddens,
                          self.Numhiddens,
                          self.Numlayer,
                          dropout=Dropout)
        self.Dense = nn.Linear(self.Numhiddens,self.VocabSize)

    def InitState(self,EncoderOutput):
        return EncoderOutput[1]

    def forward(self,x,State):
        x = self.Embedding(x)
        x = x.permute(1,0,2)
        
        Context = State[-1].repeat(x.shape[0],1,1)
        CatxContext = torch.cat((x,Context),2)
        Output,State = self.RNN(CatxContext,State)
        Output = self.Dense(Output).permute(1,0,2)
        return Output,State

即便它的模型结构变化较大,但是它依然没有跳出其核心思想:
P ( y ( 1 ) , ⋯   , y ( T ′ ) ∣ x ( 1 ) , ⋯   , x ( T ) ) = P ( y ( 1 ) ∣ X ) ⋅ ∏ t = 2 T ′ P ( y ( t ) ∣ X , y ( 1 ) , ⋯   , y ( t − 1 ) ) \mathcal P(y^{(1)},\cdots,y^{(\mathcal T')} \mid x^{(1)},\cdots,x^{(\mathcal T)}) = \mathcal P(y^{(1)} \mid \mathcal X) \cdot \prod_{t=2}^{\mathcal T'} \mathcal P(y^{(t)} \mid \mathcal X,y^{(1)},\cdots,y^{(t-1)}) P(y(1),,y(T)x(1),,x(T))=P(y(1)X)t=2TP(y(t)X,y(1),,y(t1))

相关参考:
Seq2Seq 模型详解
序列到序列学习(Seq2seq)【动手学深度学习v2】
【神经网络】学习笔记十四——Seq2Seq模型

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

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

相关文章

苏轼人生历程不同时期作品

大文豪苏轼才华横溢,一生却屡经贬谪,四处漂泊。但好在他生性豁达,为人率真,又深得道家思想精髓,所以他不仅没有为不幸的遭遇所折服,反而活出了别样的潇洒与风采。也正因如此,他的诗词、他的性情…

人脸融合相关调研

以前的记录,整理发现了值得分享一下。 云解决方案 腾讯: https://ai.qq.com/product/facemerge.shtmlFace: https://www.faceplusplus.com.cn/face-merging/Baidu:https://ai.baidu.com/tech/face/merge 自研 纯Opencv实现,基于…

由世纪互联运营的Microsoft Teams携创新功能正式发布,助力合作伙伴生态共赢

2023年4月18日,北京——由世纪互联运营的Microsoft Teams推出一系列创新功能,围绕企业数字核心能力,赋能数字化协作空间、智能化协作体验、整合生产力工具和工作流、安全合规、构建团队文化等五大落地场景,这将进一步帮助中国市场…

【unity造轮子】最简单的双向可穿越平台制作(Platform Effector 2D的使用)

文章目录 先看最终效果2D平台效应器(Platform Effector 2D)1. 这里简单解释一下2.一些常见的效果包括:3.Platform Effector 2D具有各种属性,使我们可以控制它的行为。这些属性包括: 可向上穿越的平台向下穿越的平台最终…

代码随想录算法训练营第一天| 704.二分查找、27.移除元素

LeetCode704.二分查找 链接:(704.二分查找) 题目描述:给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。 题目就…

远程服务调用的简单应用,并轻松解决LinkedHashMap无法转成相关实体类的问题

🏀(一)为啥需要远程服务调用? 🐠知其然还要知其所以然,在我们的生产项目上一般而言会部署多个微服务,每个微服务会负责不同版块的业务工作。如果某个微服务需要借助另外的某些微服务中的接口才能…

尚硅谷甄选

搭建后台管理系统模板 项目初始化 今天来带大家从0开始搭建一个vue3版本的后台管理系统。一个项目要有统一的规范,需要使用eslintstylelintprettier来对我们的代码质量做检测和修复,需要使用husky来做commit拦截,需要使用commitlint来统一提…

tb6612电机驱动与JGB37-520减速直流电机

tb6612电机驱动与JGB37-520减速直流电机 文章目录 tb6612电机驱动与JGB37-520减速直流电机电机驱动模块TB6612TB6612的引脚说明真值表(直流电机的驱动状态)TB6612的正转反转原理 直流电机原理减速器编码器一、关于编码器的介绍二、编码器的工作原理&…

Linux:DHCP服务

我的DHCP服务器 是 centos7 使用的yum安装DHCP服务(如果不会搭建yum库可以查看) Linux:rpm查询安装 && yum安装_鲍海超-GNUBHCkalitarro的博客-CSDN博客 我的环境为: 两台centos7一台win10 第一台centos7 为 DHCP服务器…

【Python 私有变量和私有方法】零基础也能轻松掌握的学习路线与参考资料

Python是一种面向对象的编程语言。在Python类中,私有变量和私有方法是常见的概念。私有变量和私有方法是指只能在类内部访问的变量和方法。在本文中,我们将介绍Python私有变量和私有方法的学习路线,并给出参考资料和优秀实践。 学习Python面…

【MySQL数据库 | 第七篇】图形化界面工具DataGrip基础应用教学

目录 前言: DataGrip安装界面: 利用DataGrip创建数据库: 利用DataGrip为数据库创建表: 利用datagrip修改表: 添加元素: 结束! 前言: 在之前我们一直接触的是MySQL命令行语句开…

macOS Sonoma 14beta With OpenCore 0.9.3 and winPE双引导分区黑苹果原版镜像

镜像特点(原文地址:http://www.imacosx.cn/113888.html) 完全由黑果魏叔官方制作,针对各种机型进行默认配置,让黑苹果安装不再困难。系统镜像设置为双引导分区,全面去除clover引导分区(如有需要…

RL - 强化学习 马尔可夫决策过程 (MDP) 转换 马尔可夫奖励过程 (MRP)

欢迎关注我的CSDN:https://spike.blog.csdn.net/ 本文地址:https://blog.csdn.net/caroline_wendy/article/details/131097165 马尔可夫决策过程(Markov Decision Process,MDP)和马尔可夫奖励过程(Markov R…

FluxMQ 规则引擎 《一》

规则引擎介绍 演示环境 http://demo.fluxmq.com:50000/ 账号:fluxmq密码:fluxmq 简介 FluxMQ Rule Engine (以下简称规则引擎) 用于配置FluxMQ 消息流与设备事件的处理、响应规则。规则引擎不仅提供了清晰、灵活的 “配置式” 的业务集成方案&#xff0…

(二)CSharp-关于内存分配的总结和疑惑(未解决)

同时看了好几本书,对变量的内存分配概念总是稀里糊涂的。所以干脆专门写一篇文章来对C#内存分配进行研究和总结。 1、值类型和引用类型 对值类型: 值类型实例通常存在线程的堆栈里。即所有值类型的非成员数据都放在线程的堆栈里。如果值类型是类的数据…

4.使用Express跨域资源共享(继上一章)

4.5、CORS跨域资源共享 1.接口的跨域问题 刚才编写的GET和POST接口,存在一个很严重的问题:不支持跨域请求。 解决接口跨域问题的方案主要有两种: ①CORS(主流的解决方案,推荐使用) ②JSONP&#xff08…

Windows软件架构概念

我是荔园微风,作为一名在IT界整整25年的老兵,今天我们来聊聊Windows软件架构的概念。 Shaw和Garlan在他们划时代的著作中以如下方式讨论了软件的体系结构:从第一个程序被划分成模块开始,软件系统就有了体系结构。现在&#xff0c…

PostgreSQL部署出现只有超级用户能创建扩展

最近在Windows Server服务器上部署PostgreSQL12遇到了一个问题,部署完成时,任务问题都没有,也可以远程连接。但是在给数据库添加扩展时出现了如下所述的问题: 执行sql命令create extension "uuid-ossp"出现问题如下:create extension “uuid-ossp” 错误: 创建扩…

文心一言 VS 讯飞星火 VS chatgpt (34)-- 算法导论5.3 1题

一、Marceau 教授不同意引理 5.5 证明中使用的循环不变式。他对第1次送代之前循环不变式是否为真提出质疑。他的理由是,我们可以很容易宣称一个空数组不包含0排列。因此一个空的子数组包含一个0排列的概率应是 0,从而第 1次选代之前循环不变式无效。请重…

Python3+Selenium2完整的自动化测试实现之旅(三):Selenium-webdriver提供的元素定位方法

目录 前言 前端技术名词解释 Selenium-webdriver定位元素 一、 通过id定位 二、通过name定位 三、通过class定位 四、 通过tag定位 五、 通过link定位 六、通过partial_link定位 七、 通过Xpath定位 八、通过CSS定位 总结 前言 本篇以实例介绍selenium下的webdriv…