论文阅读 - Joint Beat and Downbeat Tracking with Recurrent Neural Networks

文章目录

  • 1 概述
  • 2 信号预处理
  • 3 分类神经网络
  • 4 动态贝叶斯网络(HMM)
    • 4.1 原始的bar pointer model
    • 4.2 原始的bar pointer model的缺点
    • 4.3 改进后的模型
  • 5 预测
  • 参考资料

1 概述

最近在做音乐卡点相关的项目,需要对音乐的基本特征进行理解,比如beats和downbeats就是最基本的特征。madmom是我找到的一个对beats和downbeats的检测都有实现的第三方库,于是就认真学习了一下,把其中用到的方法和自己的理解记录下来。

madmom中的beats和downbeats检测就是复现了Joint Beat and Downbeat Tracking with Recurrent Neural Networks这篇论文,其核心思想就是HMM,如果对HMM没有扎实的理解的话,建议先看我写的另一篇搞懂HMM。本文不会对HMM的基本概念做详细的说明。

在说论文之前,我先来说明一些音乐上的专用术语,对齐一些概念,便于后文的叙述。有些术语在本文中可能不会再次出现,但有助于理解音乐,就一并写上了。

名词名词解释
拍子(beat)在音乐中,时间被分成均等的基本单位,每个单位叫做一个“拍子”或称一拍。
强拍(downbeat)音乐中的强拍。是beats的子集。一般是每个小节的起始beat
小节(measure/bar)音乐是由强拍和弱拍交替进行的,是按照一定的规律构成最小的节拍组织一小节,然后以此为基础循环往复。一个小节一般有2拍,3拍,4拍或者6拍等等
节拍(meter)beats per measure,一首歌的节拍,一般表示为1/4拍或者2/4拍或者3/8拍等等。比如3/4拍表示4分音符为1拍,每小节有3拍,节拍强度为强、弱、弱。
全局节奏(tempo)一般用bpm(beats per minute)来做单位,表示每分钟有多少个beats,用来衡量音乐的速度,一首音乐可以由不同的tempo演奏。
局部节奏(tempi)每两个相邻的beats之间可以是有不同的1/16音符,或是1/8音符,或是1/4等组成的,这个就是局部节奏
onset一个音符被乐器或者人发出声音的那个时刻点。
峰值(peak)onset包络图的峰值,具体可见peak_pick。

再说回这篇论文。这篇论文概括地说就是把信号切成多个frames,每个frame会在RNN网络之后对应一个概率输出,表示该frame是beat还是downbeat还是都不是。HMM会在发射概率的计算中借助于这个RNN结果,把frame在measure当中的相对位置和tempi作为隐变量,得到最佳的隐变量路径,并把该路径解码为beats和downbeats。

下面会分步骤说明一下每个步骤,着重是HMM和预测部分。这两部分理解起来有点绕。

2 信号预处理

这部分其实就是一个类似于MFCC提取语音信号特征的过程,作为RNN的输入,这里简单说下。先是用汉宁窗对信号做了有交叠的分割,分成了100fps(frame per second),并基于此做了短时傅里叶变换(STFT)。丢弃了相位特征,只保留幅值特征,因为人耳是听不出相位的。为了保证时域和频域的精度,做STFT时,分别用了1024,2048和4096三种窗口大小。把频段限制在了[30, 17000]Hz的的范围,并给每个八度分了3,6和12个频段,分别对应于1024,2048和4096三种窗口大小。同时也对频谱进行了一阶差分,也作为特征concat进去。最终,输入网络的特征维度为314。

3 分类神经网络

这部分用了由LSTM搭建而成的网络,目的是给每个frame进行分类,输出两个概率值,(是beat的概率,是downbeat的概率),取较大的作为该frame的分类。为了避免混淆,downbeat不属于beat。

同时,也设置了θ=0.05\theta=0.05θ=0.05的阈值,只有大于该阈值,才会被判为是beat或者downbeat。这是为了减小音乐头尾有空白的干扰。

既然每个frame是beat还是downbeat的概率都知道了,那我直接取每个frame最大概率的类别,两个概率都比较小的就认为既不是beat也不是downbeat,这事不就成了?

理想很美好,现实并非如此,不要被论文中的图片给误导了,来看下模型的实际输出是长啥样的。
activation output

图3-1 RNN网络输出示意图

模型的输出如上图3-1所示,这个是一条30s左右的实际样例。上半个图是每个frame为beat的概率,下半个图是每个frame为downbeat的概率。只看downbeat这部分的话,不难看出概率比较高的frame之间的间距有长有短,而在一个小节(bar)当中,强拍(downbeat)应该只会出现一次,次强拍的出现会对其产生干扰。RNN不知道强拍的出现是有周期性的,所以需要HMM来判断究竟哪些位置是强拍,哪些位置是弱拍,哪些位置什么都不是。

从另一个角度来思考,RNN这里并不知道音乐的meter是几几拍,没有这个信息,要RNN直接判断强拍和弱拍的难度是很大的。下一节的HMM的作用就是根据RNN的结果,去选一组最优的beats和downbeats。

4 动态贝叶斯网络(HMM)

这是重点部分,我们来详细讲一下。Joint Beat and Downbeat Tracking with Recurrent Neural Networks对这部分的说明很不清晰,我们直接看它沿用的An Efficient State-Space Model for Joint Tempo and Meter Tracking中的说明即可。

4.1 原始的bar pointer model

早在2006年的时候,Bayesian Modelling of Temporal Structure in Musical Audio就提出过用HMM解决beat tracking问题的方法。现在的方法,就是在它的基础上优化的,我们先来看看最早版本的HMM是怎么设计的。

我们令第kkk个frame的隐变量为xk=[Φk,Φ˙k]\bold{x}_k=[\Phi_k, \dot{\Phi}_k]xk=[Φk,Φ˙k]Φk∈{1,2,...,M}\Phi_k \in \{1,2,...,M\}Φk{1,2,...,M}表示第kkk个frame在某个小节(bar)中的相对位置,1表示起始位置,MMM表示结束位置,这个bar被分成了M个相对位置,一般是均分的。Φ˙k∈{Φ˙min,Φ˙min+1,...,Φ˙max}\dot{\Phi}_k \in \{\dot{\Phi}_{min}, \dot{\Phi}_{min} + 1, ..., \dot{\Phi}_{max}\}Φ˙k{Φ˙min,Φ˙min+1,...,Φ˙max}表示第kkk个frame的tempi,Φ˙min\dot{\Phi}_{min}Φ˙minΦ˙max\dot{\Phi}_{max}Φ˙max是人为设置的上下界。说的通俗一点,把Φk\Phi_kΦk看成位移的话,Φ˙k\dot{\Phi}_kΦ˙k就是速度,k+1k+1k+1个frame的位置Φk+1\Phi_{k + 1}Φk+1就是Φk+Φ˙k\Phi_k + \dot{\Phi}_kΦk+Φ˙k。说的音乐一点,就是Φ˙k\dot{\Phi}_kΦ˙k表示了第kkk个frame是一个几分之几的音符,比如1/8音符,如果知道这首歌是4/4拍的话,第kkk个frame就走了(1/8)/(4∗1/4)=1/8(1/8) / (4*1/4) = 1/8(1/8)/(41/4)=1/8个小节(bar),这里使用离散的MMM个数值来表示了。

观测变量就是我们的frames的特征序列,记为{y1,y2,...,yK}\{\bold{y}_1, \bold{y}_2, ..., \bold{y}_K\}{y1,y2,...,yK}。我们想要找到一串隐变量的序列x1:K∗={x1∗,x2∗,...,xK∗}\bold{x}_{1:K}^*=\{\bold{x}_1^*, \bold{x}_2^*, ..., \bold{x}_K^*\}x1:K={x1,x2,...,xK}使得

x1:K∗=argmax⁡x1:KP(x1:K∣y1:K)(4-1)\bold{x}_{1:K}^* = arg\max_{\bold{x}_{1:K}} P(\bold{x}_{1:K} | \bold{y}_{1:K}) \tag{4-1} x1:K=argx1:KmaxP(x1:Ky1:K)(4-1)

(4−1)(4-1)(41)可以用viterbi算法来解,不清楚的可以参看我的搞懂HMM。求解式(4−1)(4-1)(41)需要知道三个模型,一个是初始概率模型P(x1)P(\bold{x}_1)P(x1),第二个是状态转移模型P(xk∣xk−1)P(\bold{x}_k|\bold{x}_{k-1})P(xkxk1),第三个是发射概率P(yk∣xk)P(\bold{y}_k|\bold{x}_k)P(ykxk)

(1)初始概率
初始概率P(x1)P(\bold{x}_1)P(x1),作者用了均匀分布初始化,后面用数据学就行,没啥说的。

(2)转移概率
转移概率是个比较关键的概率,我们来仔细看下

P(xk∣xk−1)=P(Φk,Φ˙k∣Φk−1,Φ˙k−1)=P(Φk∣Φ˙k,Φk−1,Φ˙k−1)P(Φ˙k∣Φk−1,Φ˙k−1)\begin{aligned} P(\bold{x}_k | \bold{x}_{k-1}) &= P(\Phi_k, \dot{\Phi}_k | \Phi_{k-1}, \dot{\Phi}_{k-1}) \\ &=P(\Phi_k | \dot{\Phi}_k, \Phi_{k-1}, \dot{\Phi}_{k-1})P(\dot{\Phi}_k | \Phi_{k-1}, \dot{\Phi}_{k-1}) \end{aligned} P(xkxk1)=P(Φk,Φ˙kΦk1,Φ˙k1)=P(ΦkΦ˙k,Φk1,Φ˙k1)P(Φ˙kΦk1,Φ˙k1)

我们把Φk\Phi_kΦk理解成位移,Φ˙k\dot{\Phi}_kΦ˙k理解成速度,这应该也是为啥这两个变量的符号只差了一个一阶导的符号的原因。

Φk\Phi_kΦkkkk时刻的位置,它由上一刻的位置Φk−1\Phi_{k-1}Φk1和上一刻的速度Φ˙k−1\dot{\Phi}_{k-1}Φ˙k1决定,与kkk时刻的速度无关,故有

P(Φk∣Φ˙k,Φk−1,Φ˙k−1)=P(Φk∣Φk−1,Φ˙k−1)P(\Phi_k | \dot{\Phi}_k, \Phi_{k-1}, \dot{\Phi}_{k-1}) = P(\Phi_k | \Phi_{k-1}, \dot{\Phi}_{k-1}) P(ΦkΦ˙k,Φk1,Φ˙k1)=P(ΦkΦk1,Φ˙k1)

Φ˙k\dot{\Phi}_kΦ˙kkkk时刻的速度,它只与k−1k-1k1时刻的速度有关,速度不太会突变,与位置无关,故有

P(Φ˙k∣Φk−1,Φ˙k−1)=P(Φ˙k∣Φ˙k−1)P(\dot{\Phi}_k | \Phi_{k-1}, \dot{\Phi}_{k-1}) = P(\dot{\Phi}_k | \dot{\Phi}_{k-1}) P(Φ˙kΦk1,Φ˙k1)=P(Φ˙kΦ˙k1)

于是有

P(xk∣xk−1)=P(Φk∣Φk−1,Φ˙k−1)P(Φ˙k∣Φ˙k−1)(4-2)P(\bold{x}_k | \bold{x}_{k-1}) = P(\Phi_k | \Phi_{k-1}, \dot{\Phi}_{k-1})P(\dot{\Phi}_k | \dot{\Phi}_{k-1}) \tag{4-2} P(xkxk1)=P(ΦkΦk1,Φ˙k1)P(Φ˙kΦ˙k1)(4-2)

P(Φk∣Φk−1,Φ˙k−1)P(\Phi_k | \Phi_{k-1}, \dot{\Phi}_{k-1})P(ΦkΦk1,Φ˙k1)就是一个位移的计算,可以定义为

P(Φk∣Φk−1,Φ˙k−1)={1,if(Φk−1+Φ˙k−1−1)%M+10,otherwise(4-3)P(\Phi_k | \Phi_{k-1}, \dot{\Phi}_{k-1}) = \begin{cases} 1, &if \ (\Phi_{k-1} + \dot{\Phi}_{k-1} - 1) \% \ M + 1\\ 0, &otherwise \end{cases} \tag{4-3} P(ΦkΦk1,Φ˙k1)={1,0,if (Φk1+Φ˙k11)% M+1otherwise(4-3)

也就是Φk=(Φk−1+Φ˙k−1−1)%M+1\Phi_k = (\Phi_{k-1} + \dot{\Phi}_{k-1} - 1) \% \ M + 1Φk=(Φk1+Φ˙k11)% M+1的意思。这里取余是为了在下一个bar中,位置重新计数。为啥要先减1再取余再加1?我猜测是为了避免产生Φk=0\Phi_k=0Φk=0的情况,使得Φk\Phi_kΦk的取值在{1,2,...,M}\{1,2,...,M\}{1,2,...,M},只是为了符号的统一。

P(Φ˙k∣Φ˙k−1)P(\dot{\Phi}_k | \dot{\Phi}_{k-1})P(Φ˙kΦ˙k1)是一个速度变化的概率,定义为

P(Φ˙k∣Φ˙k−1)={1−p,Φ˙k=Φ˙k−1p2,Φ˙k=Φ˙k−1+1p2,Φ˙k=Φ˙k−1−1(4-4)P(\dot{\Phi}_k | \dot{\Phi}_{k-1}) = \begin{cases} 1 - p, & \dot{\Phi}_k=\dot{\Phi}_{k-1} \\ \frac{p}{2}, & \dot{\Phi}_k=\dot{\Phi}_{k-1} + 1 \\ \frac{p}{2}, & \dot{\Phi}_k=\dot{\Phi}_{k-1} - 1 \end{cases} \tag{4-4} P(Φ˙kΦ˙k1)=1p,2p,2p,Φ˙k=Φ˙k1Φ˙k=Φ˙k1+1Φ˙k=Φ˙k11(4-4)

ppp是速度发生变化的一个概率,我们人为限制了速度只能在距离为1的速度上转移或者保持不变。在边界Φ˙min\dot{\Phi}_{min}Φ˙minΦ˙max\dot{\Phi}_{max}Φ˙max上,略有不同,保持速度不超界即可。ppp是需要学习得到的。

原始状态转移示意图

图4-1 原始状态转移示意图

原始状态转移示意图如图4-1所示,可以很明显滴看出位置和速度的关系。

(3)发射概率
这里是结合RNN的结果的地方。我们假设第kkk个frame为beat的概率是bkb_kbk,为downbeat的概率是dkd_kdk,既不是beat也不是downbeat的概率为nkn_knk。那么发射概率就为

P(yk∣xk)={bk,sk∈Bdk,bk∈Dnkλ0−1,otherwise(4-5)P(\bold{y}_k | \bold{x}_k) = \begin{cases} b_k, &s_k \in B \\ d_k, &b_k \in D \\ \frac{n_k}{\lambda_0 - 1}, & otherwise \end{cases} \tag{4-5} P(ykxk)=bk,dk,λ01nk,skBbkDotherwise(4-5)

BBB表示xkx_kxk被认为是beat的集合,DDD表示xkx_kxk被认为是downbeat的集合。怎么样的xkx_kxk会被认为是beat或是downbeat呢?这点论文中没有细说,我看了A Multi-model Approach to Beat Tracking Considering Heterogeneous Music Styles中的做法,大概猜测了一下,是将位置在小节等分点附近的states作为beat或者downbeat,每个小节的第一个等分点附近为downbeat(每小节的第一拍为强拍),其他的等分点附近为beat。这个附近有多近,其实是个可以人为设置的范围。按几等份算,则是一个用户需要提前输入的参数,比如一首歌是3/4拍的,那每个小节就有3拍,就三等分,又比如一首歌是6/8拍的,那每个小节就有6拍,就六等份。如果不知道是几几拍的音乐的话,就一个个算过去,取概率最大的,这个在下一节会讲。

λ0\lambda_0λ0是个超参数,论文中取λ0=16\lambda_0=16λ0=16得到了最好的实验结果。BBBDDD的范围和λ0\lambda_0λ0相关。

4.2 原始的bar pointer model的缺点

(1)位置(时间)分辨率
原文中说是时间分辨率,我这里直接说成位置分辨率了,这样比较方便理解。作者认为不同的速度下,需要的位置分辨率是不同的。速度快的,每次都大步大步跨,需要的位置分辨率很低;速度慢的,每次跨的步幅小,需要的位置分辨率就高了。一句话说,就是不同的速度条件下,要不同的位置分辨率。

(2)速度分辨率
原文中的tempo就是我这里的速度。作者认为人耳对于速度的变化感知,在不同的速度下是不一样。比如在速度为1的时候,速度加个1,变成2,听起来就变化很明显了。但是在速度为10的时候,速度价格1,变成11,听起来都没什么变化。也就是人耳的听觉不是linear的,而是log linear的。

(3)速度的稳定性
使用HMM时,有一个齐次马尔科夫假设,认为Φk\Phi_kΦk只依赖于Φ˙k\dot{\Phi}_kΦ˙k,这可能会导致同一个beat里,速度经过几个frames之后就产生比较大的变化,也就是速度的稳定性无法保证。

4.3 改进后的模型

论文针对4.2中提出的三点对模型进行了改进,改进都是针对状态转移的计算的。改进后的状态转移示意图,如下图4-2所示。
改进后的状态转移示意图

图4-2 改进后的状态转移示意图

(1)位置分辨率的改进
这里说白了就是根据速度来调整一个bar要被分成几份。从图4-2中的横向可以看出,tempo越大的,bar position就被分的越稀疏,反之越密。划分方式我们从具体madmom的实现来看,不看论文里说的,论文里说的有些模糊。

"""
max_bpm:用户输入,表示最大的beats per minute,默认为215
min_bpm:用户输入,表示最小的beats per minute,默认为55
fps:用户输入,frame per secondmin_interval:计算得到,最小的frame per beat
max_interval:计算得到,最大的frame per beat
"""
# convert timing information to construct a beat state space
min_interval = 60. * fps / max_bpm # second per beat * frame per second = frame per beat
max_interval = 60. * fps / min_bpm

上面代码片中的min_interval和max_interval就是由最大的bpm和最小的bpm确定的每个beat被分为多少个frames。一个bar有多少个beats也是用户输入的,所以一个bar的bar positions也就根据速度的不同确定了。

(2)速度分辨率的改进
速度在min_bpm和max_bpm的范围内,按log linear的方式进行了划分。具体的实现可以看这一段https://github.com/CPJKU/madmom/blob/master/madmom/features/beats_hmm.py#L66。应该说实现中,没有速度这个东西,都转变成了位置。不同bpm下有不同的位置点,log linear的对象是位置。

(3)速度稳定性
作者为了保证速度的稳定性,速度只能在每个beat的位置上发生改变,改变时依赖于一个分布,这个分布是在实验中试了几个得到的。

Φk∈B\Phi_k \in BΦkB

P(Φ˙k∣Φ˙k−1)=f(Φ˙k,Φ˙k−1)(4-6)P(\dot{\Phi}_k | \dot{\Phi}_{k-1}) = f(\dot{\Phi}_k, \dot{\Phi}_{k-1}) \tag{4-6} P(Φ˙kΦ˙k1)=f(Φ˙k,Φ˙k1)(4-6)

其中f(Φ˙k,Φ˙k−1)f(\dot{\Phi}_k, \dot{\Phi}_{k-1})f(Φ˙k,Φ˙k1)可以是各种各样的函数,效果比较好的是

f(Φ˙k,Φ˙k−1)=exp(−λ×∣Φ˙kΦ˙k−1−1∣)(4-7)f(\dot{\Phi}_k, \dot{\Phi}_{k-1}) = exp(-\lambda \times |\frac{\dot{\Phi}_k}{\dot{\Phi}_{k-1}} - 1|) \tag{4-7} f(Φ˙k,Φ˙k1)=exp(λ×Φ˙k1Φ˙k1)(4-7)

不难看出,当Φ˙k−1=Φ˙k\dot{\Phi}_{k-1} = \dot{\Phi}_kΦ˙k1=Φ˙k时概率最大。λ∈[1,300]\lambda \in [1, 300]λ[1,300]是一个超参数,不同λ\lambdaλf(Φ˙k,Φ˙k−1)f(\dot{\Phi}_k, \dot{\Phi}_{k-1})f(Φ˙k,Φ˙k1)的结果如下图4-3所示。
f示意图

图4-3 不同参数下f的结果图

Φk∉B\Phi_k \notin BΦk/B
P(Φ˙k∣Φ˙k−1)={1,Φ˙k=Φ˙k−10,otherwise(4-8)P(\dot{\Phi}_k | \dot{\Phi}_{k-1}) = \begin{cases} 1, & \dot{\Phi}_k = \dot{\Phi}_{k-1} \\ 0, & otherwise \end{cases} \tag{4-8} P(Φ˙kΦ˙k1)={1,0,Φ˙k=Φ˙k1otherwise(4-8)

表示速度不变。

5 预测

madmom很清晰地把整个模型分成了两块,DBNDownBeatTrackingProcessor和RNNDownBeatProcessor。RNNDownBeatProcessor就是我们的RNN网络,DBNDownBeatTrackingProcessor是HMM的部分。从宏观上讲,beats和downbeats的位置是由RNN大致确定,然后由HMM根据周期性这个条件去决定最后的位置的。RNN可以理解为是针对局部的理解,HMM是针对全局的决策。

在预测的时候,我们会告诉模型这首歌每个bar的beat有几个,如果不确定的话,就把beats_per_bar=[2,3,4,6]全填上,让模型每个跑一边,然后取概率最大的就行了。

在每个beats_per_bar下,我们算一个最佳的隐变量路径

x1:K∗=argmax⁡x1:K(x1:K∣y1:K)(5-1)\bold{x}_{1:K}^* = arg\max_{x_{1:K}}(\bold{x}_{1:K} | \bold{y}_{1:K}) \tag{5-1} x1:K=argx1:Kmax(x1:Ky1:K)(5-1)

解这个用viterbi算法就可以了。

最终的结果就是

B∗={k:xk∗∈B}(5-2)B^* = \{k : \bold{x}_k^* \in B\} \tag{5-2} B={k:xkB}(5-2)

D∗={k:xk∗∈D}(5-2)D^* = \{k : \bold{x}_k^* \in D\} \tag{5-2} D={k:xkD}(5-2)

确定了B∗B^*BD∗D^*D之后,还会根据RNN的结果,把点修正到附近的概率峰值点上。

验证模型的时候,把误差在70ms以内的点都认为是正确的。madmom的效果还是很不错的。

参考资料

[1] madmom implementation
[2] Joint Beat and Downbeat Tracking with Recurrent Neural Networks
[3] An Efficient State-Space Model for Joint Tempo and Meter Tracking
[4] 百度百科-音乐节拍
[5] Bayesian Modelling of Temporal Structure in Musical Audio
[6] A Multi-model Approach to Beat Tracking Considering Heterogeneous Music Styles

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

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

相关文章

二十一、PHP框架Laravel学习笔记——模型的访问器和修改器

一.访问器 访问器:就是在获取数据列表时,拦截属性并对属性进行修改的过程;比如,我们在输出性别时,在性别左右加上括号,或给邮件转换为大写; //访问器,前固定 get&#…

python将txt转json_Python控制乐高EV3,以及VSCODE环境配置

乐高EV3的可扩展性很强,但如何用pc连接ev3,并用python代码来控制EV3,资料太少了,试着做了一次,记录在这里。需要的硬/软件硬件准备一、乐高EV3二、PC,win10系统三、TF卡(我用的是64G的&#xff…

移动文件读/写指针----lseek

头文件&#xff1a;#include<sys/types.h>、#include<unistd.h> 函数原型&#xff1a;off_t lseek(int fildes,off_t offset,int whence) 参数说明&#xff1a;fildes:文件描述符 offset:偏移量&#xff0c;正数表示正向偏移&#xff0c;负数表示负向偏移。 whence…

Yolo系列知识点梳理(Yolov1-v5)

文章目录1 概述2 Yolo系列模型2.1 基石 - Yolov12.1.1 Yolov1的网络结构2.1.2 Yolov1的feature map2.1.3 Yolov1的训练2.1.4 Yolov1的预测2.1.5 Yolov1小结2.2 Yolo9000 - Yolov22.2.1 Better2.2.1.1 引入了Batch normalization2.2.1.2 高分辨率的分类器2.2.1.3 加入了anchor机…

二十二、PHP框架Laravel学习笔记——集合的使用

一&#xff0e;创建集合 什么是集合&#xff1f;即&#xff1a;它是一种更具读取性和处理能力的数组封装&#xff1b;比如&#xff0c;我们从数据库得到的数据列表&#xff0c;它就是一种集合&#xff1b;数据集合&#xff0c;提供了大量的方法方便我们进行各种操作&#xff1…

二十三、PHP框架Laravel学习笔记——集合的常用方法

一&#xff0e;常用方法 all()方法&#xff0c;转换为属性形式输出&#xff0c;使用 dd 方法看类型&#xff1b; $collection collect([1, 2, 2, 3, 4, 4, 4]); dd($collection->all()); PS&#xff1a;$collection->dd()方法可以以 dd()模式输出&#xff0c;还有 du…

mac看图软件哪个好用_细数Mac上那些好用且免费的软件(三)

许多朋友购买了Mac电脑之后发现很多软件都没有&#xff0c;而且苹果商店好多软件都是收费的。那有没有免费的软件也能满足日常的需求呢&#xff1f;macw小编就为大家推荐一些免费且超级好用的软件&#xff0c;赶快来看看有没有你需要的吧&#xff01;细数Mac上那些好用且免费的…

图像表格实线和虚线检测

文章目录1 背景简述2 camelot中的方法2.1 二值化2.2 腐蚀膨胀2.3 轮廓检测2.4 结果展示3 基于霍夫直线检测的方法3.1 霍夫直线检测原理3.2 概率霍夫直线检测3.3 霍夫直线应用参考资料1 背景简述 图像中的表格结构化是一个比较热门的话题&#xff0c;其输入是一张图片&#xff…

二十四、PHP框架Laravel学习笔记——模型的数据集合

一&#xff0e;数据集合 数据集合&#xff0c;就是已经将模型方法 get()获取到的数据再进行处理&#xff1b;比如&#xff1a;map()方法&#xff0c;通过它可以实现类似访问器一样对字段进行处理的效果&#xff1b; $users User::get(); //使用集合方法 map 可以对输出的字…

论文阅读 - AUTOVC: Zero-Shot Voice Style Transfer with Only Autoencoder Loss

文章目录1 概述2 模型架构3 模块解析3.1 获取梅尔频谱3.2 speaker encoder3.3 AutoVC3.4 Vocoder4 关键部分参考资料1 概述 voice conversion这个任务的目标是输入两个音频&#xff0c;其输入是两段音频&#xff0c;一段音频称为content_audio&#xff0c;另一段称为speaker_a…

二十五、PHP框架Laravel学习笔记——模型的一对一关联

一&#xff0e;关联概念 关联模型&#xff0c;即&#xff1a;两张或以上的表进行一定规则的绑定关联&#xff1b;比如&#xff1a;一个学生(学生表)对应一张个人信息卡(信息表)&#xff0c;这种就是一对一&#xff1b;再比如&#xff1a;一篇博文(帖子表)对应多个评论(评论表)…

小工具:基于颜色的视频和图片切割

文章目录1 前言2 方案简述3 效果1 前言 最近做一个短视频相关的项目的时候&#xff0c;发现输入的视频有很多是有黑边的&#xff0c;有些可能是白边或者其他颜色的边。这对下游的模型处理有很大的影响。于是就写了一个自动判断填充边的颜色&#xff0c;并根据该颜色自动切割视…

二十六、PHP框架Laravel学习笔记——模型的一对多关联

二&#xff0e;一对多关联 一对多关联&#xff0c;本质上使用方法和一对一关联类似&#xff0c;内部实现略有不同&#xff1b; 创建另一个模型&#xff1a;book.php&#xff0c;我们看下这个表数据&#xff1b; PS&#xff1a;这里 user_id19 有三个&#xff0c;也就是蜡笔小…

论文阅读 - An Image is Worth 16x16 Words: Transformers for Image Recognition at Scale

文章目录1 概述2 方法简述2.1 encoder之前2.2 encoder之后3 实验结果参考资料1 概述 这篇论文是一篇将tranformer引入到图像领域的里程碑式的文章。因为这是第一次在处理图像时&#xff0c;将所有的卷积模块统统抛弃&#xff0c;只使用attention。并且实验证明了只用attention…

python五子棋人机对战_Python:游戏:五子棋之人机对战

原标题&#xff1a;Python&#xff1a;游戏&#xff1a;五子棋之人机对战 开端 画棋盘 首先肯定是要画出棋盘来&#xff0c;用 pygame 画出一个 19 19 或 15 15 的棋盘并不是什么难事&#xff0c;这在之前的文章中已经多次用到&#xff0c;就不赘述了。 画棋子 需要说一下的是…

二十七、PHP框架Laravel学习笔记——模型的多对多关联

二&#xff0e;多对多关联 多对多关联&#xff0c;比前面两种要复杂一些&#xff0c;需要一张中间表&#xff0c;共三张&#xff1b; (1) .users&#xff1a;用户表&#xff1b; (2) .roles&#xff1a;权限表&#xff1b; (3) .role_user&#xff1a;中间表&#xff1a;默…

论文阅读 - Is Space-Time Attention All You Need for Video Understanding?

文章目录1 概述2 模型结构2.1 模型输入2.2 attention模块2.3 分类模块3 模型分析3.1 不同attention方式3.2 不同的输入3.3 不同的模型3.4 不同的预训练数据3.5 不同的数据量3.6 position embedding的影响3.7 长输入时长3.8 不同的transformer3.9 不同的patch size3.10 attentio…

iOS中常见的6种传值方式,UIPageViewController

通过属性传值、方法传值、代理传值、Block传值、单例传值、通知传值6种方式进行不同视图之间的传值。不同方式只需要在AppDelegate中更改下UINavigationController的根控制器即可。使用很简单的实例让你很快理解不同的传值方式。 UIPageViewController(上传者&#xff1a;JoneJ…

websocket 获取ip_Spark+Kafka+WebSocket+eCharts实时分析-完全记录(1)

本系列内容&#xff1a;Kafka环境搭建与测试Python生产者/消费者测试Spark接收Kafka消息处理&#xff0c;然后回传到KafkaFlask引入消费者WebSocket实时显示版本&#xff1a;spark-2.4.3-bin-hadoop2.7.tgzkafka_2.11-2.1.0.tgz------------------------第1小节&#xff1a;Kaf…

二十八、PHP框架Laravel学习笔记——模型的关联查询

二&#xff0e;关联查询 前几篇博文&#xff0c;了解了三种基础的关联模型&#xff0c;并简单的进行查询&#xff1b;本节课&#xff0c;我们详细的了解更多的查询方案&#xff1b; //下面两种查询是一样的&#xff1b; $books User::find(19)->book; $books User::fin…