深度学习之循环神经网络(RNN)

1 为什么需要RNN?

​ 时间序列数据是指在不同时间点上收集到的数据,这类数据反映了某一事物、现象等随时间的变化状态或程度。一般的神经网络,在训练数据足够、算法模型优越的情况下,给定特定的x,就能得到期望y。其一般处理单个的输入,前一个输入和后一个输入完全无关,但实际应用中,某些任务需要能够更好的处理序列的信息,即前面的输入和后面的输入是有关系的。比如:

​ 当我们在理解一句话意思时,孤立的理解这句话的每个词不足以理解整体意思,我们通常需要处理这些词连接起来的整个序列; 当我们处理视频的时候,我们也不能只单独的去分析每一帧,而要分析这些帧连接起来的整个序列。为了解决一些这样类似的问题,能够更好的处理序列的信息,RNN就由此诞生了。

2 图解RNN基本结构

2.1 基本的单层网络结构

​ 在进一步了解RNN之前,先给出最基本的单层网络结构,输入是$x$,经过变换Wx+b和激活函数f得到输出y

在这里插入图片描述

2.2 图解经典RNN结构

​ 在实际应用中,我们还会遇到很多序列形的数据,如:

  • 自然语言处理问题。x1可以看做是第一个单词,x2可以看做是第二个单词,依次类推。

  • 语音处理。此时,x1、x2、x3……是每帧的声音信号。

  • 时间序列问题。例如每天的股票价格等等。

    其单个序列如下图所示:

    在这里插入图片描述

    前面介绍了诸如此类的序列数据用原始的神经网络难以建模,基于此,RNN引入了隐状态 h h h(hidden state), h ​ h​ h可对序列数据提取特征,接着再转换为输出。

    为了便于理解,先计算 h 1 ​ h_1​ h1

    在这里插入图片描述

    注:图中的圆圈表示向量,箭头表示对向量做变换。

    RNN中,每个步骤使用的参数$U,W,b$​相同,$h_2$的计算方式和$h_1​$类似,其计算结果如下:

    在这里插入图片描述

    计算 h 3 h_3 h3, h 4 ​ h_4​ h4也相似,可得:

    在这里插入图片描述

    接下来,计算RNN的输出 y 1 y_1 y1,采用 S o f t m a x Softmax Softmax作为激活函数,根据 y n = f ( W x + b ) y_n=f(Wx+b) yn=f(Wx+b),得 y 1 ​ y_1​ y1:

    在这里插入图片描述

    使用和 y 1 ​ y_1​ y1相同的参数 V , c ​ V,c​ V,c,得到 y 1 , y 2 , y 3 , y 4 ​ y_1,y_2,y_3,y_4​ y1,y2,y3,y4的输出结构:

    在这里插入图片描述

    以上即为最经典的RNN结构,其输入为 x 1 , x 2 , x 3 , x 4 x_1,x_2,x_3,x_4 x1,x2,x3,x4,输出为 y 1 , y 2 , y 3 , y 4 y_1,y_2,y_3,y_4 y1,y2,y3,y4,当然实际中最大值为 y n y_n yn,这里为了便于理解和展示,只计算4个输入和输出。从以上结构可看出,RNN结构的输入和输出等长。

2.3 vector-to-sequence结构

​ 有时我们要处理的问题输入是一个单独的值,输出是一个序列。此时,有两种主要建模方式:

​ 方式一:可只在其中的某一个序列进行计算,比如序列第一个进行输入计算,其建模方式如下:

在这里插入图片描述

​ 方式二:把输入信息X作为每个阶段的输入,其建模方式如下:

在这里插入图片描述

2.4 sequence-to-vector结构

​ 有时我们要处理的问题输入是一个序列,输出是一个单独的值,此时通常在最后的一个序列上进行输出变换,其建模如下所示:

在这里插入图片描述

2.5 Encoder-Decoder结构

​ 原始的sequence-to-sequence结构的RNN要求序列等长,然而我们遇到的大部分问题序列都是不等长的,如机器翻译中,源语言和目标语言的句子往往并没有相同的长度。

​ 其建模步骤如下:

步骤一:将输入数据编码成一个上下文向量 c c c,这部分称为Encoder,得到 c c c有多种方式,最简单的方法就是把Encoder的最后一个隐状态赋值给 c c c,还可以对最后的隐状态做一个变换得到 c c c,也可以对所有的隐状态做变换。其示意如下所示:

在这里插入图片描述

步骤二:用另一个RNN网络(我们将其称为Decoder)对其进行编码,方法一是将步骤一中的 c ​ c​ c作为初始状态输入到Decoder,示意图如下所示:

在这里插入图片描述

方法二是将 c c c作为Decoder的每一步输入,示意图如下所示:

在这里插入图片描述

2.6 以上三种结构各有怎样的应用场景

网络结构结构图示应用场景举例
1 vs N在这里插入图片描述1. 从图像生成文字,输入为图像的特征,输出为一段句子
2. 根据图像生成语音或音乐,输入为图像特征,输出为一段语音或音乐
N vs 1在这里插入图片描述1. 输出一段文字,判断其所属类别
2. 输入一个句子,判断其情感倾向
3. 输入一段视频,判断其所属类别
N vs M在这里插入图片描述1. 机器翻译,输入一种语言文本序列,输出另外一种语言的文本序列
2. 文本摘要,输入文本序列,输出这段文本序列摘要
3. 阅读理解,输入文章,输出问题答案
4. 语音识别,输入语音序列信息,输出文字序列

2.7 图解RNN中的Attention机制

​ 在上述通用的Encoder-Decoder结构中,Encoder把所有的输入序列都编码成一个统一的语义特征 c ​ c​ c再解码,因此, c ​ c​ c中必须包含原始序列中的所有信息,它的长度就成了限制模型性能的瓶颈。如机器翻译问题,当要翻译的句子较长时,一个 c ​ c​ c可能存不下那么多信息,就会造成翻译精度的下降。Attention机制通过在每个时间输入不同的 c ​ c​ c来解决此问题。

​ 引入了Attention机制的Decoder中,有不同的 c c c,每个 c ​ c​ c会自动选择与当前输出最匹配的上下文信息,其示意图如下所示:

在这里插入图片描述

举例,比如输入序列是“我爱中国”,要将此输入翻译成英文:

​ 假如用 a i j a_{ij} aij衡量Encoder中第 j j j阶段的 h j h_j hj和解码时第 i i i阶段的相关性, a i j a_{ij} aij从模型中学习得到,和Decoder的第 i − 1 i-1 i1阶段的隐状态、Encoder 第 j j j个阶段的隐状态有关,比如 a 3 j ​ a_{3j}​ a3j的计算示意如下所示:

在这里插入图片描述

最终Decoder中第 i i i阶段的输入的上下文信息 c i c_i ci来自于所有 h j h_j hj a i j a_{ij} aij的加权和。

其示意图如下图所示:

在这里插入图片描述

​ 在Encoder中, h 1 , h 2 , h 3 , h 4 h_1,h_2,h_3,h_4 h1,h2,h3,h4分别代表“我”,“爱”,“中”,“国”所代表信息。翻译的过程中, c 1 c_1 c1会选择和“我”最相关的上下午信息,如上图所示,会优先选择 a 11 a_{11} a11,以此类推, c 2 c_2 c2会优先选择相关性较大的 a 22 a_{22} a22 c 3 c_3 c3会优先选择相关性较大的 a 33 , a 34 a_{33},a_{34} a33a34,这就是attention机制。

3 RNNs典型特点?

  1. RNNs主要用于处理序列数据。对于传统神经网络模型,从输入层到隐含层再到输出层,层与层之间一般为全连接,每层之间神经元是无连接的。但是传统神经网络无法处理数据间的前后关联问题。例如,为了预测句子的下一个单词,一般需要该词之前的语义信息。这是因为一个句子中前后单词是存在语义联系的。
  2. RNNs中当前单元的输出与之前步骤输出也有关,因此称之为循环神经网络。具体的表现形式为当前单元会对之前步骤信息进行储存并应用于当前输出的计算中。隐藏层之间的节点连接起来,隐藏层当前输出由当前时刻输入向量和之前时刻隐藏层状态共同决定。
  3. 标准的RNNs结构图,图中每个箭头代表做一次变换,也就是说箭头连接带有权值。
  4. 在标准的RNN结构中,隐层的神经元之间也是带有权值的,且权值共享。
  5. 理论上,RNNs能够对任何长度序列数据进行处理。但是在实践中,为了降低复杂度往往假设当前的状态只与之前某几个时刻状态相关,下图便是一个典型的RNNs

在这里插入图片描述

在这里插入图片描述

输入单元(Input units):输入集 { x 0 , x 1 , . . . , x t , x t + 1 , . . . } \bigr\{x_0,x_1,...,x_t,x_{t+1},...\bigr\} {x0,x1,...,xt,xt+1,...}

输出单元(Output units):输出集 { y 0 , y 1 , . . . , y t , y y + 1 , . . . } \bigr\{y_0,y_1,...,y_t,y_{y+1},...\bigr\} {y0,y1,...,yt,yy+1,...}

隐藏单元(Hidden units):输出集 { s 0 , s 1 , . . . , s t , s t + 1 , . . . } \bigr\{s_0,s_1,...,s_t,s_{t+1},...\bigr\} {s0,s1,...,st,st+1,...}

图中信息传递特点:

  1. 一条单向流动的信息流是从输入单元到隐藏单元。
  2. 一条单向流动的信息流从隐藏单元到输出单元。
  3. 在某些情况下,RNNs会打破后者的限制,引导信息从输出单元返回隐藏单元,这些被称为“Back Projections”。
  4. 在某些情况下,隐藏层的输入还包括上一时刻隐藏层的状态,即隐藏层内的节点可以自连也可以互连。
  5. 当前单元(cell)输出是由当前时刻输入和上一时刻隐藏层状态共同决定。

4 CNN和RNN的区别 ?

类别特点描述
相同点1、传统神经网络的扩展。
2、前向计算产生结果,反向计算模型更新。
3、每层神经网络横向可以多个神经元共存,纵向可以有多层神经网络连接。
不同点1、CNN空间扩展,神经元与特征卷积;RNN时间扩展,神经元与多个时间输出计算
2、RNN可以用于描述时间上连续状态的输出,有记忆功能,CNN用于静态输出

5 RNNs和FNNs有什么区别?

  1. 不同于传统的前馈神经网络(FNNs),RNNs引入了定向循环,能够处理输入之间前后关联问题。
  2. RNNs可以记忆之前步骤的训练信息。
    定向循环结构如下图所示

在这里插入图片描述

6.6 RNNs训练和传统ANN训练异同点?

相同点

  1. RNNs与传统ANN都使用BP(Back Propagation)误差反向传播算法。

不同点

  1. RNNs网络参数W,U,V是共享的(具体在本章6.2节中已介绍),而传统神经网络各层参数间没有直接联系。
  2. 对于RNNs,在使用梯度下降算法中,每一步的输出不仅依赖当前步的网络,还依赖于之前若干步的网络状态。

7 为什么RNN 训练的时候Loss波动很大

​ 由于RNN特有的memory会影响后期其他的RNN的特点,梯度时大时小,learning rate没法个性化的调整,导致RNN在train的过程中,Loss会震荡起伏,为了解决RNN的这个问题,在训练的时候,可以设置临界值,当梯度大于某个临界值,直接截断,用这个临界值作为梯度的大小,防止大幅震荡。

8 标准RNN前向输出流程

​ 以 x x x表示输入, h h h是隐层单元, o o o是输出, L L L为损失函数, y y y为训练集标签。 t t t表示 t t t时刻的状态, V , U , W V,U,W V,U,W是权值,同一类型的连接权值相同。以下图为例进行说明标准RNN的前向传播算法:

在这里插入图片描述

对于 t t t时刻:
h ( t ) = ϕ ( U x ( t ) + W h ( t − 1 ) + b ) h^{(t)}=\phi(Ux^{(t)}+Wh^{(t-1)}+b) h(t)=ϕ(Ux(t)+Wh(t1)+b)
其中 ϕ ( ) \phi() ϕ()为激活函数,一般会选择tanh函数, b b b为偏置。

t t t时刻的输出为:
o ( t ) = V h ( t ) + c o^{(t)}=Vh^{(t)}+c o(t)=Vh(t)+c
模型的预测输出为:
y ^ ( t ) = σ ( o ( t ) ) \widehat{y}^{(t)}=\sigma(o^{(t)}) y (t)=σ(o(t))
其中 σ ​ \sigma​ σ为激活函数,通常RNN用于分类,故这里一般用softmax函数。

9 BPTT算法推导

​ BPTT(back-propagation through time)算法是常用的训练RNN的方法,其本质还是BP算法,只不过RNN处理时间序列数据,所以要基于时间反向传播,故叫随时间反向传播。BPTT的中心思想和BP算法相同,沿着需要优化的参数的负梯度方向不断寻找更优的点直至收敛。需要寻优的参数有三个,分别是U、V、W。与BP算法不同的是,其中W和U两个参数的寻优过程需要追溯之前的历史数据,参数V相对简单只需关注目前,那么我们就来先求解参数V的偏导数。
∂ L ( t ) ∂ V = ∂ L ( t ) ∂ o ( t ) ⋅ ∂ o ( t ) ∂ V \frac{\partial L^{(t)}}{\partial V}=\frac{\partial L^{(t)}}{\partial o^{(t)}}\cdot \frac{\partial o^{(t)}}{\partial V} VL(t)=o(t)L(t)Vo(t)
RNN的损失也是会随着时间累加的,所以不能只求t时刻的偏导。
L = ∑ t = 1 n L ( t ) L=\sum_{t=1}^{n}L^{(t)} L=t=1nL(t)

∂ L ∂ V = ∑ t = 1 n ∂ L ( t ) ∂ o ( t ) ⋅ ∂ o ( t ) ∂ V \frac{\partial L}{\partial V}=\sum_{t=1}^{n}\frac{\partial L^{(t)}}{\partial o^{(t)}}\cdot \frac{\partial o^{(t)}}{\partial V} VL=t=1no(t)L(t)Vo(t)

​ W和U的偏导的求解由于需要涉及到历史数据,其偏导求起来相对复杂。为了简化推导过程,我们假设只有三个时刻,那么在第三个时刻 L对W,L对U的偏导数分别为:
∂ L ( 3 ) ∂ W = ∂ L ( 3 ) ∂ o ( 3 ) ∂ o ( 3 ) ∂ h ( 3 ) ∂ h ( 3 ) ∂ W + ∂ L ( 3 ) ∂ o ( 3 ) ∂ o ( 3 ) ∂ h ( 3 ) ∂ h ( 3 ) ∂ h ( 2 ) ∂ h ( 2 ) ∂ W + ∂ L ( 3 ) ∂ o ( 3 ) ∂ o ( 3 ) ∂ h ( 3 ) ∂ h ( 3 ) ∂ h ( 2 ) ∂ h ( 2 ) ∂ h ( 1 ) ∂ h ( 1 ) ∂ W \frac{\partial L^{(3)}}{\partial W}=\frac{\partial L^{(3)}}{\partial o^{(3)}}\frac{\partial o^{(3)}}{\partial h^{(3)}}\frac{\partial h^{(3)}}{\partial W}+\frac{\partial L^{(3)}}{\partial o^{(3)}}\frac{\partial o^{(3)}}{\partial h^{(3)}}\frac{\partial h^{(3)}}{\partial h^{(2)}}\frac{\partial h^{(2)}}{\partial W}+\frac{\partial L^{(3)}}{\partial o^{(3)}}\frac{\partial o^{(3)}}{\partial h^{(3)}}\frac{\partial h^{(3)}}{\partial h^{(2)}}\frac{\partial h^{(2)}}{\partial h^{(1)}}\frac{\partial h^{(1)}}{\partial W} WL(3)=o(3)L(3)h(3)o(3)Wh(3)+o(3)L(3)h(3)o(3)h(2)h(3)Wh(2)+o(3)L(3)h(3)o(3)h(2)h(3)h(1)h(2)Wh(1)

∂ L ( 3 ) ∂ U = ∂ L ( 3 ) ∂ o ( 3 ) ∂ o ( 3 ) ∂ h ( 3 ) ∂ h ( 3 ) ∂ U + ∂ L ( 3 ) ∂ o ( 3 ) ∂ o ( 3 ) ∂ h ( 3 ) ∂ h ( 3 ) ∂ h ( 2 ) ∂ h ( 2 ) ∂ U + ∂ L ( 3 ) ∂ o ( 3 ) ∂ o ( 3 ) ∂ h ( 3 ) ∂ h ( 3 ) ∂ h ( 2 ) ∂ h ( 2 ) ∂ h ( 1 ) ∂ h ( 1 ) ∂ U \frac{\partial L^{(3)}}{\partial U}=\frac{\partial L^{(3)}}{\partial o^{(3)}}\frac{\partial o^{(3)}}{\partial h^{(3)}}\frac{\partial h^{(3)}}{\partial U}+\frac{\partial L^{(3)}}{\partial o^{(3)}}\frac{\partial o^{(3)}}{\partial h^{(3)}}\frac{\partial h^{(3)}}{\partial h^{(2)}}\frac{\partial h^{(2)}}{\partial U}+\frac{\partial L^{(3)}}{\partial o^{(3)}}\frac{\partial o^{(3)}}{\partial h^{(3)}}\frac{\partial h^{(3)}}{\partial h^{(2)}}\frac{\partial h^{(2)}}{\partial h^{(1)}}\frac{\partial h^{(1)}}{\partial U} UL(3)=o(3)L(3)h(3)o(3)Uh(3)+o(3)L(3)h(3)o(3)h(2)h(3)Uh(2)+o(3)L(3)h(3)o(3)h(2)h(3)h(1)h(2)Uh(1)

可以观察到,在某个时刻的对W或是U的偏导数,需要追溯这个时刻之前所有时刻的信息。根据上面两个式子得出L在t时刻对W和U偏导数的通式:
∂ L ( t ) ∂ W = ∑ k = 0 t ∂ L ( t ) ∂ o ( t ) ∂ o ( t ) ∂ h ( t ) ( ∏ j = k + 1 t ∂ h ( j ) ∂ h ( j − 1 ) ) ∂ h ( k ) ∂ W \frac{\partial L^{(t)}}{\partial W}=\sum_{k=0}^{t}\frac{\partial L^{(t)}}{\partial o^{(t)}}\frac{\partial o^{(t)}}{\partial h^{(t)}}(\prod_{j=k+1}^{t}\frac{\partial h^{(j)}}{\partial h^{(j-1)}})\frac{\partial h^{(k)}}{\partial W} WL(t)=k=0to(t)L(t)h(t)o(t)(j=k+1th(j1)h(j))Wh(k)

∂ L ( t ) ∂ U = ∑ k = 0 t ∂ L ( t ) ∂ o ( t ) ∂ o ( t ) ∂ h ( t ) ( ∏ j = k + 1 t ∂ h ( j ) ∂ h ( j − 1 ) ) ∂ h ( k ) ∂ U \frac{\partial L^{(t)}}{\partial U}=\sum_{k=0}^{t}\frac{\partial L^{(t)}}{\partial o^{(t)}}\frac{\partial o^{(t)}}{\partial h^{(t)}}(\prod_{j=k+1}^{t}\frac{\partial h^{(j)}}{\partial h^{(j-1)}})\frac{\partial h^{(k)}}{\partial U} UL(t)=k=0to(t)L(t)h(t)o(t)(j=k+1th(j1)h(j))Uh(k)

整体的偏导公式就是将其按时刻再一一加起来。

9 RNN中为什么会出现梯度消失?

首先来看tanh函数的函数及导数图如下所示:

在这里插入图片描述

sigmoid函数的函数及导数图如下所示:

在这里插入图片描述

从上图观察可知,sigmoid函数的导数范围是(0,0.25],tanh函数的导数范围是(0,1],他们的导数最大都不大于1。

​ 基于6.8中式(9-10)中的推导,RNN的激活函数是嵌套在里面的,如果选择激活函数为 t a n h tanh tanh s i g m o i d sigmoid sigmoid,把激活函数放进去,拿出中间累乘的那部分可得:
∏ j = k + 1 t ∂ h j ∂ h j − 1 = ∏ j = k + 1 t t a n h ′ ⋅ W s \prod_{j=k+1}^{t}{\frac{\partial{h^{j}}}{\partial{h^{j-1}}}} = \prod_{j=k+1}^{t}{tanh^{'}}\cdot W_{s} j=k+1thj1hj=j=k+1ttanhWs

∏ j = k + 1 t ∂ h j ∂ h j − 1 = ∏ j = k + 1 t s i g m o i d ′ ⋅ W s \prod_{j=k+1}^{t}{\frac{\partial{h^{j}}}{\partial{h^{j-1}}}} = \prod_{j=k+1}^{t}{sigmoid^{'}}\cdot W_{s} j=k+1thj1hj=j=k+1tsigmoidWs

梯度消失现象:基于上式,会发现累乘会导致激活函数导数的累乘,如果取tanh或sigmoid函数作为激活函数的话,那么必然是一堆小数在做乘法,结果就是越乘越小。随着时间序列的不断深入,小数的累乘就会导致梯度越来越小直到接近于0,这就是“梯度消失“现象。

​ 实际使用中,会优先选择tanh函数,原因是tanh函数相对于sigmoid函数来说梯度较大,收敛速度更快且引起梯度消失更慢。

10 如何解决RNN中的梯度消失问题?

​ 上节描述的梯度消失是在无限的利用历史数据而造成,但是RNN的特点本来就是能利用历史数据获取更多的可利用信息,解决RNN中的梯度消失方法主要有:

​ 1、选取更好的激活函数,如Relu激活函数。ReLU函数的左侧导数为0,右侧导数恒为1,这就避免了“梯度消失“的发生。但恒为1的导数容易导致“梯度爆炸“,但设定合适的阈值可以解决这个问题。

​ 2、加入BN层,其优点包括可加速收敛、控制过拟合,可以少用或不用Dropout和正则、降低网络对初始化权重不敏感,且能允许使用较大的学习率等。

​ 2、改变传播结构,LSTM结构可以有效解决这个问题。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【从零开始的LeetCode-算法】3238. 求出胜利玩家的数目

给你一个整数 n ,表示在一个游戏中的玩家数目。同时给你一个二维整数数组 pick ,其中 pick[i] [xi, yi] 表示玩家 xi 获得了一个颜色为 yi 的球。 如果玩家 i 获得的球中任何一种颜色球的数目 严格大于 i 个,那么我们说玩家 i 是胜利玩家。…

GIT的基本使用与进阶

GIT的简单入门 一.什么是git? Git 是一个开源的分布式版本控制系统,用于跟踪文件更改、管理代码版本以及协作开发。它主要由 Linus Torvalds 于 2005 年创建,最初是为 Linux 内核开发而设计的。如今,Git 已经成为现代软件开发中…

ReactPress:功能全面的开源发布平台

ReactPress Github项目地址:https://github.com/fecommunity/reactpress 欢迎Star。 此项目是用于构建博客网站的,包含前台展示、管理后台和后端。 此项目是基于 React antd NestJS NextJS MySQL 的,项目已经开源,项目地址在 …

C++初阶——vector

一、什么是vector vector是表示可变大小的数组的序列容器,就像数组一样,vector也采用连续空间来存储元素。也就是说它的访问和数组一样高效,但是它的大小是动态可变的,并且它的大小会被容器自动处理。 二、vector的构造 常用的构…

sql专题 之 where和join on

文章目录 前言where介绍使用过滤结果集关联两个表 连接外连接内连接自然连接 使用inner join和直接使用where关联两个表的区别总结 前言 从数据库查询数据时,一张表不足以查询到我们想要的数据,更多的时候我们需要联表查询。 联表查询我们一般会使用连接…

服务器数据恢复—分区结构被破坏的reiserfs文件系统数据恢复案例

服务器数据恢复环境: 一台服务器中有一组由4块SAS硬盘组建的RAID5阵列,上层安装linux操作系统统。分区结构:boot分区LVM卷swap分区(按照顺序),LVM卷中划分了一个reiserfs文件系统作为根分区。 服务器故障…

文章解读与仿真程序复现思路——电网技术EI\CSCD\北大核心《基于稳态信息和条件分布自适应的风电场阻抗智能辨识和稳定性评估》

本专栏栏目提供文章与程序复现思路,具体已有的论文与论文源程序可翻阅本博主免费的专栏栏目《论文与完整程序》 论文与完整源程序_电网论文源程序的博客-CSDN博客https://blog.csdn.net/liang674027206/category_12531414.html 电网论文源程序-CSDN博客电网论文源…

vue反向代理配置及宝塔配置

vue生产环境和开发环境 反向代理 正向代理 宝塔面板配置 本地小皮面板---NginxApache解决方案_小皮面板反向代理-CSDN博客 上面这个链接供大家参考,我这里面提取vue配置反向代理格式 在vite.config.js页面写入 server: {proxy: {"/api": {target: "…

【NOIP普及组】统计单词数

【NOIP普及组】统计单词数 💐The Begin💐点点关注,收藏不迷路💐 一般的文本编辑器都有查找单词的功能,该功能可以快速定位特定单词在文章中的位置,有的还能统计出特定单词在文章中出现的次数。 现在&#x…

uni-app中使用 unicloud 云开发平台③

文章目录 六、hbuilderX 中使用 unicloud 云开发平台文档传统业务开发流程什么是 unicloudunicloud 优点开发流程uncloud 构成云数据库云存储及 CDN创建云函数工程七、unicloud api 操作云函数调用云函数实现云数据库基本增删改查1. 获取数据库引用云存储操作六、hbuilderX 中使…

STM32 极速入门第一天 点亮一个LED( 使用PlatformIO开发STM32单片机 ) 2024/11/11

什么是STM32? STM32是STMicroelectronics(意法半导体)推出的一系列基于ARM Cortex-M内核的32位Flash微控制器。它们因高性能、低功耗、易于编程和广泛的外设集成而广泛应用于各种嵌入式系统项目中。 使用设备: STM32F103C6T6 我的 keil 装的是 C51 所以…

微信小程序使用阿里巴巴矢量图标库正确姿势

1、打开官网:https://www.iconfont.cn/,把整理好的图标下载解压。 2、由于微信小程序不支持直接在wxss中引入.ttf/.woff/.woff2(在开发工具生效,手机不生效)。我们需要对下载的文件进一步处理。 eot:IE系列…

kafka面试题解答(四)

5、消费者组和分区数之间的关系是怎样的? 消费者组数小于等于分区数,消费者组内每个消费者负责消费不同分区的数据,一个分区只能由一个组内消费者消费。 6、kafka如何知道哪个消费者消费哪个分区? 生产者把数据发送给各个分区&…

Android Profiler 内存分析

Android studio(下面简称AS)为App提供的性能分析工具,在AS3.0替换掉旧的分析工具,对于其使用方法,官方也有对应的介绍:Android Profiler 对于使用方法,我只用到比较简单的功能,高级的…

DXF-模型空间和图纸空间、图层冷冻标志位

‌DXF文件中操作环境的标志码是组代码67 CAD-模型空间和图纸空间-是CAD中两种不同的操作环境 模型空间主要用于建模,是一个没有界限的三维空间,用户在这个空间中以任意尺寸绘制图形,通常按照1:1的比例,以实际尺寸绘制…

前端开发调试之 PC 端调试

以下内容来自稀土掘金青训营课程 bug 与 debug 点击.cls开启动态修改元素的class输入字符串可以动态的给元素添加类名勾选/取消类名可以动态的查看类名生效效果点击具体的样式值(字号、颜色、宽度高度等)可以进行编辑,浏览器内容区域实时预览…

Spring Boot集成SQL Server快速入门Demo

1.什么是SQL Server? SQL Server是由Microsoft开发和推广的以客户/服务器(c/s)模式访问、使用Transact-SQL语言的关系数据库管理系统(DBMS),它最初是由Microsoft、Sybase和Ashton-Tate三家公司共同开发的&…

Self-RAG讲解

Self-RAG Self-RAG 概述 Self-RAG(Self-Reflective Retrieval-Augmented Generation)是一种增强型的RAG(检索增强生成)策略,结合了自我反思和自我评分机制,以提高检索文档和生成内容的质量。通过对检索到…

设计一致性的关键:掌握 Axure 母版使用技巧

设计一致性的关键:掌握 Axure 母版使用技巧 前言 在快节奏的产品开发周期中,设计师们一直在寻找能够提升工作效率和保持设计一致性的方法。 Axure RP,作为一款强大的原型设计工具,其母版功能为设计师们提供了一个强大的解决方案…

uniapp框架配置项pages.json

uniapp框架配置项pages.json pages.json 文件用来对 uni-app 进行全局配置,决定页面文件的路径、窗口样式、原生的导航栏、底部的原生tabbar 等。 globalStyle 全局配置 用于设置应用的状态栏、导航条、标题、窗口背景色等。下面配置项默认应用于每个页面。 注意…