【深度学习(deep learning)】花书第10章 序列建模:循环和递归网络 读书笔记

第10章 序列建模:循环和递归网络

  • 【深度学习(deep learning)】花书第10章 序列建模:循环和递归网络 读书笔记
  • 前言
  • 一、序列模型
    • 1.1 序列模型中的参数共享
      • 1.时延神经网络(卷积)
      • 2.循环神经网络
    • 1.2 计算图展开
  • 二、循环神经网络 RNN
    • 2.1 多对多,隐藏到隐藏
      • **反向传播:通过时间反向传播(BPTT)**
    • 2.2 多对多,输出到隐藏
      • 训练算法:导师驱动过程(teacher forcing)
    • 2.3 多对一,隐藏到隐藏
    • 2.4 基于上下文的RNN序列建模
      • 2.4.1 一对多 隐藏到隐藏 标记到隐藏
      • 2.4.2 多对多 隐藏到隐藏 标记到隐藏
    • 2.5 双向RNN
    • 2.6 基于编码-解码的 序列到序列(seq to seq)
    • 2.7 深度循环网络
  • 三、循环神经网络的优化问题
    • 3.1 长期依赖的问题
    • 3.2 回声状态网络 ESN
    • 3.3 多时间尺度策略
      • 3.3.1 时间维度的跳跃连接
      • 3.3.2 渗漏单元
      • 3.3.3 删除连接
    • 3.4 优化长期依赖
      • 3.4.1 截断梯度
      • 3.4.2 引导信息流的正则化
  • 四、门控RNN
    • 4.1 长短期记忆网络 LSTM
    • 4.2 门控循环单元 GRU
  • 参考资料

前言

打基础,阅读花书,感觉一次性啃不动。看一点算一点,写一点笔记留作纪念。以便日后查看与回顾。大名鼎鼎RNN。2020.12.3-2020.12.4


以下是正式内容。除了特殊标注外,其他配图都来自花书。

一、序列模型

处理序列数据:
x(1),⋯,x(t),⋯,x(τ)\boldsymbol{x}^{\left( 1 \right)},\cdots ,\boldsymbol{x}^{\left( t \right)},\cdots ,\boldsymbol{x}^{\left( \tau \right)} x(1),⋯,x(t),⋯,x(τ)

1.1 序列模型中的参数共享

1.时延神经网络(卷积)

在一维时间序列上使用卷积,输出的每一项是相邻几项输入的函数在每个时间步中使用相同的卷积核。最终效果是读入一个序列,输出一个卷积后的序列。

2.循环神经网络

输出的每一项是前一项输出的函数。由前一项输出得到后一项输出的规则是公用的,因此参数是共享的。

1.2 计算图展开

递归表达式:
s(t)=f(s(t−1);θ)\boldsymbol{s}^{\left( t \right)}=f\left( \boldsymbol{s}^{\left( t-1 \right)};\boldsymbol{\theta } \right) s(t)=f(s(t−1);θ)展开成非递归:
含外部信号的递归表达式:h(t)=f(h(t−1),x(t);θ)\boldsymbol{h}^{\left( t \right)}=f\left( \boldsymbol{h}^{\left( t-1 \right)},\boldsymbol{x}^{\left( t \right)};\boldsymbol{\theta } \right) h(t)=f(h(t−1),x(t);θ)展开的计算图:

h(t)作为过去序列信息的一个有损表示。可以用另一个函数表达这种关系:
h(t)=f(h(t−1),x(t);θ)\boldsymbol{h}^{\left( t \right)}=f\left( \boldsymbol{h}^{\left( t-1 \right)},\boldsymbol{x}^{\left( t \right)};\boldsymbol{\theta } \right) h(t)=f(h(t−1),x(t);θ)=g(t)(x(t),x(t−1),x(t−2),...,x(2),x(1))=g^{\left( t \right)}\left( \boldsymbol{x}^{\left( t \right)},\boldsymbol{x}^{\left( t-1 \right)},\boldsymbol{x}^{\left( t-2 \right)},...,\boldsymbol{x}^{\left( 2 \right)},\boldsymbol{x}^{\left( 1 \right)} \right) =g(t)(x(t),x(t−1),x(t−2),...,x(2),x(1))展开带来的好处:

  1. 可以处理任意长度的序列。因为函数处理的是每个时刻中固定的大小,与序列长度就无关了。
  2. f函数是共享的,也就是参数共享。

二、循环神经网络 RNN

循环神经网络有多种模式。

2.1 多对多,隐藏到隐藏

每个时间步都产生一个输出,隐藏单元之间有循环连接。
将一个长度的输入序列映射到等长的输出序列,且y相互间无关(条件独立的假设)

x是输入,h是隐层表示,o是隐层输出,y只真实标记,L是根据输出与标记计算的损失。

前向传播过程:t=1 到 t=τ(tanh softmax 分别代表激活函数和输出函数)
a(t)=b+Wh(t−1)+Ux(t)\boldsymbol{a}^{\left( t \right)}=\boldsymbol{b}+\boldsymbol{Wh}^{\left( t-1 \right)}+\boldsymbol{Ux}^{\left( t \right)} a(t)=b+Wh(t−1)+Ux(t)h(t)=tan⁡h(a(t))\boldsymbol{h}^{\left( t \right)}=\tan\text{h}\left( \boldsymbol{a}^{\left( t \right)} \right) h(t)=tanh(a(t))o(t)=c+Vh(t)\boldsymbol{o}^{\left( t \right)}=\boldsymbol{c}+\boldsymbol{Vh}^{\left( t \right)} o(t)=c+Vh(t)y^(t)=softmax(o(t))\boldsymbol{\hat{y}}^{\left( t \right)}=softmax\left( \boldsymbol{o}^{\left( t \right)} \right) y^​(t)=softmax(o(t))
总的L 就是序列上损失L(t)的总和。每一个损失都是y的预测的负对数似然。
L=∑tL(t)L=\sum_t{L^{\left( t \right)}} L=t∑​L(t)L(t)=−log⁡pmodel(y(t)∣{x(1),...,x(t)})L^{\left( t \right)}=-\log\text{\ }p_{model}\left( \boldsymbol{y}^{\left( t \right)}|\left\{ \boldsymbol{x}^{\left( 1 \right)},...,\boldsymbol{x}^{\left( t \right)} \right\} \right) L(t)=−log pmodel​(y(t)∣{x(1),...,x(t)})

反向传播:通过时间反向传播(BPTT)

只能串行,且前向传播各状态必须保存,一般训练方法的时空代价都很大。
1.L→L(t)∂L∂L(t)=1\frac{\partial L}{\partial L^{\left( t \right)}}\ =\ 1 ∂L(t)∂L​ = 1
2.L(t)→o(t)(y是o输入到softmax后产生的概率向量)

3.计算h
t = τ: o → h

t = τ-1 到 t = 1:h(t+1) → h(t) , o(t) → h(t)

4.计算每一时间步对共享权重的梯度影响,再计算完全的权重梯度。

2.2 多对多,输出到隐藏

每个时间步都产生一个输出,当前的输出到下一时刻的隐藏之间有循环连接。

牺牲了一些循环连接,模型的表示能力有所削减,但是可以进行并行化。h(t)可以同时计算。

训练算法:导师驱动过程(teacher forcing)

在训练时,用真实标记y去替代隐层输出o
但是y并不能完全代替o,更不能代替h中的信息。因此完全使用导师驱动过程,会导致训练和预测时的差异太大,可以混合使用导师驱动过程和隐层输出o以缓解这个问题。

2.3 多对一,隐藏到隐藏

隐藏单元之间有循环连接,但是只有最后产生一个输出。

2.4 基于上下文的RNN序列建模

上下文:RNN的输入

2.4.1 一对多 隐藏到隐藏 标记到隐藏

接受一个向量x当作输入,映射到一个序列y。
适用任务如图注,给定一个图片(一个向量),得到一个文字序列(一个序列)。

2.4.2 多对多 隐藏到隐藏 标记到隐藏

将一个长度的输入序列映射到等长的输出序列,且y之间相关

2.5 双向RNN

序列中的一个时间步不仅与过去的时间步(以及其输出/标记)有关,还和其未来的时间步(及其输出/标记)相关。
在语音序列/文字序列中相当常见这种相关性。
x 同时输入 到一个序列前向前进的表示h与一个序列后向递进的表示g中,且这 两个表示同时输入产生输出 o。

2.6 基于编码-解码的 序列到序列(seq to seq)

将一个可变长度序列映射到一个长度任意序列

编码器(读取器、输入):一个多对一RNN,将输入序列映射到一个上下文表示(一个向量) 。通常取最后一个表示h当作上下文表示C。
解码器(写入器、输出):一个一对多RNN,将上下文表示映射到输出序列

两个子网络共同训练以最大化目标:
log⁡P(y(1),...,y(ny)∣x(1),...,x(nx))\log\text{\ }P\left( \boldsymbol{y}^{\left( 1 \right)},...,\boldsymbol{y}^{\left( n_y \right)}|\boldsymbol{x}^{\left( 1 \right)},...,\boldsymbol{x}^{\left( n_x \right)} \right) log P(y(1),...,y(ny​)∣x(1),...,x(nx​))
在解码器部分,一对多 有多种输入方式:
1.如2.4.1所示,将输入向量作为各隐层的共同输入
2.将输入向量作为起始状态 h0
3.两者的结合

2.7 深度循环网络

增加RNN中的隐层数目。 当隐层数目变多时,循环连接的连接方式更为多种多样。

(a):添加隐层,各隐层内部分别包含循环连接。
(b):在输入-隐层,隐层-隐层,隐层到输出中,插入MLP(起到提取特征等等多种多样的效果),延长循环连接的路径(但是会难以优化)。
(c):增加跳跃链接,缓解路径延长。

三、循环神经网络的优化问题

3.1 长期依赖的问题

  1. 梯度爆炸:梯度变得很大。
  2. 梯度消失:梯度趋于0,指数级缩小。
  3. 激活函数在多次叠加后 极端非线性。

原因:循环网络参数共享,导致了同一矩阵的高维幂运算。简化表示为:
h(t)=QTΛtQh(0)\boldsymbol{h}^{\left( t \right)}=\boldsymbol{Q}^T\boldsymbol{\Lambda }^t\boldsymbol{Q}h^{\left( 0 \right)} h(t)=QTΛtQh(0) t很大时:小于一的特征值会衰减到0,大于一的会激增。到最后,除特征最大值方向外的所有信息都会被丢弃。

梯度爆炸比较容易解决,可以进行梯度截断。
梯度消失则会导致网络丧失学习长期联系的能力。序列越深,序列初期的信息对应权重越是指数级衰减,越容易被短期信息所扰动,甚至覆盖。

解决办法
1.直接优化长期依赖,比如梯度截断/正则化等。
2.设置隐藏单元,增强其学习历史的能力,比如回声状态网络
3.多时间尺度策略:设计在多个时间尺度上工作的模型,如渗漏单元
4.门控网络,如LSTM

3.2 回声状态网络 ESN

基本思想:设置隐藏单元,使其捕捉过去的输入历史,并且只学习输出权重。
回声状态网络流体状态机都基于这种想法,并称为储层计算
ESN使用连续输出的隐藏单元,流行状态机使用脉冲神经元(二值输出)。
在隐藏单元内形成了可能捕获输入历史不同方面的临时特征池

将循环网络视为动态系统,并设定让 动态系统 接近 稳定边缘的输入与循环权重,以使输入与权重可以表达丰富的历史信息。

jacobian矩阵的谱半径:特征值的最大绝对值。
谱半径在线性网络中的作用:
假设刚开始的梯度向量为g,反向传播jacobian矩阵为J,在n步之后,得到:Jng\boldsymbol{J}^n\boldsymbol{g} Jng则带有扰动的反向传播会得到:Jn(g+δv)\boldsymbol{J}^n\left( \boldsymbol{g}+\delta \boldsymbol{v} \right) Jn(g+δv)偏离了Jnδv\boldsymbol{J}^n\delta \boldsymbol{v} Jnδv如果v是特征向量对应的单位特征向量,则每一步只是对jacobian矩阵进行简单的缩放。偏离的距离是:δ∣λ∣n\delta \left| \lambda \right|^n δ∣λ∣n当v是最大特征值对应的特征向量,则代表扰动可能达到的最宽量。
∣λ∣ >1,偏差指数增长,反之则指数缩小。

回声状态网络的策略是固定权重,使其具有一定的谱半径,比如3。这样会使信息在传播的过程中会逐步放大,但是又会因为非线性单元的饱和而带来一定的稳定作用,从而不会爆炸。

3.3 多时间尺度策略

模型的一部分处理细粒度时间尺度,学习细节;另一部分在粗时间粒度上学习过去的长期信息。

3.3.1 时间维度的跳跃连接

跨时间维度增加连接。

3.3.2 渗漏单元

渗漏单元:使用线性自连接的隐藏单元,可以模拟滑动平均
对于要更新的v值,维护一个滑动平均值:μ(t)←αμ(t−1)+(1−α)v(t)\mu ^{\left( t \right)}\gets \alpha \mu ^{\left( t-1 \right)}+\left( 1-\alpha \right) v^{\left( t \right)} μ(t)←αμ(t−1)+(1−α)v(t)α是 μ (t-1) 到 μ (t) 的线性自连接。
调整连接系数α和时间步数d,可以实现多种方式的平滑地读取过去的信息。

3.3.3 删除连接

删除长度为1的连接。

3.4 优化长期依赖

3.4.1 截断梯度

有多种方案:
1.在参数更新前,逐元素截断参数梯度ifgi>v,gi=vif\ g_i>v\ ,\ g_i=v if gi​>v , gi​=v2.在参数更新前,截断梯度g的范数if∥g∥>v,g=g∥g∥vif\ \lVert \boldsymbol{g} \rVert >v\ ,\ \boldsymbol{g}=\frac{\boldsymbol{g}}{\lVert \boldsymbol{g} \rVert}v if ∥g∥>v , g=∥g∥g​v方案2可以保证方向是不变的,仍然沿着梯度方向,但是大小缩小了。

3.4.2 引导信息流的正则化

在展开的计算图中,希望路径上的梯度乘积接近1(不消失,也不爆炸). 一种办法是门控单元,另一种办法是施加正则化或约束参数。
形式上,希望
(∇h(t)L)∂h(t)∂h(t−1)=∇h(t)L\left( \nabla _{\boldsymbol{h}^{\left( t \right)}}L \right) \frac{\partial \boldsymbol{h}^{\left( t \right)}}{\partial \boldsymbol{h}^{\left( t-1 \right)}}\ =\ \nabla _{\boldsymbol{h}^{\left( t \right)}}L (∇h(t)​L)∂h(t−1)∂h(t)​ = ∇h(t)​L提出以下正则项:Ω=∑t(∥(∇h(t)L)∂h(t)∂h(t−1)∥∥∇h(t)L∥−1)2\varOmega =\sum_t{\left( \frac{\lVert \left( \nabla _{\boldsymbol{h}^{\left( t \right)}}L \right) \frac{\partial \boldsymbol{h}^{\left( t \right)}}{\partial \boldsymbol{h}^{\left( t-1 \right)}}\ \rVert} {\lVert \nabla _{\boldsymbol{h}^{\left( t \right)}}L \rVert}-1 \right)}^2 Ω=t∑​(∥∇h(t)​L∥∥(∇h(t)​L)∂h(t−1)∂h(t)​ ∥​−1)2
这一正则化的优缺点:
1.计算梯度比较困难,但是可以改造后向传播,用恒值近似表示变量。与截断梯度配合,可以显著增加RNN学习的依赖跨度。
2.在处理冗余数据的任务,如语言模型,不如LSTM有效。

四、门控RNN

门控RNN使用门控循环单元,扩展渗漏单元。渗漏单元对于过去信息的读取是基于一个常量系数的,是固定的,学习到的过去信息会一直保存,不能忘记。门控单元允许动态地修改这些权重,网络能自主地进行清除无用的历史信息。

4.1 长短期记忆网络 LSTM

核心贡献:引入自循环,以产生梯度长时间持续流动的路径。自循环的权重视上下文而定,并不固定。由门控制自循环的权重,累积的时间尺度可以动态地改变。
LSTM除了外部RNN循坏外,还有内部的LSTM细胞循环(这一个细胞相当于一个隐藏单元):

状态单元 s:线性单元,维护与渗漏单元类似的线性自环。代表着网络的长期状态信息。s(t)=f(t)∘s(t−1)+g(t)∘i(t)\boldsymbol{s}^{\left( t \right)}=\boldsymbol{f}^{\left( t \right)}\circ \boldsymbol{s}^{\left( t-1 \right)}+\boldsymbol{g}^{\left( t \right)}\circ \boldsymbol{i}^{\left( t \right)} s(t)=f(t)∘s(t−1)+g(t)∘i(t)
遗忘门:sigmoid单元,控制状态单元线性自环的权重。控制保存长期状态,决定上一代长期状态多少写入这一代。
f(t)=σ(bf+Wfhh(t−1)+Wfxx(t))f^{\left( t \right)}=\sigma \left( \boldsymbol{b}^{f}+\boldsymbol{W}_{fh}\boldsymbol{h}^{\left( t-1 \right)}+\boldsymbol{W}_{fx}\boldsymbol{x}^{\left( t \right)} \right) f(t)=σ(bf+Wfh​h(t−1)+Wfx​x(t))
输入门:sigmoid单元,决定一个输入能否累积到状态。控制当前信息写入到长期状态中,决定当前输入多少能写入到长期状态。
g(t)=σ(bg+Wghh(t−1)+Wgxx(t))g^{\left( t \right)}=\sigma \left( \boldsymbol{b}^{g}+\boldsymbol{W}_{gh}\boldsymbol{h}^{\left( t-1 \right)}+\boldsymbol{W}_{gx}\boldsymbol{x}^{\left( t \right)} \right) g(t)=σ(bg+Wgh​h(t−1)+Wgx​x(t))
输入单元:常规的神经元,计算当前输入特征,允许非线性。
i(t)=σ/tan⁡h(b+Whh(t−1)+Wxx(t))i^{\left( t \right)}=\sigma /\tan\text{h}\left( \boldsymbol{b}+\boldsymbol{W}_h\boldsymbol{h}^{\left( t-1 \right)}+\boldsymbol{W}_x\boldsymbol{x}^{\left( t \right)} \right) i(t)=σ/tanh(b+Wh​h(t−1)+Wx​x(t))
输出门:sigmoid单元,决定细胞能否进行输出。控制是否要将长期状态写出到输出。o(t)=σ(bo+Wohh(t−1)+Woxx(t))o^{\left( t \right)}=\sigma \left( \boldsymbol{b}^{o}+\boldsymbol{W}_{oh}\boldsymbol{h}^{\left( t-1 \right)}+\boldsymbol{W}_{ox}\boldsymbol{x}^{\left( t \right)} \right) o(t)=σ(bo+Woh​h(t−1)+Wox​x(t))
最终输出:h(t)=tan⁡h(s(t))∘o(t)\boldsymbol{h}^{\left( t \right)}=\tan\text{h}\left( \boldsymbol{s}^{\left( t \right)} \right) \circ \boldsymbol{o}^{\left( t \right)} h(t)=tanh(s(t))∘o(t)

4.2 门控循环单元 GRU

单个门控单元更新门同时控制遗忘因子和更新状态单元。
更新门:遗忘门与输入门的合并。
u(t)=σ(bu+Wuhh(t−1)+Wuxx(t))u^{\left( t \right)}=\sigma \left( \boldsymbol{b}^{u}+\boldsymbol{W}_{uh}\boldsymbol{h}^{\left( t -1\right)}+\boldsymbol{W}_{ux}\boldsymbol{x}^{\left( t \right)} \right) u(t)=σ(bu+Wuh​h(t−1)+Wux​x(t))
复位门:
r(t)=σ(br+Wrhh(t−1)+Wrxx(t))r^{\left( t \right)}=\sigma \left( \boldsymbol{b}^{r}+\boldsymbol{W}_{rh}\boldsymbol{h}^{\left( t -1\right)}+\boldsymbol{W}_{rx}\boldsymbol{x}^{\left( t \right)} \right) r(t)=σ(br+Wrh​h(t−1)+Wrx​x(t))
输入单元:i(t)=σ/tan⁡h(b+Wh[h(t−1)∘r(t)]+Wxx(t))i^{\left( t \right)}=\sigma /\tan\text{h}\left( \boldsymbol{b}+\boldsymbol{W}_h\left[ \boldsymbol{h}^{\left( t-1 \right)}\circ \boldsymbol{r}^{\left( t \right)} \right] +\boldsymbol{W}_x\boldsymbol{x}^{\left( t \right)} \right) i(t)=σ/tanh(b+Wh​[h(t−1)∘r(t)]+Wx​x(t))
输出:h(t)=(1−u(t))∘h(t−1)+u(t)∘i(t)\boldsymbol{h}^{\left( t \right)}=\left( 1-\boldsymbol{u}^{\left( t \right)} \right) \circ \boldsymbol{h}^{\left( t-1 \right)}+\boldsymbol{u}^{\left( t \right)}\circ \boldsymbol{i}^{\left( t \right)} h(t)=(1−u(t))∘h(t−1)+u(t)∘i(t)

参考资料

1.机器学习,周志华
2.统计学习方法,第二版,李航
3.https://zhuanlan.zhihu.com/p/38431213
4.https://github.com/MingchaoZhu/DeepLearning
5.https://www.bilibili.com/video/BV1kE4119726?p=5&t=1340
6.cs231n
7.https://zybuluo.com/hanbingtao/note/541458
8.https://zhuanlan.zhihu.com/p/30844905
9.https://blog.csdn.net/weixin_42555985/article/details/104422343
10.https://blog.csdn.net/weixin_42555985/article/details/104471711
11.https://zybuluo.com/hanbingtao/note/581764
12.https://blog.csdn.net/weixin_42555985/article/details/104490326

【深度学习(deep learning)】花书第10章 序列建模:循环和递归网络 读书笔记相关推荐

  1. 真的!最难啃的《深度学习》圣经花书,居然新出版了视频课!

    [翻到文末免费学习<机器学习实战>,还能让你看尽CV和NLP完整技术路径以及前沿+经典论文篇目,助你构建深度学习知识框架] 在AI领域内,关于深度学习的课程资料有很多很多,而<深度学 ...

  2. 最难啃的《深度学习》圣经花书,居然新出版了视频课!

    [翻到文末免费学习<机器学习实战>,还能让你看尽CV和NLP完整技术路径以及前沿+经典论文篇目,助你构建深度学习知识框架] 在AI领域内,关于深度学习的课程资料有很多很多,而<深度学 ...

  3. OMG!最难啃的《深度学习》圣经花书,居然新出版了视频课!

    [翻到文末免费学习<机器学习实战>,还能让你看尽CV和NLP完整技术路径以及前沿+经典论文篇目,助你构建深度学习知识框架] 在AI领域内,关于深度学习的课程资料有很多很多,而<深度学 ...

  4. 机器学习(Machine Learning)深度学习(Deep Learning)资料汇总

    本文来源:https://github.com/ty4z2008/Qix/blob/master/dl.md 机器学习(Machine Learning)&深度学习(Deep Learning ...

  5. 机器学习(Machine Learning)深度学习(Deep Learning)资料【转】

    转自:机器学习(Machine Learning)&深度学习(Deep Learning)资料 <Brief History of Machine Learning> 介绍:这是一 ...

  6. 机器学习(Machine Learning)深度学习(Deep Learning)资料集合

    机器学习(Machine Learning)&深度学习(Deep Learning)资料 原文链接:https://github.com/ty4z2008/Qix/blob/master/dl ...

  7. 机器学习 Machine Learning 深度学习 Deep Learning 资料

    机器学习(Machine Learning)&深度学习(Deep Learning)资料 機器學習.深度學習方面不錯的資料,轉載. 原作:https://github.com/ty4z2008 ...

  8. 大量机器学习(Machine Learning)深度学习(Deep Learning)资料

    机器学习目前比较热,网上也散落着很多相关的公开课和学习资源,这里基于课程图谱的机器学习公开课标签做一个汇总整理,便于大家参考对比. 1.Coursera上斯坦福大学Andrew Ng教授的" ...

  9. 机器学习(Machine Learning)amp;深度学习(Deep Learning)资料

    机器学习(Machine Learning)&深度学习(Deep Learning)资料 機器學習.深度學習方面不錯的資料,轉載. 原作:https://github.com/ty4z2008 ...

最新文章

  1. ios c语言头文件,iOS开发 -- C语言基础12(预处理指令)
  2. 让人迷茫的三十岁,从专业技能、行业知识和软实力的人才三角谈起
  3. Linux下安装并破解StarUML
  4. 数据结构-查找-总结归纳知识点
  5. WPF多线程UI更新——两种方法
  6. 高阶函数(Higher-order function)
  7. 山东大学计算机应用基础期中测试,山东大学期末考试计算机应用基础模拟题三套题.pdf...
  8. MySql Connector-Java下载
  9. 【OpenCV】图片对比度和亮度
  10. python与excel-超简单:用Python让Excel飞起来
  11. ImportError: No module named MySQLdb
  12. 基于STM32的PWM电机驱动TB6612、A4950
  13. UiPath Excel内容去重操作(21.10现代设计体验)
  14. LeetCode 3:Longest Substring Without Repeating Charact
  15. cortana在哪里打开_Windows 10开启Cortana的方法步骤
  16. 使用纯JavaCV实现颜色分割 / 轮廓提取 / 离焦 / 线性旋转变焦模糊 / 灰度化 / 标注等处理
  17. Spring学习(二)—— 对象创建方式及依赖注入
  18. 全国计算机软考网络管理员考试大纲(2012)
  19. KNN算法(二) sklearn KNN实践
  20. CodeForces 1216CodeForces 1221 A~D

热门文章

  1. 软硬件学习记录2——通道速率中比特率bps、Bps、波特率含义及换算
  2. 论文写作-如何提高英语论文写作水平
  3. 投影变换--透视投影和正交投影
  4. springboot(九)--统一异常处理(500)、错误页处理(404)
  5. 多场景支付融合,刷脸支付入驻新华书店
  6. PHP正则验证手机号
  7. 【GMS认证】MBA政策解读
  8. 9.1 多元微分学及应用——多元函数的基本概念
  9. 【数据库】主键,超键,候选键,外键区别与联系?
  10. 计算机从图灵到冯诺依曼,电脑是谁发明的 冯·诺依曼和图灵(两人都起到了重要作用)...