word2vec原理

news2024/11/23 16:52:22

1.背景

  2013年,Google开源了一款用于词向量计算的工具—word2vec,引起了工业界和学术界的关注。首先,word2vec可以在百万数量级的词典和上亿的数据集上进行高效地训练;其次,该工具得到的训练结果——词向量(word embedding),可以很好地度量词与词之间的相似性。随着深度学习在自然语言处理中应用的普及,很多人误以为word2vec是一种深度学习算法。其实word2vec算法的背后是一个浅层神经网络。另外需要强调的一点是,word2vec是一个计算word vector的开源工具。当我们在说word2vec算法或模型的时候,其实指的是其背后用于计算word vector的CBoW模型和Skip-gram模型。

2.统计语言模型

什么是统计语言模型呢?

简单来说,统计语言模型就是用来计算一个句子的概率的概率模型,它通常基于一个语料库来构建。

如何计算一段文本序列在某种语言下出现的概率?

例如,在机器翻译的问题中,如果我们知道了目标语言中每句话的概率,就可以从候选集合中挑选出最合理的句子做为翻译结果返回。

统计语言模型给出了这一类问题的一个基本解决框架。对于一段文本序列 S = w 1 , w 2 , . . . , w T S=w_1, w_2, ... , w_T S=w1,w2,...,wT , 它的概率可以表示为:
P ( S ) = P ( w 1 , w 2 , . . . , w T ) = ∏ t = 1 T p ( w t ∣ w 1 , w 2 , . . . , w t − 1 ) P(S)=P(w_1, w_2, ..., w_T)=\prod_{t=1}^Tp(w_t|w_1, w_2, ..., w_{t-1}) P(S)=P(w1,w2,...,wT)=t=1Tp(wtw1,w2,...,wt1)
即将序列的联合概率转化为一系列条件概率的乘积。问题变成了如何去预测这些给定previous words下的条件概率: p ( w t ∣ w 1 , w 2 , . . . , w t − 1 ) p(w_t|w_1,w_2,...,w_{t-1}) p(wtw1,w2,...,wt1)。 一般来说,语言模型都是为了使得条件概率 p ( w t ∣ w 1 , w 2 , . . . , w t − 1 ) p(w_t|w_1,w_2,...,w_{t-1}) p(wtw1,w2,...,wt1) 最大化,不过考虑到近因效应,当前词只与距离它比较近的n个词更加相关(一般n不超过5),而非前面所有的词都有关。 上述公式可以近似为:
p ( w t ∣ w 1 , w 2 , . . . , w t − 1 ) ≈ p ( w t ∣ w t − ( n + 1 ) , . . . , w t − 1 ) p(w_t|w_1, w_2, ..., w_{t-1}) \approx p(w_t|w_{t-(n+1)}, ..., w_{t-1}) p(wtw1,w2,...,wt1)p(wtwt(n+1),...,wt1)
N-gram模型仍有其局限性。

  • 首先,由于参数空间的爆炸式增长,它无法处理更长程的context( N > 3 N>3 N>3)。

    • 在这里插入图片描述
  • 其次,它没有考虑词与词之间内在的联系性。

    • 例如:“the cat is walking in the bedroom"​这句话。如果在训练语料中看到了很多类似“the dog is walking in the bedroom”或是“the cat is running in the bedroom”这样的句子;那么,哪怕此前没有见过这句话"the cat is walking in the bedroom”,也可以从“cat”和“dog”(“walking”和“running”)之间的相似性,推测出这句话的概率。

然而, Ngram模型做不到。 因为Ngram本质上是将词当做一个个孤立的原子单元(atomic unit)去处理的。这种处理方式对应到数学上的形式是一个个离散的one-hot向量(除了一个词典索引的下标对应的方向上是1,其余方向上都是0)。 例如:对于一个大小为5的词典:{“I”, “love”, “nature”, “luaguage”, “processing”},其中的“nature”对应的one-hot向量为: [ 0 , 0 , 1 , 0 , 0 ] [0,0,1,0,0] [0,0,1,0,0]。显然,one-hot向量的维度等于词典的大小。 在动辄上万甚至百万词典的实际应用中,面临着巨大的维度灾难问题(The Curse of Dimensionality)。

3.神经语言模型

NNLM最初由Bengio在2003年发表的一篇论文《A Neural Probabilistic Language Mode》中提出来的,word2vec便是从其中简化训练而来。

NNLM模型的基本思想可以概括如下:

  1. 假定词表中的每一个word都对应着一个连续的特征向量;
  2. 假定一个连续平滑的概率模型,输入一段词向量的序列,可以输出这段序列的联合概率;
  3. 同时学习词向量的权重和概率模型里的参数。

在这里插入图片描述

将整个模型拆分成两部分加以理解:

  • 一个线性的Embedding层
  • 将输入的 N − 1 N−1 N1个one-hot词向量,通过一个共享的 D × V D×V D×V的矩阵 C C C,映射为 N − 1 N−1 N1个分布式的词向量(distributed vector)。其中, V V V是词典的大小, D D D是Embedding向量的维度(一个先验参数)。C矩阵里存储了要学习的word vector。
  • 一个简单的前向反馈神经网络 g g g
  • 它由一个tanh隐层和一个softmax输出层组成。通过将Embedding层输出的 N − 1 N−1 N1个词向量映射为一个长度为 V V V的概率分布向量,从而对词典中的word在输入context下的条件概率做出预估: p ( w i ∣ w 1 , w 2 , . . . , w t − 1 ) ≈ f ( w i , w t − 1 , . . . , w t − n + 1 ) = g ( w i , C ( w t − n + 1 ) , . . . , C ( w t − 1 ) ) p(w_i|w_1,w_2,...,w_{t-1}) \approx f(w_i, w_{t-1}, ..., w_{t-n+1}) = g(w_i, C(w_{t-n+1}), ..., C(w_{t-1})) p(wiw1,w2,...,wt1)f(wi,wt1,...,wtn+1)=g(wi,C(wtn+1),...,C(wt1))

通过最小化一个cross-entropy的正则化损失函数来调整模型的参数   θ \ \theta  θ
L ( θ ) = 1 T ∑ t log ⁡ f ( w t , w t − 1 , . . . , w t − n + 1 ) + R ( θ ) L(\theta)=\frac{1}{T}\sum_t{\log{f(w_t, w_{t-1}, ..., w_{t-n+1})}}+R(\theta) L(θ)=T1tlogf(wt,wt1,...,wtn+1)+R(θ)
其中,模型的参数 θ \theta θ 包括了Embedding层矩阵 C C C 的元素,和前向反馈神经网络模型 g g g 里的权重。这是一个巨大的参数空间。

在用SGD学习更新模型的参数时,并不是所有的参数都需要调整(例如未在输入的context中出现的词对应的词向量)计算的瓶颈主要是在softmax层的归一化函数上(需要对词典中所有的word计算一遍条件概率)。

神经语言模型解决了两个问题:

  • 统计语言模型里关注的条件概率 p ( w t ∣ c o n t e x t ) p(w_t|context) p(wtcontext)的计算
  • 向量空间模型里关注的词向量的表达

通过引入连续的词向量和平滑的概率模型,使得可以在一个连续空间里对序列概率进行建模,从而从根本上缓解数据稀疏性和维度灾难的问题。另一方面,以条件概率 p ( w t ∣ c o n t e x t ) p(w_t|context) p(wtcontext)为学习目标去更新词向量的权重,具有更强的导向性。

4.CBOW & Skip-gram Model

NNLM存在的几个问题:

  • NNLM模型只能处理定长的序列。 在03年的论文里,Bengio等人将模型能够一次处理的序列长度N提高到了5,虽然相比bigram和trigram已经是很大的提升,但依然缺少灵活性。
  • NNLM的训练太慢了。 即便是在百万量级的数据集上,即便是借助了40个CPU进行训练,NNLM也需要耗时数周才能给出一个稍微靠谱的解来。

这时Mikolov注意到,原始的NNLM模型的训练其实可以拆分成两个步骤

  1. 用一个简单模型训练出连续的词向量;
  2. 基于词向量的表达,训练一个连续的Ngram神经网络模型。

而NNLM模型的计算瓶颈主要是在第二步。

如果我们只是想得到word的连续特征向量,是不是可以对第二步里的神经网络模型进行简化呢?

Mikolov是这么想的,也是这么做的。他在2013年一口气推出了两篇paper,并开源了一款计算词向量的工具——至此,word2vec横空出世,主角闪亮登场。

在word2vec中提出了两个模型(假设上下文窗口为3,图来自2013年Mikolov的原始论文,注意这里没有隐藏层,只有输入层、投影层、输出层,且输入层到投影层不带权重,投影层到输出层带权重)

在这里插入图片描述

  • CBOW(Continuous Bag-of-Word):以上下文词汇预测当前词,即用 w t − 2 、 w t − 1 、 w t + 1 、 w t + 2 w_{t-2}、w_{t-1}、w_{t+1}、w_{t+2} wt2wt1wt+1wt+2去预测 w t w_{t} wt

  • SkipGram:以当前词预测其上下文词汇,即用 w t w_{t} wt去预测 w t − 2 、 w t − 1 、 w t + 1 、 w t + 2 w_{t-2}、w_{t-1}、w_{t+1}、w_{t+2} wt2wt1wt+1wt+2

5.基于Hierarchical Softmax的模型

5.1 基本介绍

  传统的神经网络词向量语言模型,里面一般有三层,输入层(词向量),隐藏层和输出层(softmax层)。最大的问题在于从隐藏层到输出的softmax层的计算量很大,因为要计算所有词的softmax概率,再去找概率最大的值。这个模型如下图所示。其中 V V V是词汇表的大小,

在这里插入图片描述

word2vec对这个模型做了改进,

  • 首先,对于从输入层到隐藏层的映射,没有采取神经网络的线性变换加激活函数的方法,而是采用简单的对所有输入词向量求和并取平均的方法。

    • 输入的是三个4维词向量: ( 1 , 2 , 3 , 4 ) , ( 9 , 6 , 11 , 8 ) , ( 5 , 10 , 7 , 12 ) (1,2,3,4),(9,6,11,8),(5,10,7,12) (1,2,3,4),(9,6,11,8),(5,10,7,12),那么word2vec映射后的词向量就是 ( 5 , 6 , 7 , 8 ) (5,6,7,8) (5,6,7,8)。由于这里是从多个词向量变成了一个词向量。
  • 从隐藏层到输出的softmax层这里的计算量做改进。

  • 为了避免要计算所有词的softmax概率,word2vec采样了霍夫曼树来代替从隐藏层到输出softmax层的映射。

Q: 如何映射呢?

  由于把之前所有都要计算的从输出softmax层的概率计算变成了一颗二叉霍夫曼树,那么softmax概率计算只需要沿着树形结构进行就可以了。如下图所示,沿着霍夫曼树从根节点一直走到叶子节点的词 w 2 w_2 w2

在这里插入图片描述

  与神经网络语言模型相比,霍夫曼树的所有内部节点就类似之前神经网络隐藏层的神经元, 其中,根节点的词向量对应投影后的词向量,而所有叶子节点就类似于神经网络softmax输出层的神经元,叶子节点的个数就是词汇表的大小。在霍夫曼树中,隐藏层到输出层的softmax映射不是一下子完成的,而是沿着霍夫曼树一步步完成的,因此这种softmax取名为"Hierarchical Softmax"。

Q: 如何“沿着霍夫曼树一步步完成”呢?

  在word2vec中,采用了二元逻辑回归的方法,即规定沿着左子树走,那么就是负类(霍夫曼树编码1),沿着右子树走,那么就是正类(霍夫曼树编码0)。判别正类和负类的方法是使用sigmoid函数,即:
P ( + ) = σ ( x w T θ ) = 1 1 + e − x w T θ P(+) = \sigma(x_w^T\theta) = \frac{1}{1+e^{-x_w^T\theta}} P(+)=σ(xwTθ)=1+exwTθ1
其中 x w x_w xw 是当前内部节点的词向量,而 θ \theta θ 则是需要从训练样本求出的逻辑回归的模型参数。

Q: 使用霍夫曼树有什么好处呢?

  • 由于是二叉树,之前计算量为 V V V,现在变成了 l o g 2 V log_2V log2V
  • 由于使用霍夫曼树是高频的词靠近树根,这样高频词需要更少的时间会被找到,这符合我们的贪心优化思想。

容易理解,被划分为左子树而成为负类的概率为 P ( − ) = 1 − P ( + ) P(−)=1−P(+) P()=1P(+)在某一个内部节点,要判断是沿左子树还是右子树走的标准就是看 P ( − ) , P ( + ) P(−),P(+) P(),P(+)谁的概率值大。 而控制 P ( − ) , P ( + ) P(−),P(+) P(),P(+)谁的概率值大的因素一个是当前节点的词向量,另一个是当前节点的模型参数 θ \theta θ(从公式里就能看出来)。

对于上图中的 w 2 w_2 w2,如果它是一个训练样本的输出,那么我们期望对于里面的隐藏节点 n ( w 2 , 1 ) n(w_2,1) n(w2,1) P ( − ) P(−) P() 概率大, n ( w 2 , 2 ) ) n(w_2,2)) n(w2,2)) P ( − ) P(−) P() 概率大, n ( w 2 , 3 ) n(w_2,3) n(w2,3) P ( + ) P(+) P(+) 概率大。

目标就是找到合适的所有节点的词向量和所有内部节点 θ \theta θ, 使训练样本达到最大似然。那么如何达到最大似然呢?

5.2 梯度计算

使用最大似然法来寻找所有节点的词向量和所有内部节点 θ \theta θ。先拿上面的 w 2 w_2 w2 例子来看,我们期望最大化下面的似然函数:
∏ i = 1 3 P ( n ( w i ) , i ) = ( 1 − 1 1 + e − x w T θ 1 ) ( 1 − 1 1 + e − x w T θ 2 ) 1 1 + e − x w T θ 3 \prod_{i=1}^3P(n(w_i),i) = (1- \frac{1}{1+e^{-x_w^T\theta_1}})(1- \frac{1}{1+e^{-x_w^T\theta_2}})\frac{1}{1+e^{-x_w^T\theta_3}} i=13P(n(wi),i)=(11+exwTθ11)(11+exwTθ21)1+exwTθ31
对于所有的训练样本,我们期望最大化所有样本的似然函数乘积。

为了方便,我们定义:

  • 输入的词为 w w w ,其从输入层词向量求和平均后的霍夫曼树根节点词向量为 x w x_w xw, 从根节点到 w w w所在的叶子节点,包含的节点总数为 l w l_w lw,
  • w w w 在霍夫曼树中从根节点开始,经过的第 i i i 个节点表示为 p i w p^w_i piw ,对应的霍夫曼编码为 d i w ∈ { 0 , 1 } d^w_i\in \{0,1\} diw{0,1} ,其中 i = 2 , 3 , . . . l w i=2,3,...l_w i=2,3,...lw。而该节点对应的模型参数表示为 θ i w \theta^w_i θiw, 其中 i = 1 , 2 , . . . l w − 1 i=1,2,...l_{w−1} i=1,2,...lw1,没有 i = l w i=l_w i=lw 是因为模型参数仅仅针对于霍夫曼树的内部节点。

定义 w w w经过的霍夫曼树某一个节点 j j j的逻辑回归概率为 P ( d j w ∣ x w , θ j − 1 w ) P(d_j^w|x_w, \theta_{j-1}^w) P(djwxw,θj1w),其表达式为:
P ( d j w ∣ x w , θ j − 1 w ) = { σ ( x w T θ j − 1 w ) d j w = 0 1 − σ ( x w T θ j − 1 w ) d j w = 1 P(d_j^w|x_w, \theta_{j-1}^w)= \begin{cases} \sigma(x_w^T\theta_{j-1}^w)& {d_j^w=0}\\[2ex] 1- \sigma(x_w^T\theta_{j-1}^w) & {d_j^w = 1} \end{cases} P(djwxw,θj1w)= σ(xwTθj1w)1σ(xwTθj1w)djw=0djw=1
那么对于某一个目标输出词 w w w,其最大似然为:
∏ j = 2 l w P ( d j w ∣ x w , θ j − 1 w ) = ∏ j = 2 l w [ σ ( x w T θ j − 1 w ) ] 1 − d j w [ 1 − σ ( x w T θ j − 1 w ) ] d j w \prod_{j=2}^{l_w}P(d_j^w|x_w, \theta_{j-1}^w) = \prod_{j=2}^{l_w} [\sigma(x_w^T\theta_{j-1}^w)] ^{1-d_j^w}[1-\sigma(x_w^T\theta_{j-1}^w)]^{d_j^w} j=2lwP(djwxw,θj1w)=j=2lw[σ(xwTθj1w)]1djw[1σ(xwTθj1w)]djw
在word2vec中,由于使用的是随机梯度上升法,所以并没有把所有样本的似然乘起来得到真正的训练集最大似然,仅仅每次只用一个样本更新梯度,这样做的目的是减少梯度计算量。这样我们可以得到 w w w的对数似然函数 L L L如下:
L = l o g ∏ j = 2 l w P ( d j w ∣ x w , θ j − 1 w ) = ∑ j = 2 l w ( ( 1 − d j w ) l o g [ σ ( x w T θ j − 1 w ) ] + d j w l o g [ 1 − σ ( x w T θ j − 1 w ) ] ) L= log \prod_{j=2}^{l_w}P(d_j^w|x_w, \theta_{j-1}^w) = \sum\limits_{j=2}^{l_w} \left((1-d_j^w) log \left[\sigma(x_w^T\theta_{j-1}^w)\right] + d_j^w log\left[1-\sigma(x_w^T\theta_{j-1}^w)\right]\right) L=logj=2lwP(djwxw,θj1w)=j=2lw((1djw)log[σ(xwTθj1w)]+djwlog[1σ(xwTθj1w)])
要得到模型中 w w w 词向量和内部节点的模型参数 θ \theta θ, 使用梯度上升法即可。首先我们求模型参数 θ j − 1 w \theta^w_{j-1} θj1w 的梯度:
∂ L ∂ θ j − 1 w = ( 1 − d j w ) ( σ ( x w T θ j − 1 w ) ( 1 − σ ( x w T θ j − 1 w ) σ ( x w T θ j − 1 w ) x w − d j w ( σ ( x w T θ j − 1 w ) ( 1 − σ ( x w T θ j − 1 w ) 1 − σ ( x w T θ j − 1 w ) x w = ( 1 − d j w ) ( 1 − σ ( x w T θ j − 1 w ) ) x w − d j w σ ( x w T θ j − 1 w ) x w = ( 1 − d j w − σ ( x w T θ j − 1 w ) ) x w \begin{align} \frac{\partial L}{\partial \theta_{j-1}^w} & = (1-d_j^w)\frac{(\sigma(x_w^T\theta_{j-1}^w)(1-\sigma(x_w^T\theta_{j-1}^w)}{\sigma(x_w^T\theta_{j-1}^w)}x_w - d_j^w \frac{(\sigma(x_w^T\theta_{j-1}^w)(1-\sigma(x_w^T\theta_{j-1}^w)}{1- \sigma(x_w^T\theta_{j-1}^w)}x_w \\[3ex] & = (1-d_j^w)(1-\sigma(x_w^T\theta_{j-1}^w))x_w - d_j^w\sigma(x_w^T\theta_{j-1}^w)x_w \\[2ex] & = (1-d_j^w-\sigma(x_w^T\theta_{j-1}^w))x_w \end{align} θj1wL=(1djw)σ(xwTθj1w)(σ(xwTθj1w)(1σ(xwTθj1w)xwdjw1σ(xwTθj1w)(σ(xwTθj1w)(1σ(xwTθj1w)xw=(1djw)(1σ(xwTθj1w))xwdjwσ(xwTθj1w)xw=(1djwσ(xwTθj1w))xw
θ j − 1 w \theta^w_{j-1} θj1w的更新公式为:
θ j − 1 w : = θ j − 1 w + η [ 1 − d j w − σ ( x w T θ j − 1 w ) ] x w \theta^w_{j-1}:=\theta^w_{j-1}+\eta\left[1-d_j^w-\sigma(x_w^T\theta_{j-1}^w)\right]x_w θj1w:=θj1w+η[1djwσ(xwTθj1w)]xw
η \eta η表示学习率。

同样的方法,可以求出 x w x_w xw的梯度表达式如下:
∂ L ∂ x w = ∑ j = 2 l w ( 1 − d j w − σ ( x w T θ j − 1 w ) ) θ j − 1 w \frac{\partial L}{\partial x_w} = \sum\limits_{j=2}^{l_w}(1-d_j^w-\sigma(x_w^T\theta_{j-1}^w))\theta_{j-1}^w xwL=j=2lw(1djwσ(xwTθj1w))θj1w
有了梯度表达式,我们就可以用梯度上升法进行迭代来一步步的求解我们需要的所有的 θ j − 1 w \theta^w_{j-1} θj1w x w x_w xw

5.3 基于Hierarchical Softmax的CBOW模型

CBOW模型(上下文词预测当前词)的网络结构,包括三层:输入层、投影层和输出层。

定义词向量的维度大小 M M M,以及CBOW的上下文大小 2 c 2c 2c,这样对于训练样本中的每一个词,其前面的 c c c 个词和后面的 c c c 个词作为了CBOW模型的输入,该词本身作为样本的输出,期望softmax概率最大。

首先 需要先将词汇表建立成一颗霍夫曼树。
在这里插入图片描述

  • 输入层:包含上下文中 2 c 2c 2c个词的词向量

  • 投影层:将输入层的 2 c 2c 2c个两个做求和积累
    x w = 1 2 c ∑ i = 1 2 c x i x_w = \frac{1}{2c}\sum\limits_{i=1}^{2c}x_i xw=2c1i=12cxi

  • 输出层:对应一棵二叉树(Huffman树),由语料库中出现过的词当作叶子结点,各个词的频率当作权值构建的一棵Huffman树。(叶子结点的个数: N N N(词典的所有词),非叶子结点: N − 1 N-1 N1)。

构建完Huffman树之后, 通过梯度上升法来更新的 θ j − 1 w \theta^w_{j−1} θj1w x w x_w xw,注意这里的 x w x_w xw是由 2 c 2c 2c个词向量相加而成,梯度更新完毕后会用梯度项直接更新原始的各个 x i ( i = 1 , 2 , . . . , 2 c ) x_i(i=1,2,...,2c) xi(i=1,2,...,2c),即:
θ j − 1 w = θ j − 1 w + η ( 1 − d j w − σ ( x w T θ j − 1 w ) ) x w x i = x i + η ∑ j = 2 l w ( 1 − d j w − σ ( x w T θ j − 1 w ) ) θ j − 1 w    ( i = 1 , 2.. , 2 c ) \theta_{j-1}^w = \theta_{j-1}^w + \eta (1-d_j^w-\sigma(x_w^T\theta_{j-1}^w))x_w\\[2ex] x_i= x_i +\eta \sum\limits_{j=2}^{l_w}(1-d_j^w-\sigma(x_w^T\theta_{j-1}^w))\theta_{j-1}^w \;(i =1,2..,2c) θj1w=θj1w+η(1djwσ(xwTθj1w))xwxi=xi+ηj=2lw(1djwσ(xwTθj1w))θj1w(i=1,2..,2c)
其中 η \eta η 为梯度上升法的步长。

基于Hierarchical Softmax的CBOW模型算法流程,梯度迭代使用了随机梯度上升法:

输入:基于CBOW的语料训练样本,词向量的维度大小 M M M,CBOW的上下文大小 2 c 2c 2c,步长 η \eta η

输出:霍夫曼树的内部节点模型参数 θ \theta θ,所有的词向量 w w w

  1. 基于语料训练样本建立霍夫曼树。

  2. 随机初始化所有的模型参数 θ \theta θ,所有的词向量 w w w

  3. 进行梯度上升迭代过程,对于训练集中的每一个样本 $(context(w),w) 做如下处理:

    a) e = 0 e=0 e=0,计算 x w = 1 2 c ∑ i = 1 2 c x i x_w= \frac{1}{2c}\sum\limits_{i=1}^{2c}x_i xw=2c1i=12cxi

    b) for j = 2 j=2 j=2 to l w l_w lw:

f = σ ( x w T θ j − 1 w ) g = ( 1 − d j w − f ) η e = e + g θ j − 1 w θ j − 1 w = θ j − 1 w + g x w f = \sigma(x_w^T\theta_{j-1}^w)\\[2ex] g = (1-d_j^w-f)\eta\\[2ex] e = e + g\theta_{j-1}^w\\[2ex] \theta_{j-1}^w= \theta_{j-1}^w + gx_w f=σ(xwTθj1w)g=(1djwf)ηe=e+gθj1wθj1w=θj1w+gxw
​ c) 对于 c o n t e x t ( w ) context(w) context(w)中的每一个词向量 x i x_i xi(共 2 c 2c 2c个)进行更新:
x i = x i + e x_i = x_i + e xi=xi+e
​ d) 如果梯度收敛,则结束梯度迭代,否则回到步骤3继续迭代。

5.4 基于Hierarchical Softmax的Skip-Gram模型

Skip-Gram模型(当前词预测上下文词)的网络结构,包括三层:输入层、投影层和输出层。

定义词向量的维度大小 M M M,以及CBOW的上下文大小 2 c 2c 2c, 对于训练样本中的每一个词,该词本身作为样本的输入, 其前面的 c c c 个词和后面的 c c c 个词作为了Skip-Gram模型的输出,期望这些词的softmax概率比其他的词大。

首先 需要先将词汇表建立成一颗霍夫曼树。

在这里插入图片描述

  • 输入层:只包含当前样本的中心词 w w w的词向量 v ( w ) \bold v(w) v(w)
  • 投影层:将 v ( w ) \bold v(w) v(w) 投影到 v ( w ) \bold v(w) v(w),投影层是多余的
  • 输出层:对应一棵二叉树(Huffman树),由语料库中出现过的词当作叶子结点,各个词的频率当作权值构建的一棵Huffman树。(叶子结点的个数: N N N(词典的所有词),非叶子结点: N − 1 N-1 N1)。

构建完Huffman树之后, 通过梯度上升法来更新我们的 θ j − 1 w \theta^w_{j−1} θj1w x w x_w xw,注意这里的 x w x_w xw周围有 2 c 2c 2c个词向量, 此时期望 P ( x i ∣ x w ) , i = 1 , 2...2 c P(x_i|x_w),i=1,2...2c P(xixw),i=1,2...2c最大。 由于上下文是相互的,在期望 P ( x i ∣ x w ) , i = 1 , 2...2 c P(x_i|x_w),i=1,2...2c P(xixw),i=1,2...2c最大化的同时,反过来也期望 P ( x w ∣ x i ) , i = 1 , 2...2 c P(x_w|x_i),i=1,2...2c P(xwxi),i=1,2...2c最大。那么是使用 P ( x i ∣ x w ) ) P(x_i|x_w)) P(xixw))好还是 P ( x w ∣ x i ) P(x_w|x_i) P(xwxi)好?

word2vec使用了后者,好处就是在一个迭代窗口内,不是只更新 x w x_w xw 一个词,而是 x i   ( i = 1 , 2...2 c   ) x_i\ (i=1,2...2c\ ) xi (i=1,2...2c ) 2 c 2c 2c 个词。这样整体的迭代会更加的均衡。因此,Skip-Gram模型并没有和CBOW模型一样对输入进行迭代更新,而是对 2 c 2c 2c 个输出进行迭代更新。

基于Hierarchical Softmax的Skip-Gram模型算法流程,梯度迭代使用了随机梯度上升法:

输入:基于 Skip-Gram 的语料训练样本,词向量的维度大小 M M M, Skip-Gram 的上下文大小 2 c 2c 2c,步长 η \eta η

输出:霍夫曼树的内部节点模型参数 θ \theta θ,所有的词向量 w w w

  1. 基于语料训练样本建立霍夫曼树。

  2. 随机初始化所有的模型参数 θ \theta θ,所有的词向量 w w w

  3. 进行梯度上升迭代过程,对于训练集中的每一个样本 ( c o n t e x t ( w ) , w ) (context(w),w) (context(w),w)做如下处理:

    a) for i = 1 i=1 i=1 to 2 c 2c 2c:

    ​ i) e = 0 e=0 e=0

    ​ ii) for j = 2 j=2 j=2 to l w l_w lw:

f = σ ( x w T θ j − 1 w ) g = ( 1 − d j w − f ) η e = e + g θ j − 1 w θ j − 1 w = θ j − 1 w + g x w f = \sigma(x_w^T\theta_{j-1}^w)\\[2ex] g = (1-d_j^w-f)\eta\\[2ex] e = e + g\theta_{j-1}^w\\[2ex] \theta_{j-1}^w= \theta_{j-1}^w + gx_w f=σ(xwTθj1w)g=(1djwf)ηe=e+gθj1wθj1w=θj1w+gxw

​ iii)
x i = x i + e x_i = x_i + e xi=xi+e
​ b) 如果梯度收敛,则结束梯度迭代,否则回到步骤a继续迭代。

5.5.举个栗子

假设2014年世界杯期间,从新浪微博中抓取了若干条与足球相关的微博,经统计,“我”、“喜欢”、“观看”、“巴西”、“足球”、“世界杯”这个六个词出现的次数分别为15,8,6,5,3,1。这6个词的Huffman编码,其中约定(词频大的)左孩子结点编码为1,(词频较小)右孩子结点编码为0。“我”、“喜欢”、“观看”、“巴西”、“足球”、“世界杯”这个六个词的Huffman编码为:0,111,110,101,1001,1000。
在这里插入图片描述

现在考虑词 w = " 足球 " w="足球" w="足球"的情形。

在这里插入图片描述

  • 从根结点到足球结点由4条红色边串起来的5个结点构成路径 p w p^w pw,其路径长度 l w = 5 l_w=5 lw=5
  • 路径 p w p^w pw上的5个结点分别为: p 1 w , p 2 w , p 3 w , p 4 w , p 5 w p^w_1,p^w_2,p^w_3,p^w_4,p^w_5 p1w,p2w,p3w,p4w,p5w,其中 p 1 w p^w_1 p1w对应根结点
  • d 2 w , d 3 w , d 4 w , d 5 w d^w_2,d^w_3,d^w_4,d^w_5 d2w,d3w,d4w,d5w分别为 1 , 0 , 0 , 1 1,0,0,1 1,0,0,1,即足球的Huffman编码为 1001 1001 1001
  • θ 1 , θ 2 , θ 3 , θ 4 \theta_1,\theta_2,\theta_3,\theta_4 θ1,θ2,θ3,θ4分别表示路径 p w p^w pw上4个非叶子结点对应的向量

从根结点到“足球”叶子结点,中间经过了4个分支(每条红色的边对应一次分支),而每一次分支可以视为一次二分类。Huffman编码为1的结点定义为负类,编码为0的结点定义为正类(这只是一个约定)。

对于从根结点到“足球”叶子结点,经过了4次二分类,每次分类的结果的概率如下:

  • 第1次: p ( d 2 w ∣ x w , θ 1 w ) = 1 − σ ( x w T θ 1 w ) p(d^w_2|x_w,\theta^w_1)=1-\sigma(x^T_w\theta^w_1) p(d2wxw,θ1w)=1σ(xwTθ1w)
  • 第2次: p ( d 3 w ∣ x w , θ 2 w ) = σ ( x w T θ 2 w ) p(d^w_3|x_w,\theta^w_2)=\sigma(x^T_w\theta^w_2) p(d3wxw,θ2w)=σ(xwTθ2w)
  • 第3次: p ( d 4 w ∣ x w , θ 3 w ) = σ ( x w T θ 3 w ) p(d^w_4|x_w,\theta^w_3)=\sigma(x^T_w\theta^w_3) p(d4wxw,θ3w)=σ(xwTθ3w)
  • 第4次: p ( d 5 w ∣ x w , θ 4 w ) = 1 − σ ( x w T θ 4 w ) p(d^w_5|x_w,\theta^w_4)=1-\sigma(x^T_w\theta^w_4) p(d5wxw,θ4w)=1σ(xwTθ4w)

所以要求的 p ( 足球 ∣ C o n t e x t ( 足球 ) ) p(足球|Context(足球)) p(足球Context(足球))等于上述4个概率的乘积
p ( 足球 ∣ C o n t e x t ( 足球 ) ) = ∏ 2 5 p ( d j w ∣ x w , θ j − 1 w ) p(足球|Context(足球))=\prod\limits^5\limits_2p(d^w_j|x_w,\theta^w_{j-1}) p(足球Context(足球))=25p(djwxw,θj1w)

5.6 分层softmax(Hierachical Softmax)思想

  • Hierachical Softmax的基本思想就是首先将词典中的每个词按照词频大小构建出一棵Huffman树,保证词频较大的词处于相对比较浅的层,词频较低的词相应的处于Huffman树较深层的叶子节点,每一个词都处于这棵Huffman树上的某个叶子节点。

  • 将原本的一个 ∣ V ∣ |V| V分类问题变成了 l o g ⁡ ∣ V ∣ log⁡|V| log⁡∣V次的二分类问题。

  • 原先要计算 P ( w t ∣ c t ) P(w_t|c_t) P(wtct)的时候,因为使用的是普通的softmax,势必要求词典中的每一个词的概率大小 ,那么如何减少计算量呢?

  • 计算当前词 w t w_t wt 在其上下文中的概率大小,只需要把它变成在Huffman树中的路径预测问题就可以了,因为当前词 w t w_t wt 在Huffman树中对应到一条路径,这条路径由这棵二叉树中从根节点开始,经过一系列中间的父节点,最终到达当前这个词的叶子节点而组成,那么在每一个父节点上,都对应的是一个二分类问题(本质上就是一个LR分类器),而Huffman树的构造过程保证了树的深度为 l o g ⁡ ∣ V ∣ log⁡|V| log⁡∣V,所以也就只需要做 l o g ⁡ ∣ V ∣ log⁡|V| log⁡∣V次二分类便可以求得 P ( w t ∣ c t ) P(w_t|c_t) P(wtct) 的大小。

6.基于Negative Sampling的模型

6.1 背景

  使用霍夫曼树来代替传统的神经网络,可以提高模型训练的效率。但是如果我们的训练样本里的中心词 w w w是一个很生僻的词,那么就得在霍夫曼树中辛苦的向下走很久了。能不能不用搞这么复杂的一棵霍夫曼树,将模型变的更加简单呢?

Negative Sampling就是这么一种求解word2vec模型的方法,它摒弃了霍夫曼树,采用了Negative Sampling(负采样)的方法来求解。

6.2 语言模型的训练过程

对于文本“”Thou shalt not make a machine in the likeness of a human mind“而言:

  • 构造样本,假设窗口大小=5

在这里插入图片描述

  • 训练过程,用not预测thou

    • 预测结果

在这里插入图片描述

  如上图一样,预测结果极度不靠谱,not本该预测thou,但其却将 0.4 0.4 0.4 的概率预测成了taco,预测错了,如何解决?计算损失loss,利用梯度

  • 误差计算

在这里插入图片描述

现在误差向量可以被用于更新模型了,所以在下一轮预测中,如果用not作为输入,我们更有可能得到thou作为输出了。接下来继续对数据集内下一份样本进行同样的操作,直到遍历所有的样本。这就是一轮(epoch)了。我们再多做几轮(epoch),得到训练过的模型,于是就可以从中提取嵌入矩阵来用于其他应用了。

如果按照上述训练方法,则not是不是要把整个词表的所有的都要预测一遍?

6.3 理解负采样的过程

比如有一个训练样本,中心词是 w w w,它周围上下文共有 2 c 2c 2c 个词,记为 c o n t e x t ( w ) context(w) context(w)。由于这个中心词 w w w 的确和 c o n t e x t ( w ) context(w) context(w) 相关存在,因此它是一个真实的正例。通过Negative Sampling采样,得到neg个和 w w w不同的词   w i , i = 1 , 2 , . . n e g \ w_i,i=1,2,..neg  wi,i=1,2,..neg, 这样 c o n t e x t ( w ) context(w) context(w) w i w_i wi就组成了neg个并不真实存在的负例 作为负例。利用这一个正例和neg个负例,进行二元逻辑回归,得到负采样对应每个词 w i w_i wi对应的模型参数 θ i \theta_i θi,和每个词的词向量。

对于上述问题,那么负采样的样本如何获取? 从词汇表中随机抽取单词就可以了
在这里插入图片描述

训练流程:

  • 在训练过程开始之前,预先处理正在训练模型的文本。确定词典的大小(vocab_size,比如说10,000)以及哪些词被它包含在内。
  • 在训练阶段的开始,创建两个矩阵——Embedding矩阵和Context矩阵。

在这里插入图片描述

  • 在训练过程开始时,用 “随机值初始化” 这些矩阵。开始训练过程。在每个训练步骤中,采取一个相邻的例子及其相关的非相邻例子。

在这里插入图片描述

  • 输入单词not和输出/上下文单词: thou(实际邻居词),aaron和taco(负面例子)。
    对于输入词,查看Embedding矩阵。对于上下文单词,查看Context矩阵
  • 计算输入嵌入与每个上下文嵌入的点积。在每种情况下,结果都将是表示输入和上下文嵌入的相似性的数字。计算误差,使用梯度下降法更新参数。

在这里插入图片描述

6.4 负采样中的梯度计算

Negative Sampling也是采用了二元逻辑回归来求解模型参数,通过负采样得到了neg个负例 ( c o n t e x t ( w ) , w i ) i = 1 , 2 , . . n e g (context(w),w_i)i=1,2,..neg (context(w),wi)i=1,2,..neg为了统一描述将正例定义为 w 0 w_0 w0

在逻辑回归中,正例应该期望满足: P ( c o n t e x t ( w 0 ) , w i ) = σ ( x w 0 T θ w i ) , y i = 1 , i = 0 P(context(w_0), w_i) = \sigma(x_{w_0}^T\theta_{w_i}) ,y_i=1, i=0 P(context(w0),wi)=σ(xw0Tθwi),yi=1,i=0

负例期望满足: P ( c o n t e x t ( w 0 ) , w i ) = 1 − σ ( x w 0 T θ w i ) , y i = 0 , i = 1 , 2 , . . n e g P(context(w_0), w_i) =1- \sigma(x_{w_0}^T\theta_{w_i}), y_i = 0, i=1,2,..neg P(context(w0),wi)=1σ(xw0Tθwi),yi=0,i=1,2,..neg

期望可以最大化: ∏ i = 0 n e g P ( c o n t e x t ( w 0 ) , w i ) = σ ( x w 0 T θ w 0 ) ∏ i = 1 n e g ( 1 − σ ( x w 0 T θ w i ) ) \prod\limits_{i=0}\limits^{neg}P(context(w_0), w_i) = \sigma(x_{w_0}^T\theta_{w_0})\prod\limits_{i=1}\limits^{neg}(1- \sigma(x_{w_0}^T\theta_{w_i})) i=0negP(context(w0),wi)=σ(xw0Tθw0)i=1neg(1σ(xw0Tθwi))

似然函数为: ∏ i = 0 n e g σ ( x w 0 T θ w i ) y i ( 1 − σ ( x w 0 T θ w i ) ) 1 − y i \prod\limits_{i=0}\limits^{neg} \sigma(x_{w_0}^T\theta_{w_i})^{y_i}(1- \sigma(x_{w_0}^T\theta_{w_i}))^{1-y_i} i=0negσ(xw0Tθwi)yi(1σ(xw0Tθwi))1yi

对数似然: L = ∑ i = 0 n e g y i l o g ( σ ( x w 0 T θ w i ) ) + ( 1 − y i ) l o g ( 1 − σ ( x w 0 T θ w i ) ) L = \sum\limits_{i=0}^{neg}y_i log(\sigma(x_{w_0}^T\theta_{w_i})) + (1-y_i) log(1- \sigma(x_{w_0}^T\theta_{w_i})) L=i=0negyilog(σ(xw0Tθwi))+(1yi)log(1σ(xw0Tθwi))

梯度上升法来更新我们的 θ w i \theta_{w_i} θwi x w i , i = 0 , 1 , . . n e g x_{wi},i=0,1,..neg xwi,i=0,1,..neg,分别求解梯度:
∂ L ∂ θ w i = y i ( 1 − σ ( x w 0 T θ w i ) ) x w 0 − ( 1 − y i ) σ ( x w 0 T θ w i ) x w 0 = ( y i − σ ( x w 0 T θ w i ) ) x w 0 ∂ L ∂ x w 0 = ∑ i = 0 n e g ( y i − σ ( x w 0 T θ w i ) ) θ w i \begin{align} \frac{\partial L}{\partial \theta_{w_i} } &= y_i(1- \sigma(x_{w_0}^T\theta_{w_i}))x_{w_0}-(1-y_i)\sigma(x_{w_0}^T\theta_{w_i})x_{w_0} \\[2ex] & = (y_i -\sigma(x_{w_0}^T\theta_{w_i})) x_{w_0} \\[4ex] \frac{\partial L}{\partial x_{w_0} } &= \sum\limits_{i=0}^{neg}(y_i -\sigma(x_{w_0}^T\theta_{w_i}))\theta_{w_i} \end{align} θwiLxw0L=yi(1σ(xw0Tθwi))xw0(1yi)σ(xw0Tθwi)xw0=(yiσ(xw0Tθwi))xw0=i=0neg(yiσ(xw0Tθwi))θwi

6.5 负采样的方法

如果词汇表的大小为 V V V,那么将一段长度为1的线段分成 V V V份,每份对应词汇表中的一个词。当然每个词对应的线段长度是不一样的,高频词对应的线段长,低频词对应的线段短。每个词 w w w的线段长度由下式决定:
l e n ( w ) = c o u n t ( w ) ∑ u ∈ v o c a b c o u n t ( u ) len(w) = \frac{count(w)}{\sum\limits_{u \in vocab} count(u)} len(w)=uvocabcount(u)count(w)
在word2vec中,分子和分母都取了 3 / 4 3/4 3/4 次幂如下:
l e n ( w ) = c o u n t ( w ) 3 / 4 ∑ u ∈ v o c a b c o u n t ( u ) 3 / 4 len(w) = \frac{count(w)^{3/4}}{\sum\limits_{u \in vocab} count(u)^{3/4}} len(w)=uvocabcount(u)3/4count(w)3/4
在采样前,将这段长度为1的线段划分成 M M M等份,这里 M > > V M>>V M>>V,这样可以保证每个词对应的线段都会划分成对应的小块。而 M M M份中的每一份都会落在某一个词对应的线段上。在采样的时候,我们只需要从 M M M个位置中采样出 n e g neg neg个位置就行,此时采样到的每一个位置对应到的线段所属的词就是我们的负例词。

在这里插入图片描述

在word2vec中, M M M取值默认为 1 0 8 10^8 108

总的来说:非等距切分+等距切分

6.5负采样的技巧点

例如: 选定句子 “The quick brown fox jumps over lazy dog” ,设定窗口大小为2 ( w i n d o w _ s i z e = 2 window\_size=2 window_size=2) 选输入词前后各两个词和输入词进行组合。下图中,蓝色代表input word,方框内代表位于窗口内的单词。
在这里插入图片描述

对高频词进行抽样

但是对于“the”这种常用高频单词,这样的处理方式会存在下面两个问题:

  • 当我们得到成对的单词训练样本时,(“fox”, “the”) 这样的训练样本并不会给我们提供关于“fox”更多的语义信息,因为“the”在每个单词的上下文中几乎都会出现。
  • 由于在文本中“the”这样的常用词出现概率很大,因此我们将会有大量的(”the“,…)这样的训练样本,而这些样本数量远远超过了我们学习“the”这个词向量所需的训练样本数。

Word2Vec通过“抽样”模式来解决这种高频词问题。它的基本思想如下:对于在训练原始文本中遇到的每一个单词,它们都有一定概率从文本中被删掉,而这个被删除的概率与单词的频率有关。

如果设置窗口大小 s p a n = 10 span=10 span=10,并且从文本中删除所有的“the”,那么会有下面的结果:

  1. 由于删除了文本中所有的“the”,那么在训练样本中,“the”这个词永远不会出现在上下文窗口中。
  2. 当“the”作为input word时,训练样本数至少会减少10个。

Q:如何选择抽样率呢?

word2vec的C语言代码实现了一个计算在词汇表中保留某个词概率的公式。
P ( w i ) = ( Z ( w i ) 0.001 + 1 ) × 0.001 Z ( w i ) P(w_i)=(\sqrt{\frac{Z(w_i)}{0.001}}+1)×\frac{0.001}{Z(w_i)} P(wi)=(0.001Z(wi) +1)×Z(wi)0.001
P ( w i ) P(w_i) P(wi)表示某个单词被保留的概率。 w i w_i wi是一个单词, Z ( w i ) Z_(w_i) Z(wi) w i w_i wi这个单词在所有语料中出现的频次。

举个栗子:如果单词“peanut”在10亿规模大小的语料库中出现了1000次,则有 Z ( " p e a n u t " ) = 1000 / 1000000000 = 1 e − 6 Z("peanut")=1000/1000000000=1e-6 Z("peanut")=1000/1000000000=1e6

在代码中还有一个参数叫“sample”,这个参数代表一个阈值,默认值为0.001**(在gensim包中的Word2Vec类说明中,这个参数默认为0.001,文档中对这个参数的解释为“ threshold** for configuring which higher-frequency words are randomly downsampled”)。这个值越小意味着这个单词被保留下来的概率越小(即有越大的概率被我们删除)。
在这里插入图片描述

6.6 负采样的思想

负采样每遍历到一个目标词,为了使得目标词的概率 P ( w t ∣ c t ) P(w_t|c_t) P(wtct) 最大,根据softmax函数的概率公式,也就是让分子中的 e ′ ( w t ) T x e′(w_t)^Tx e(wt)Tx 最大,而分母中其他非目标词的 e ′ ( w i ) T x e′(w_i)^Tx e(wi)Tx 最小,普通softmax的计算量太大就是因为它把词典中所有其他非目标词都当做负例了,而负采样的思想特别简单,就是每次按照一定概率随机采样一些词当做负例,从而就只需要计算这些负采样出来的负例了,那么概率公式便相应变为:
P ( w t ∣ c t ) = e x p ( e ´ ( w t ) T ) x ∑ i = 1 K e x p ( e ´ ( w i ) T ) x , x = ∑ i ∈ c e ( w i ) P(w_t|c_t)=\frac{exp(e´(w_t)^T)x}{\sum\limits_{i=1}\limits^Kexp(e´(w_i)^T)x}, \quad x=\sum\limits_{i \in c}e(w_i) P(wtct)=i=1Kexp(e´(wi)T)xexp(e´(wt)T)x,x=ice(wi)
仔细和普通softmax进行比较便会发现,将原来的|V|分类问题变成了K分类问题,这便把词典大小对时间复杂度的影响变成了一个常数项,而改动又非常的微小,不可谓不巧妙。

7.word2vec的好处

不同于one_hot这种暴力映射,无法衡量字词的语义空间距离。Word2vec采用的是低维稠密矩阵去表征字词的语义关系。

  • 降低维度,解决稀疏性
  • 相似性(衡量词与词之间的距离远近关系)
  • 泛化能力更强

对于泛化能力的理解:假设现有四个特征值woman girl man boy,经过onet-hot编码之后得到

[1,0,0,0]–>woman [0,1,0,0]–>girl 每个特征之间是独立的,放进网络里训练彼此之间是没有任何关系的。如果将特征进行embedding操作为2维度:[性别,年龄]==> 女 40(通过性别和年龄能学习出woman)—>woman 可以学习出泛化性。

8.总结

  • 统计语言模型就是用来计算一个句子的概率的概率模型(N-gram方式计算)
  • 神经语言模=Embedding层+前馈神经网络
  • word2vec主要有两种实现方式
    • Skip-gram:输入一个词 x x x,预测它的上下文的词
    • CBOW:通过上下文的词,去预测当前的词
  • word2vec本质上学习词与词之间的共现关系
  • hierarchical softmax: 本质是把 N 分类问题变成 log(N)次二分类
  • negative sampling: 本质是预测总体类别的一个子集
  • Word2vec学习的参数是两个矩阵(每一个行是一个词向量)
  • embedding矩阵有两个矩阵,可以取第一个或者把二者相加做平均做真正的词向量w

本文仅仅作为个人学习记录所用,不作为商业用途,谢谢理解。

参考:

1.https://zhuanlan.zhihu.com/p/88874759

2.https://www.cnblogs.com/peghoty/p/3857839.html

3.https://www.cnblogs.com/pinard/p/7160330.html

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

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

相关文章

GDPU C语言 天码行空7

1. 数组最大值交换 ⭐ 1e9&#xff1a;10的9次方 #include<stdio.h>int main() {int n, i,idx 0;//idx 记录第一个出现的最大值下标scanf("%d", &n);double a[30];double max -1e9;// 1e9 表示10的9次方&#xff0c;十亿&#xff0c;int 的最大范围级别…

使用RT-Thread Studio搭配STM32CubeMX新建RT-Thread项目

STM32CubeMX下载 RT-Thread Studio下载 安装好RT-Thread Studio后&#xff0c;先打开RT-Thread SDK管理器确认有没有自己MCU需要的SDK包&#xff0c;直接安装好之后里面是有STM32F1系列的SDK包&#xff0c;其他的需要自己安装。 之后点击文件→新建→RT-Thread项目&#xff0…

C++ 实现 matlab 的 zp2tf 函数

文章目录1. matlab 的 zp2tf 函数的作用2. matlab 的 zp2tf 函数的使用方法3. C实现3.1 complex.h 文件3.2 zp2tf.h 文件4. 测试结果4.1 测试文件4.2 测试结果1. matlab 的 zp2tf 函数的作用 作用是将极点形式的 H(s) 函数的分母展开 2. matlab 的 zp2tf 函数的使用方法 [z,…

ICASSP2023 | 基于多任务学习的保留背景音的语音转换

在影视、有声书内容中&#xff0c;背景音是一种表现丰富的艺术形式。语音转换&#xff08;Voice Conversion&#xff09;如能将源说话人语音转换成目标说话人语音的同时&#xff0c;保留源语音中的背景音&#xff0c;将会提供更沉浸的语音转换体验。之前的语音转换研究主要关注…

低代码平台很赞,用2个小时,搭出1套应用

最近低代码很火&#xff0c;到处都是低代码的尝试贴&#xff0c;笔者今天也决定深入体验一下&#xff0c;感受它的便捷程度。 在案例开始之前&#xff0c;我们先来聊聊概念。 一、低代码 低代码实质上并不是一个新颖的话题&#xff0c;也不是最近才有的技术突破和创新&#xf…

Python--异常处理机制

Python异常处理机制 1、什么是异常处理&#xff1a; 程序运行时常会碰到一些错误&#xff0c;例如除数为 0、年龄为负数、数组下标越界等&#xff0c;这些错误如果不能发现并加以处理&#xff0c;很可能会导致程序崩溃。 可以简单的理解异常处理机制&#xff0c;就是在程序运…

Nginx生产环境配置、elasticsearch生产环境配置、rocketmq生产环境配置 (史上最全)

Nginx实现10万并发 在优化内核时&#xff0c;可以做的事情很多&#xff0c;不过&#xff0c;我们通常会根据业务特点来进行调整&#xff0c;当Nginx作为静态web内容服务器、反向代理或者提供压缩服务器的服务器时&#xff0c;期内核参数的调整都是不同的&#xff0c; 概述&am…

计算机组成原理——第五章中央处理器

半生风雨半生伤&#xff0c;半醉半醒半心凉 文章目录前言5.1 CPU的功能和基本结构5.2 指令周期的数据流5.3.1 单总线结构5.3.2 专用通路结构前言 之前我们就说过CPU主要包括两个部分&#xff0c;运算器和控制器&#xff0c;运算器主要是实现算数运算.逻辑运算&#xff0c; 运算…

React 搜索时遇到的坑

一、业务场景&#xff1a; 最近在优化React的天枢项目里面&#xff0c;搜索时遇到了一些问题。为了大家后面遇到和我一样的问题&#xff0c;给大家分享一下 二、问题描述&#xff1a; 1.点击搜索按钮&#xff0c;报以下错误。 TypeError: Converting circular structure to J…

全景丨0基础学习VR全景制作,平台篇:如何从素材库发布VR漫游

大家好欢迎观看蛙色平台使用教程 大家可以将创建作品理解成搭建房子&#xff0c;建房子需要基础的砖块、木头、钉子等原材料&#xff0c;房子成品是多种原材料的有机组合&#xff0c;而蛙色VR平台在创建作品前&#xff0c;也需要先准备对应的基础原材料。当前蛙色VR素材上传类型…

C++实现前缀树

文章目录1. 什么是前缀树2. 前缀树的实现2.1 前缀树的基本结构2.2 插入2.3 word出现了几次2.3 word作为前缀出现几次2.4 删除1. 什么是前缀树 假设这里有一个字符串数组&#xff0c;和一个树的根结点&#xff1a; 这个结点的pass意思是&#xff1a;有几个字符通过了这个结点。…

Golang中是否可以无限开辟协程以及如何控制协程的数量?

文章目录1. Golang中是否可以无限开辟协程&#xff1f;2. 不控制goroutine数量引发的问题3. 如何控制goroutine的数量&#xff1f;⭐️3.1 只用有buffer的channel3.2 channel与sync同步组合方式3.3 利用无缓冲channel与任务发送/执行分离方式1. Golang中是否可以无限开辟协程&a…

腾讯轻联中多维表记录id是什么?如何获取记录id?

在腾讯文档智能表、金山轻维表、维格表需要去【更新表格数据】的时候&#xff0c;经常会需要输入记录id&#xff08;英文record id&#xff09;&#xff0c;很多用户也会有疑问&#xff0c;什么是记录id&#xff0c;如何获取记录id等。 金山、维格表、腾讯文档的记录ID是什么&a…

字节跳动CVPR 2023论文精选来啦(内含一批图像生成新研究)

计算机视觉领域三大顶会之一的 CVPR 今年已经开奖啦。 今年的 CVPR 将于六月在加拿大温哥华举办&#xff0c;和往年一样&#xff0c;字节跳动技术团队的同学们收获了不少中选论文&#xff0c;覆盖文本生成图像、语义分割、目标检测、自监督学习等多个领域&#xff0c;其中不少…

[ROC-RK3568-PC] [Firefly-Android] 10min带你了解Camera的使用

&#x1f347; 博主主页&#xff1a; 【Systemcall小酒屋】&#x1f347; 博主追寻&#xff1a;热衷于用简单的案例讲述复杂的技术&#xff0c;“假传万卷书&#xff0c;真传一案例”&#xff0c;这是林群院士说过的一句话&#xff0c;另外“成就是最好的老师”&#xff0c;技术…

SVN利用 AS 进行代码对比的方法

第 1 种&#xff1a;如果我们是从 SVN 检出的项目&#xff0c;并且想比较本地代码与从 SVN 检出时的代码相比都有那些区别&#xff0c;可以按如下步骤操作 如上图所示&#xff0c;在代码编辑区&#xff0c;右键唤出功能菜单&#xff0c;然后选择Subversion&#xff0c;进而会展…

沉浸式翻译 – 支持 PDF、EPUB、网页,可同时显示原文与译文的双语翻译工具

使用的理由 自从谷歌翻译不再对大陆用户提供服务后。内心是一阵酸痛的&#xff0c;毕竟我认识单词单词不认识我啊&#xff0c;这简直是天书一般的存在。 期间网络中的很多大神也是推荐了不少方法让我再次拥抱谷歌翻译&#xff0c;比如教我修改 host 文件什么的&#xff0c;但这…

谁能真正替代你?AI辅助编码工具深度对比(chatGPT/Copilot/Cursor/New Bing)

写在开头 这几个月AI相关新闻的火爆程度大家都已经看见了&#xff0c;作为一个被裹挟在AI时代浪潮中的程序员&#xff0c;在这几个月里我也是异常兴奋和焦虑。甚至都兴奋的不想拖更了。不仅仅兴奋于AI对于我们生产力的全面提升&#xff0c;也焦虑于Copilot等AI辅助编码工具&am…

VUE3 学习笔记(八-1)中 EasyUI 组件的使用方法

目录 一、首先看官方 Accordion 文档说明 二、如何使用 Props 属性 三、如何使用 Methods&#xff08;方法&#xff09; 四、如何使用Methods&#xff08;方法&#xff09; 1. 通过 ref 给Vue3中的标签添加引用 2. 在script setup lang"ts"中定义变量引用 3. 增…

全面剖析OpenAI发布的GPT-4比其他GPT模型强在哪里

最强的文本生成模型GPT-4一、什么是GPT-4二、GPT-4的能力三、和其他GPT模型比较3.1、增加了图像模态的输入3.2、可操纵性更强3.3、复杂任务处理能力大幅提升3.4、幻觉、安全等局限性的改善3.6、风险和缓解措施改善更多安全特性3.7、可预测的扩展四、与之前 GPT 系列模型比较五、…