【数字人】2、MODA | 基于人脸关键点的语音驱动单张图数字人生成(ICCV2023)

news2024/12/22 20:31:23

在这里插入图片描述

文章目录

    • 一、背景
    • 二、方法
      • 2.1 问题描述和数据预处理
      • 2.2 Mapping-Once network with Dual Attentions
      • 2.3 Facial Composer Network
      • 2.4 使用 TPE 来合成人像图片
    • 三、效果
      • 3.1 训练细节
      • 3.2 数据
      • 3.3 测评指标
      • 3.4 结果比较
    • 四、代码
      • 4.1 数据前处理
      • 4.2 训练
      • 4.3 推理

论文:MODA: Mapping-Once Audio-driven Portrait Animation with Dual Attentions

代码:https://tinyurl.com/iccv23-moda

出处:ICCV2023

贡献:

  • 提出了一个 unifided MODA 网络,能够经过一次映射来同时获得确定的唇部动作和不确定的其他面部动作
  • 是一种基于密集关键点的方法,能够同时驱动嘴、眼、头、肩的运动,更自然

和典型方法的对比:

  • Wav2Lip(MM2020) :下半张脸被模糊了(Wav2Lip-GFPGAN 使用两个模型提升输出结果的分辨率)
  • PC-AVS(CVPR2021) :基本都是正脸的图,头部变化不够多样
  • MakeItTalk(SIGGRAPH 2020):由于使用的 2D warping 所以脸部会扭曲。
  • Audio2Head(IJCAI2021):只会产生正脸的图,且由于使用的 2D warping 所以脸部会扭曲
  • SadTalker(CVPR2023):唇部同步性较好,唇部较清晰,头部运动较丰富,牙齿不够清晰,没有考虑除唇部动作和眨眼外的其他面部表情,表情比较固定
  • MODA(ICCV2023):使用一个模型(双分支)来学习确定性的【唇部】、不确定性的【眼部+面部+head+身体】的关键点,理论上能让动作看起来更自然,能保留更多的面部细节。

一、背景

在这里插入图片描述

talking head 是通过一个给定的语音信号来驱动图片,从而合成一个和语音同频的说话的视频

之前的方法 [7,29,52] 都是学习语音和图片帧之间的关系,且一般会忽略 head pose(因为他们认为 head pose 难以和面部动作分开)。

很多 3D 面部重建的方法和基于 GAN 的方法一般会估计一个中间表达(3D face shape、2D landmark、face expression parameters 等)来帮助生成

但是,这些稀疏的表达会丢失很多面部细节,导致过平滑(over-smooth)

NeRF[10,44] 以其高保真结果也受到了很多关注,但是其难以控制

虽然前面提到了这么多方法,但是生成一个真实且表情丰富的 talking vedio 仍然很难,因为人们对合成的 vedio 很敏感,所以要达到可用的效果要达到很高的标准

主要要考虑的问题如下:

  • 正确性:合成的 vedio 要和驱动的 audio 高度一致
  • 高视觉质量:合成的 vedio 要有高分辨率且包含很多细节信息
  • 多样性:说话时主要是嘴唇需要很好的和声音同步,而眨眼和头部动作时不确定的,但也需要和正常人说话的动作类似

为了实现上面三个目标,之前的方法有的将 mouth landmark 和 head pose 分开学习,使用不同的 sub-network [22,50],还有的方法只对 mouth 运动建模,head pose 是从其他 vedio 中拿来的[29,52]。但是这样 lip-sync 和其他运动会缺少关联,导致不确定的结果。

本文中,作者提出了 MODA,mapping-once network with dual attentions,是一个统一的结构来生成不同的表达,简化了步骤。

  • 为了将唇部动作和其他动作结合起来,作者设计了一个 dual-attention module 来分别学习确定性的映射(确定的 mouth movement)和概率采样(the diverse head pose/eye blinking from time-totime)。
  • transformer-based dual attention module:生成准确且多样性的表示特征
  • facial composer network:得到更准确和细节的面部 landmark
  • tenporally guided renderer:合成 vedio

二、方法

在这里插入图片描述

整体框架如图 2 所示,本文方法主要是为了生成高保真 talking head,且具有确定的 lip motion 和其他的 multi-modal motion(head pose、eye blinking、torso movements)

共包含 3 个部分:

  • 首先,给定 driven audio 和 conditioned subjects,MODA 会生成多模态和正确的语义人像部件
  • 然后,面部合成网络会将 ficial component 结合起来,并添加一些细节面部细节
  • 最后,使用具有时间位置嵌入(temporally positional embedding, TPE)的人像渲染器来合成高保真且稳定的视频

2.1 问题描述和数据预处理

给定一个长度为 t 的音频序列 A = { a 0 , a 1 , . . . , a T } A=\{a_0, a_1,...,a_T\} A={a0,a1,...,aT},其音频采样率为 r

本文的 talking portrait (说话人像)方法主要的面部是将这个音频映射到对应的视频 video clip 中, V = { I 0 , I 1 , . . . , I K } V=\{I_0,I_1,...,I_K\} V={I0,I1,...,IK},且 FPS 为 f, K = ⌊ f T / r ⌋ K=\lfloor{fT/r}\rfloor K=fT/r

由于 V 远远大于 A,很多方法提出逐步生成 V,并且引入很多中间表达 R,为了让 V 看起来更自然,那么多 R 的约束就自然很重要了

在之前的 audio-driven face 生成任务中,R 一般都是一种 face information(如 facial landmark、head pose)

为了更好的表达说话人像,本文作者定义 R 是多种不同的人像描述, R = P M , P E , P F , H , P T R=P^M, P_E, P^F, H, P^T R=PM,PE,PF,H,PT

  • 嘴部关键点 P M P^M PM:40 个
  • 眼部关键点 P E P^E PE:60 个,包括眼睛和眉毛的关键点,控制眨眼
  • 面部关键点 P F P^F PF:478 个,是密集的面部 3D 关键点,用于控制面部表情细节
  • 头部动作 H H H:6 个,head rotation ( θ , ϕ , ψ ) (\theta, \phi, \psi) (θ,ϕ,ψ),head transpose ( x , y , z ) (x,y,z) (x,y,z)
  • 躯体动作 Torso points P T P^T PT:18 个,每个肩膀 9 个

所以,整个 talking portrait 可以被写为 A→R→V,作者也是分别设计了对应的网络来实现对应的过程


在这里插入图片描述

数据预处理:关键点提取

  • 使用 Mediapipe 抽取 478 个 3D facial keypoints
  • 使用 WHENet 估计 head pose
  • 使用 BiseNet 分割,然后抽取出肩部关键点

2.2 Mapping-Once network with Dual Attentions

在这里插入图片描述

Mapping-once 结构:如图 3 所示

  • 给定 driven audio A 和 subject condition S,MODA 的作用是使用一次前向过程来将其投影到 R 中(lip movement, eye blinking, head pose, and torso)
  • 第一步:分别使用两个 encoder 来编码 audio feature 和抽取 subject style
  • 第二步:使用一个 dual-attention module 来生成多样且确定的 motion feature
  • 第三步:分别使用 4 个 decoder 来得到对应的关键点

audio 特征处理:

  • audio feature 抽取:首先使用 Wav2Vec[30] 来抽取语音上下文信息,然后使用 MLP 映射到 s a ∈ R d × T s_a \in R^{d \times T} saRd×T,d 是一帧数据的特征维度,T 是待生成的 vedio 的 frame 的个数

  • 为了建模不同说话风格,作者使用 conditioned subject 的 facial vertices 作为输入,然后将这些 vertices 映射到 d 维向量 v s v_s vs 中作为 subject style code,这里的映射也是使用 MLP 来实现的,然后对 s a s_a sa v s v_s vs 进行结合,得到结合后的特征 s s s

    在这里插入图片描述

  • dual-attention module 的输入是 s s s s a s_a sa,输出是时序上下文 s t s_t st

    在这里插入图片描述

  • 然后,使用 4 个 MLP 来解码不同的关键点

    在这里插入图片描述

Dual-attention module:

  • specific attention branch:SpecAttn
  • probabilistic attention branch:ProbAttn

由于 talking portrait 生成任务需要从有限的驱动信息中生成多模态的输出,所以该任务具有很大的不确定性

本文方法提出的 dual-attention 模型,将这个任务解耦成了下面两个任务:

  • specific mapping :得到时序对齐的确定的 audio 和 lip movement 特征
  • probabilistic mapping:得到时序关联的概率 audio 和 other movements 特征
  • 作者使用两个子模块来分别学习不同的特征,然后使用 time-wise concatenation 来聚合这两种特征

dual-attention 的两个分支:

  • SpecAttn 分支
  • ProbAttn 分支

1、SpecAttn 分支:specific attention branch,用于捕捉 s s s 和 audio feature s a s_a sa 的实时对齐的 attention s s a s_{sa} ssa,根据 FaceFormer,本文的 SpecAttn 格式如下:

在这里插入图片描述

  • d d d s a s_a sa 的维度

  • alignment bias M A M_A MA 如下:

    在这里插入图片描述

不同于 FaceFormer 中只在自回归中使用了 cross-attention,本文在整个序列中都使用了 cross-attention,计算速度提升了 Tx

为了捕捉更丰富的时序信息,作者还在 s s s 上使用了 periodic positional encoding (PPE) 和 biased casual self-attention:

在这里插入图片描述

M T M_T MT 是一个上三角区为负无穷的矩阵,这是为了避免看到未来的帧来进行当前帧的预测

在这里插入图片描述

  • q q q 是控制序列周期的超参数
  • 这样做能够让 encoded feature s’ 包含更丰富的 空间-时序 信息,能够生成的更准确

2、ProbAttn 分支

为了生成更逼真的结果且避免过平滑,学习声音特征和人像动作之间的概率映射很重要,VAE[17] 能够建模概率生成并且在时序的生成任务上表现的比较好

所以,基于 advanced transformer Variational Autoencoder (t-VAE),本文设计了 probabilistic attention branch 来生成更多样的结果

给定特征表达 s s s,probabilistic attention 的目标是生成更多样的特征 s p a s_{pa} spa

  • 首先,将 s s s 送入 encoder(Enc),然后学习 μ \mu μ θ \theta θ 来建模 s s s
  • 然后,使用 decoder(Dec)通过 resample 来生成 multimodal 输出

在这里插入图片描述

  • Φ \Phi Φ:是 MLP
  • U ( μ , θ ) U(\mu, \theta) U(μ,θ):是高斯分布

为了让 ProbAttn 能够学习更丰富的风格,使用 KL 散度 loss 来约束 t-VAE 的特征:

在这里插入图片描述

  • d l d_l dl:是 μ \mu μ 的维度

3、整合两个 attention 的输出

在这里插入图片描述


Loss 函数:

MODA 有四个 decoder,分别生成不同部位的运动系数

所以作者使用了 multi-task 学习机制,通过最小化对应的 L 1 L_1 L1 距离来实现:

在这里插入图片描述

加上 KL loss:

在这里插入图片描述


2.3 Facial Composer Network

在这里插入图片描述

Facial composer network (FaCo-Net)的输入是 subject information S S S 、mouth point P M P^M PM 、eye point P E P^E PE

FaCo-Net 的目标:合成更精细的面部 landmark P F P^F PF

在这里插入图片描述
FaCo-Net 的结构:

  • 3 个 encoder 对 3 种特征分别编码
    • subject encoder:将 facial point S S S 映射到 style code p f p_f pf
    • P M P^M PM encoder:将 P M P^M PM 映射到和 p f p_f pf 同一空间的 p m p_m pm
    • P E P^E PE encoder:将 P E P^E PE 映射到和 p f p_f pf 同一空间的 p e p_e pe
  • 1 个 decoder 生成面部 landmark
    • 在这里插入图片描述
      Faco-Net 的作用是生成器:生成 “看起来逼真” 的 facial dense point

生成器的 loss 如下:

在这里插入图片描述

  • L G A N L_{GAN} LGAN 是 adversarial loss, z ˆ = D ( P F ) \^{z}=D(P^F) zˆ=D(PF)
    在这里插入图片描述
  • λ \lambda λ:10

判别器 D:使用 GAN 作为判别器的 backbone 来判断是真实的 facial points 还是生成的 facial points

用于优化判别器 D 的 adversarial Loss:LSGAN loss

在这里插入图片描述

  • z z z:输入为 gt face points 时,判别器的输出
  • z ˆ \^{z} zˆ:输入为 生成的 face points 时,判别器的输出

生成 facial landmarks P F P^F PF 后, P F P^F PF 会根据 head pose 来变换到 camera coordinate

torso points 和 变换后的 facial landmark 会映射到 image space 来进行写实的渲染

2.4 使用 TPE 来合成人像图片

在这里插入图片描述

最后就是要将前面得到的输出来渲染出人像,如图 2

作者使用 U-Net-like 的带 TPE 的渲染器 G R G_R GR 来生成高保真且稳定的视频

TPE :

在这里插入图片描述

然后使用 G R G_R GR来渲染 t-frame 的结果 I t I_t It

  • I t c I_t^c Itc:是 frame index t 时的 condition image
  • I r I_r Ir:是 reference image

三、效果

3.1 训练细节

训练细节:

  • 超参数 ( β 1 , β 2 ) = ( 0.9 , 0.99 ) (\beta_1, \beta_2)=(0.9,0.99) (β1,β2)=(0.9,0.99)
  • 学习率:10^-4
  • 单卡 3090:三个部分分别需要 (30, 2, 6) 小时,(200,300,100)epoch,(32,32,4) batch
  • 测试时,选择最小的验证 loss 的模型
  • 使用滑动窗口来处理任意长度的视频(window size 300,stirde 150)

3.2 数据

作者使用的 HDTF 和 LSP 数据,video 的平均长度为 1-5 分钟,并且作者将其处理成了 25 fps

作者随机选择 80% 的视频作为训练集,其他的作为测试集,也就是有 132 个训练视频,32 个测试视频

所有视频以人脸为中心,被 resize 成 512x512 大小

数据预处理:

  • 首先,使用 Mediapipe 对所有视频提取 478 个 3D facial landmarks
  • 然后,使用开源方法估计 head pose H,且根据 head pose,将上面的 3D facial landmarks 投影到 canonical space
  • 接着,使用 face parsing 方法来根据分割结果估计出 torso 的 boundary

3.3 测评指标

  • LMD:mouth landmark distance,衡量生成的视频的唇部正确性
  • LMD-v:velocity of mouth landmark distance,衡量生成的视频的唇部正确性
  • MA:衡量预测的 mouth area 和真实的 mouth area 的 IoU
  • confidence score from SyncNet:衡量 audio-video 的合成
  • Natural Image Quality Evaluator (NIQE) :衡量图像的质量,能够捕捉图像的细节

3.4 结果比较

和 SOTA 结果的定量比较:

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

User Study:

在这里插入图片描述

消融实验:

dual-attention 的消融实验效果:

  • 使用 LSTM 代替 dual-attention,LSTM 无法获得 multimodal 的结果,且 diverse score 降低到了 0
  • 移除 specific attention branch,移除后,MODA 生成的唇部运动结果过平滑
  • 移除两个 attention branch

在这里插入图片描述

FaCo-Net 消融实验:该模型的目标是为了为渲染器生成自然且连续的表达特征

作者通过移除该模块,直接使用 facial dense landmark 来代替 eye landmark 和 mouth landmark,如图 6a 展示了没有 FaCo-Net 的结果,唇部区域联系不太正常,且丢失了一些脸部细节

在这里插入图片描述

在这里插入图片描述

TPE 消融实验

作者使用时序一致性衡量方式来衡量 frame-wise consistency(TCM),

在这里插入图片描述

  • O t O_t Ot 表示 reference video(O)第 t 帧
  • V t V_t Vt 表示 generated video (V) 第 t 帧
  • warp(.) 表示使用 optical flow 的 warping function
  • 图 6b 展示了 with/without TPE 的对比效果,可以看出使用 TPE 能够让输出视频更稳定

在这里插入图片描述

在这里插入图片描述


本文方法的限制:

  • 不能很好的泛化到不同的目标人物或 out-of-domain audio
  • 对于新的人物要重新训练渲染部分的模型

单卡 3090 训练时间和测试时间对比:

在这里插入图片描述

四、代码

4.1 数据前处理

git clone https://github.com/DreamtaleCore/MODA.git

1、装环境

我按照官方给出的方法没有装成功,是一步步按 conda 的命令装的

2、下载 HDTF 数据

这里目前只找到了 HDTF 的数据:

有下载 HDTF 工具的 github 路径:https://github.com/universome/HDTF

  • 下载方式:python download.py --output_dir /path/to/output/dir --num_workers 8
  • 注意:要科学上网,需要安装 ffmpeg、youtubu-dl,否则会报错,报错原因可以去下载路径下的 log 中去看
  • 注意:将 download.py 的第 168 行修改成 video_selection = f"best[ext={video_format}]",才能保证下载的视频有声音,否则下载的视频没有声音

3、处理数据

处理数据在 MODA/data_prepare/ 目录下:

第一步:先编译 3DDFA-V2 的环境:

cd 3DDFA-V2
bash build.sh
cd ..

我用 MODA 自带下来的 3DDFA-V2 无法 build,自己重新 clone 了一份 3DDFA_V2 才 build 成功

 sh ./build.sh

第二步:下载 face-parsing 的模型并上传到 face-parsing/res/cp

第三步:执行处理代码:

python process.py -i your/video/dir -o your/output/dir

报错 1 :这里 step0 第 42 行的路径没有写入权限,导致无法在程序运行中间写入,换成有权限的目录

在这里插入图片描述

报错 2:unrecognized option 'crf'

在这里插入图片描述
这常见于在使用 ffmpeg 时使用到了 libx264,但在实际的编译过程中并有指定编译 libx264 参数,默认不会编译这一部分组件,从而产生报错。

可以使用 apt 安装 ffmpeg :

sudo apt install ffmpeg    //通过 apt 安装 ffmpeg

或者如下方式解决:

conda install x264
conda install x264 ffmpeg -c conda-forge

但我都没有解决,然后我就把 -crf 参数舍弃了哈哈哈

修改 step0 中的 line 51 如下:

# cvt_wav_cmd = 'ffmpeg -i ' + vfp + f' -vf scale={args.target_h}:{args.target_w} -crf 2 ' + args.out_video_fp + ' -y' # 无法处理 crf 参数
cvt_wav_cmd = 'ffmpeg -i ' + vfp + f' -vf scale={args.target_h}:{args.target_w} '+ args.out_video_fp + ' -y' # 注意 {args.target_w} 后的空格

报错 3:no module named 'FaceBoxes'

暂且将这里改成了绝对路径,得以解决

在这里插入图片描述

报错 4:找不到 viz_pose2

因为我这里用了 3DDFA_V2 源码,源码中没有这个函数,所以我从 MODA 中重新拷了这个函数,解决了

报错 5:

Could not find a backend to open `/mnt/cpfs/dataset/tuxiangzu/Face_Group/WM/project/MODA/HDTF_PROCESS/RD_Radio11_000/video.mp4`` with iomode `r?`

在这里插入图片描述

 python -m pip install imageio[ffmpeg]
 python -m pip install imageio[pyav]

报错 6:

找不到 step2 中的 3DDFA-V2/config/mb1_120x120.yml,这里没发现作者写成了非下划线,改了好久才发现,我们使用的是 3DDFA_V2 是这样写的,注意修改

在这里插入图片描述

报错 7:onnxruntime.InferenceSession 报错

在这里插入图片描述

按上面的提示添加对应参数:

在这里插入图片描述
报错 8 : 找不到 config 中写的路径, No such file or directory: 'weights/mb1_120x120.pth'No such file or directory: 'configs/bfm_noneck_v3.pkl'

不知道是编译问题还是怎么的,相对路径都不起作用,暂且将 mb1_120x120.yml 中的路径都改为绝对路径

报错 9:module 'numpy' has no attribute 'long',改为 np.longlong()

numpy.long 在 numpy 1.20中被弃用,并在 numpy 1.24 中被删除,可以尝试 numpy.longlong
在这里插入图片描述

在这里插入图片描述

报错 10:AttributeError: module 'numpy' has no attribute 'int'.

在这里插入图片描述

修改为 np.int_,然后重新编译 sh ./build.sh

在这里插入图片描述

报错 11:ModuleNotFoundError: No module named 'RobustVideoMatting'

在这里插入图片描述

在这里插入图片描述

报错 12:其实是提示,但这里也最好改一下,在 step5 中 加上 n_init 这个参数:

在这里插入图片描述
在这里插入图片描述

最后就愉快的跑起来啦,我这里其实很多问题都是相对路径找不到的锅~

预估跑完 HDTF 的 167 个视频需要一两天时间,8线程

在这里插入图片描述

训练时报的错误:缺少 shoulder-billboard.npy

其实可以看到在整个数据处理过程是没有运行 step6 这个文件的,也就是没有从 shoulder.npy 生成 shoulder-billboard.npy,所以训练时候在 audio2repr_dataset.py 中是找不到这个文件的

但作者这里代码和实现逻辑有些出入,没有专门生成 shoulder.py 而是将其写入了 feature.npz 中,可以通过如下方式来调用,所以可以在 step5 后面加入 step6,将 process.py 中的 force_update=False,就是如果已有需要生成的文件时,不执行步骤,这样就能只执行 step6,不执行其他步骤了,生成对应的 shoulder-billboard.npy 就可以了。

process.py
在这里插入图片描述
step6.py

将 62 行注释,添加 64 行

在这里插入图片描述

这里下载的视频数据有些被损坏,有些没有内容,需要删除:

  • WDA_MaggieHassan_000.mp4
  • WRA_PeterKing_000.mp4

4.2 训练

首先,建立自己的 train.txt 和 val.txt

这里作者写的是随机选取的,代码里也没有写是怎么选的,所以我这里也就先随机选了一些:

import os
import random
datapath = 'MODA/assets/dataset/HDTF/HDTF_PROCESS'
dir_list = os.listdir(datapath)
val_list_num = random.sample([x for x in range(0, len(dir_list))], 32)
with open('assets/dataset/HDTF/train.txt', 'w') as f1:
    with open('assets/dataset/HDTF/val.txt', 'w') as f2:
        for i, dirs in enumerate(dir_list):
            if i in val_list_num:
                f2.write('HDTF_PROCESS/' + dirs + '\n')
            else:
                f1.write('HDTF_PROCESS/' + dirs + '\n')

得到的 txt 中放的就是这样的路径:

在这里插入图片描述

报错 1:Expected more than 1 value per channel when training, got input size [1,128]

这里的原因应该是最后一个 batch=1 了,所以这里设置丢弃最后一个就行了

MODA/dataset/__init__.py 的 self.dataloader 中的 drop_last=True 打开

在这里插入图片描述

模型结构:

model [MODAModel] was created
---------- Networks initialized -------------
[Network MODA] Total number of parameters : 96.718 M
-----------------------------------------------
---------- Networks initialized -------------
DataParallel(
  (module): MODANet(
    (audio_encoder): Wav2Vec2Model(
      (feature_extractor): Wav2Vec2FeatureEncoder(
        (conv_layers): ModuleList(
          (0): Wav2Vec2GroupNormConvLayer(
            (conv): Conv1d(1, 512, kernel_size=(10,), stride=(5,), bias=False)
            (activation): GELUActivation()
            (layer_norm): GroupNorm(512, 512, eps=1e-05, affine=True)
          )
          (1): Wav2Vec2NoLayerNormConvLayer(
            (conv): Conv1d(512, 512, kernel_size=(3,), stride=(2,), bias=False)
            (activation): GELUActivation()
          )
          (2): Wav2Vec2NoLayerNormConvLayer(
            (conv): Conv1d(512, 512, kernel_size=(3,), stride=(2,), bias=False)
            (activation): GELUActivation()
          )
          (3): Wav2Vec2NoLayerNormConvLayer(
            (conv): Conv1d(512, 512, kernel_size=(3,), stride=(2,), bias=False)
            (activation): GELUActivation()
          )
          (4): Wav2Vec2NoLayerNormConvLayer(
            (conv): Conv1d(512, 512, kernel_size=(3,), stride=(2,), bias=False)
            (activation): GELUActivation()
          )
          (5): Wav2Vec2NoLayerNormConvLayer(
            (conv): Conv1d(512, 512, kernel_size=(2,), stride=(2,), bias=False)
            (activation): GELUActivation()
          )
          (6): Wav2Vec2NoLayerNormConvLayer(
            (conv): Conv1d(512, 512, kernel_size=(2,), stride=(2,), bias=False)
            (activation): GELUActivation()
          )
        )
      )
      (feature_projection): Wav2Vec2FeatureProjection(
        (layer_norm): LayerNorm((512,), eps=1e-05, elementwise_affine=True)
        (projection): Linear(in_features=512, out_features=768, bias=True)
        (dropout): Dropout(p=0.1, inplace=False)
      )
      (encoder): Wav2Vec2Encoder(
        (pos_conv_embed): Wav2Vec2PositionalConvEmbedding(
          (conv): Conv1d(768, 768, kernel_size=(128,), stride=(1,), padding=(64,), groups=16)
          (padding): Wav2Vec2SamePadLayer()
          (activation): GELUActivation()
        )
        (layer_norm): LayerNorm((768,), eps=1e-05, elementwise_affine=True)
        (dropout): Dropout(p=0.1, inplace=False)
        (layers): ModuleList(
          (0): Wav2Vec2EncoderLayer(
            (attention): Wav2Vec2Attention(
              (k_proj): Linear(in_features=768, out_features=768, bias=True)
              (v_proj): Linear(in_features=768, out_features=768, bias=True)
              (q_proj): Linear(in_features=768, out_features=768, bias=True)
              (out_proj): Linear(in_features=768, out_features=768, bias=True)
            )
            (dropout): Dropout(p=0.1, inplace=False)
            (layer_norm): LayerNorm((768,), eps=1e-05, elementwise_affine=True)
            (feed_forward): Wav2Vec2FeedForward(
              (intermediate_dropout): Dropout(p=0.1, inplace=False)
              (intermediate_dense): Linear(in_features=768, out_features=3072, bias=True)
              (intermediate_act_fn): GELUActivation()
              (output_dense): Linear(in_features=3072, out_features=768, bias=True)
              (output_dropout): Dropout(p=0.1, inplace=False)
            )
            (final_layer_norm): LayerNorm((768,), eps=1e-05, elementwise_affine=True)
          )
          (1): Wav2Vec2EncoderLayer(
            (attention): Wav2Vec2Attention(
              (k_proj): Linear(in_features=768, out_features=768, bias=True)
              (v_proj): Linear(in_features=768, out_features=768, bias=True)
              (q_proj): Linear(in_features=768, out_features=768, bias=True)
              (out_proj): Linear(in_features=768, out_features=768, bias=True)
            )
            (dropout): Dropout(p=0.1, inplace=False)
            (layer_norm): LayerNorm((768,), eps=1e-05, elementwise_affine=True)
            (feed_forward): Wav2Vec2FeedForward(
              (intermediate_dropout): Dropout(p=0.1, inplace=False)
              (intermediate_dense): Linear(in_features=768, out_features=3072, bias=True)
              (intermediate_act_fn): GELUActivation()
              (output_dense): Linear(in_features=3072, out_features=768, bias=True)
              (output_dropout): Dropout(p=0.1, inplace=False)
            )
            (final_layer_norm): LayerNorm((768,), eps=1e-05, elementwise_affine=True)
          )
          (2): Wav2Vec2EncoderLayer(
            (attention): Wav2Vec2Attention(
              (k_proj): Linear(in_features=768, out_features=768, bias=True)
              (v_proj): Linear(in_features=768, out_features=768, bias=True)
              (q_proj): Linear(in_features=768, out_features=768, bias=True)
              (out_proj): Linear(in_features=768, out_features=768, bias=True)
            )
            (dropout): Dropout(p=0.1, inplace=False)
            (layer_norm): LayerNorm((768,), eps=1e-05, elementwise_affine=True)
            (feed_forward): Wav2Vec2FeedForward(
              (intermediate_dropout): Dropout(p=0.1, inplace=False)
              (intermediate_dense): Linear(in_features=768, out_features=3072, bias=True)
              (intermediate_act_fn): GELUActivation()
              (output_dense): Linear(in_features=3072, out_features=768, bias=True)
              (output_dropout): Dropout(p=0.1, inplace=False)
            )
            (final_layer_norm): LayerNorm((768,), eps=1e-05, elementwise_affine=True)
          )
          (3): Wav2Vec2EncoderLayer(
            (attention): Wav2Vec2Attention(
              (k_proj): Linear(in_features=768, out_features=768, bias=True)
              (v_proj): Linear(in_features=768, out_features=768, bias=True)
              (q_proj): Linear(in_features=768, out_features=768, bias=True)
              (out_proj): Linear(in_features=768, out_features=768, bias=True)
            )
            (dropout): Dropout(p=0.1, inplace=False)
            (layer_norm): LayerNorm((768,), eps=1e-05, elementwise_affine=True)
            (feed_forward): Wav2Vec2FeedForward(
              (intermediate_dropout): Dropout(p=0.1, inplace=False)
              (intermediate_dense): Linear(in_features=768, out_features=3072, bias=True)
              (intermediate_act_fn): GELUActivation()
              (output_dense): Linear(in_features=3072, out_features=768, bias=True)
              (output_dropout): Dropout(p=0.1, inplace=False)
            )
            (final_layer_norm): LayerNorm((768,), eps=1e-05, elementwise_affine=True)
          )
          (4): Wav2Vec2EncoderLayer(
            (attention): Wav2Vec2Attention(
              (k_proj): Linear(in_features=768, out_features=768, bias=True)
              (v_proj): Linear(in_features=768, out_features=768, bias=True)
              (q_proj): Linear(in_features=768, out_features=768, bias=True)
              (out_proj): Linear(in_features=768, out_features=768, bias=True)
            )
            (dropout): Dropout(p=0.1, inplace=False)
            (layer_norm): LayerNorm((768,), eps=1e-05, elementwise_affine=True)
            (feed_forward): Wav2Vec2FeedForward(
              (intermediate_dropout): Dropout(p=0.1, inplace=False)
              (intermediate_dense): Linear(in_features=768, out_features=3072, bias=True)
              (intermediate_act_fn): GELUActivation()
              (output_dense): Linear(in_features=3072, out_features=768, bias=True)
              (output_dropout): Dropout(p=0.1, inplace=False)
            )
            (final_layer_norm): LayerNorm((768,), eps=1e-05, elementwise_affine=True)
          )
          (5): Wav2Vec2EncoderLayer(
            (attention): Wav2Vec2Attention(
              (k_proj): Linear(in_features=768, out_features=768, bias=True)
              (v_proj): Linear(in_features=768, out_features=768, bias=True)
              (q_proj): Linear(in_features=768, out_features=768, bias=True)
              (out_proj): Linear(in_features=768, out_features=768, bias=True)
            )
            (dropout): Dropout(p=0.1, inplace=False)
            (layer_norm): LayerNorm((768,), eps=1e-05, elementwise_affine=True)
            (feed_forward): Wav2Vec2FeedForward(
              (intermediate_dropout): Dropout(p=0.1, inplace=False)
              (intermediate_dense): Linear(in_features=768, out_features=3072, bias=True)
              (intermediate_act_fn): GELUActivation()
              (output_dense): Linear(in_features=3072, out_features=768, bias=True)
              (output_dropout): Dropout(p=0.1, inplace=False)
            )
            (final_layer_norm): LayerNorm((768,), eps=1e-05, elementwise_affine=True)
          )
          (6): Wav2Vec2EncoderLayer(
            (attention): Wav2Vec2Attention(
              (k_proj): Linear(in_features=768, out_features=768, bias=True)
              (v_proj): Linear(in_features=768, out_features=768, bias=True)
              (q_proj): Linear(in_features=768, out_features=768, bias=True)
              (out_proj): Linear(in_features=768, out_features=768, bias=True)
            )
            (dropout): Dropout(p=0.1, inplace=False)
            (layer_norm): LayerNorm((768,), eps=1e-05, elementwise_affine=True)
            (feed_forward): Wav2Vec2FeedForward(
              (intermediate_dropout): Dropout(p=0.1, inplace=False)
              (intermediate_dense): Linear(in_features=768, out_features=3072, bias=True)
              (intermediate_act_fn): GELUActivation()
              (output_dense): Linear(in_features=3072, out_features=768, bias=True)
              (output_dropout): Dropout(p=0.1, inplace=False)
            )
            (final_layer_norm): LayerNorm((768,), eps=1e-05, elementwise_affine=True)
          )
          (7): Wav2Vec2EncoderLayer(
            (attention): Wav2Vec2Attention(
              (k_proj): Linear(in_features=768, out_features=768, bias=True)
              (v_proj): Linear(in_features=768, out_features=768, bias=True)
              (q_proj): Linear(in_features=768, out_features=768, bias=True)
              (out_proj): Linear(in_features=768, out_features=768, bias=True)
            )
            (dropout): Dropout(p=0.1, inplace=False)
            (layer_norm): LayerNorm((768,), eps=1e-05, elementwise_affine=True)
            (feed_forward): Wav2Vec2FeedForward(
              (intermediate_dropout): Dropout(p=0.1, inplace=False)
              (intermediate_dense): Linear(in_features=768, out_features=3072, bias=True)
              (intermediate_act_fn): GELUActivation()
              (output_dense): Linear(in_features=3072, out_features=768, bias=True)
              (output_dropout): Dropout(p=0.1, inplace=False)
            )
            (final_layer_norm): LayerNorm((768,), eps=1e-05, elementwise_affine=True)
          )
          (8): Wav2Vec2EncoderLayer(
            (attention): Wav2Vec2Attention(
              (k_proj): Linear(in_features=768, out_features=768, bias=True)
              (v_proj): Linear(in_features=768, out_features=768, bias=True)
              (q_proj): Linear(in_features=768, out_features=768, bias=True)
              (out_proj): Linear(in_features=768, out_features=768, bias=True)
            )
            (dropout): Dropout(p=0.1, inplace=False)
            (layer_norm): LayerNorm((768,), eps=1e-05, elementwise_affine=True)
            (feed_forward): Wav2Vec2FeedForward(
              (intermediate_dropout): Dropout(p=0.1, inplace=False)
              (intermediate_dense): Linear(in_features=768, out_features=3072, bias=True)
              (intermediate_act_fn): GELUActivation()
              (output_dense): Linear(in_features=3072, out_features=768, bias=True)
              (output_dropout): Dropout(p=0.1, inplace=False)
            )
            (final_layer_norm): LayerNorm((768,), eps=1e-05, elementwise_affine=True)
          )
          (9): Wav2Vec2EncoderLayer(
            (attention): Wav2Vec2Attention(
              (k_proj): Linear(in_features=768, out_features=768, bias=True)
              (v_proj): Linear(in_features=768, out_features=768, bias=True)
              (q_proj): Linear(in_features=768, out_features=768, bias=True)
              (out_proj): Linear(in_features=768, out_features=768, bias=True)
            )
            (dropout): Dropout(p=0.1, inplace=False)
            (layer_norm): LayerNorm((768,), eps=1e-05, elementwise_affine=True)
            (feed_forward): Wav2Vec2FeedForward(
              (intermediate_dropout): Dropout(p=0.1, inplace=False)
              (intermediate_dense): Linear(in_features=768, out_features=3072, bias=True)
              (intermediate_act_fn): GELUActivation()
              (output_dense): Linear(in_features=3072, out_features=768, bias=True)
              (output_dropout): Dropout(p=0.1, inplace=False)
            )
            (final_layer_norm): LayerNorm((768,), eps=1e-05, elementwise_affine=True)
          )
          (10): Wav2Vec2EncoderLayer(
            (attention): Wav2Vec2Attention(
              (k_proj): Linear(in_features=768, out_features=768, bias=True)
              (v_proj): Linear(in_features=768, out_features=768, bias=True)
              (q_proj): Linear(in_features=768, out_features=768, bias=True)
              (out_proj): Linear(in_features=768, out_features=768, bias=True)
            )
            (dropout): Dropout(p=0.1, inplace=False)
            (layer_norm): LayerNorm((768,), eps=1e-05, elementwise_affine=True)
            (feed_forward): Wav2Vec2FeedForward(
              (intermediate_dropout): Dropout(p=0.1, inplace=False)
              (intermediate_dense): Linear(in_features=768, out_features=3072, bias=True)
              (intermediate_act_fn): GELUActivation()
              (output_dense): Linear(in_features=3072, out_features=768, bias=True)
              (output_dropout): Dropout(p=0.1, inplace=False)
            )
            (final_layer_norm): LayerNorm((768,), eps=1e-05, elementwise_affine=True)
          )
          (11): Wav2Vec2EncoderLayer(
            (attention): Wav2Vec2Attention(
              (k_proj): Linear(in_features=768, out_features=768, bias=True)
              (v_proj): Linear(in_features=768, out_features=768, bias=True)
              (q_proj): Linear(in_features=768, out_features=768, bias=True)
              (out_proj): Linear(in_features=768, out_features=768, bias=True)
            )
            (dropout): Dropout(p=0.1, inplace=False)
            (layer_norm): LayerNorm((768,), eps=1e-05, elementwise_affine=True)
            (feed_forward): Wav2Vec2FeedForward(
              (intermediate_dropout): Dropout(p=0.1, inplace=False)
              (intermediate_dense): Linear(in_features=768, out_features=3072, bias=True)
              (intermediate_act_fn): GELUActivation()
              (output_dense): Linear(in_features=3072, out_features=768, bias=True)
              (output_dropout): Dropout(p=0.1, inplace=False)
            )
            (final_layer_norm): LayerNorm((768,), eps=1e-05, elementwise_affine=True)
          )
        )
      )
    )
    (audio_encoder_head): MLP(
      (layers): Sequential(
        (0): Linear(in_features=768, out_features=128, bias=True)
        (1): BatchNorm1d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (2): LeakyReLU(negative_slope=0.2)
        (3): Linear(in_features=128, out_features=128, bias=True)
      )
    )
    (subject_encoder_head): MLP(
      (layers): Sequential(
        (0): Linear(in_features=1434, out_features=128, bias=True)
        (1): BatchNorm1d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (2): LeakyReLU(negative_slope=0.2)
        (3): Linear(in_features=128, out_features=128, bias=True)
        (4): BatchNorm1d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (5): LeakyReLU(negative_slope=0.2)
        (6): Linear(in_features=128, out_features=128, bias=True)
      )
    )
    (temporal_body): DualTemporalMoudleV2(
      (short_layer): TemporalAlignedBlock(
        (decoder): TransformerDecoder(
          (layers): ModuleList(
            (0): TransformerDecoderLayer(
              (self_attn): MultiheadAttention(
                (out_proj): NonDynamicallyQuantizableLinear(in_features=128, out_features=128, bias=True)
              )
              (multihead_attn): MultiheadAttention(
                (out_proj): NonDynamicallyQuantizableLinear(in_features=128, out_features=128, bias=True)
              )
              (linear1): Linear(in_features=128, out_features=128, bias=True)
              (dropout): Dropout(p=0.1, inplace=False)
              (linear2): Linear(in_features=128, out_features=128, bias=True)
              (norm1): LayerNorm((128,), eps=1e-05, elementwise_affine=True)
              (norm2): LayerNorm((128,), eps=1e-05, elementwise_affine=True)
              (norm3): LayerNorm((128,), eps=1e-05, elementwise_affine=True)
              (dropout1): Dropout(p=0.1, inplace=False)
              (dropout2): Dropout(p=0.1, inplace=False)
              (dropout3): Dropout(p=0.1, inplace=False)
            )
            (1): TransformerDecoderLayer(
              (self_attn): MultiheadAttention(
                (out_proj): NonDynamicallyQuantizableLinear(in_features=128, out_features=128, bias=True)
              )
              (multihead_attn): MultiheadAttention(
                (out_proj): NonDynamicallyQuantizableLinear(in_features=128, out_features=128, bias=True)
              )
              (linear1): Linear(in_features=128, out_features=128, bias=True)
              (dropout): Dropout(p=0.1, inplace=False)
              (linear2): Linear(in_features=128, out_features=128, bias=True)
              (norm1): LayerNorm((128,), eps=1e-05, elementwise_affine=True)
              (norm2): LayerNorm((128,), eps=1e-05, elementwise_affine=True)
              (norm3): LayerNorm((128,), eps=1e-05, elementwise_affine=True)
              (dropout1): Dropout(p=0.1, inplace=False)
              (dropout2): Dropout(p=0.1, inplace=False)
              (dropout3): Dropout(p=0.1, inplace=False)
            )
            (2): TransformerDecoderLayer(
              (self_attn): MultiheadAttention(
                (out_proj): NonDynamicallyQuantizableLinear(in_features=128, out_features=128, bias=True)
              )
              (multihead_attn): MultiheadAttention(
                (out_proj): NonDynamicallyQuantizableLinear(in_features=128, out_features=128, bias=True)
              )
              (linear1): Linear(in_features=128, out_features=128, bias=True)
              (dropout): Dropout(p=0.1, inplace=False)
              (linear2): Linear(in_features=128, out_features=128, bias=True)
              (norm1): LayerNorm((128,), eps=1e-05, elementwise_affine=True)
              (norm2): LayerNorm((128,), eps=1e-05, elementwise_affine=True)
              (norm3): LayerNorm((128,), eps=1e-05, elementwise_affine=True)
              (dropout1): Dropout(p=0.1, inplace=False)
              (dropout2): Dropout(p=0.1, inplace=False)
              (dropout3): Dropout(p=0.1, inplace=False)
            )
          )
        )
        (ppe): PeriodicPositionalEncoding(
          (dropout): Dropout(p=0.1, inplace=False)
        )
      )
      (long_layer): TemporalVAEBlock(
        (embedding): PositionalEncoding(
          (dropout): Dropout(p=0.1, inplace=False)
        )
        (encoder): TransformerEncoder(
          (layers): ModuleList(
            (0): TransformerEncoderLayer(
              (self_attn): MultiheadAttention(
                (out_proj): NonDynamicallyQuantizableLinear(in_features=128, out_features=128, bias=True)
              )
              (linear1): Linear(in_features=128, out_features=128, bias=True)
              (dropout): Dropout(p=0.1, inplace=False)
              (linear2): Linear(in_features=128, out_features=128, bias=True)
              (norm1): LayerNorm((128,), eps=1e-05, elementwise_affine=True)
              (norm2): LayerNorm((128,), eps=1e-05, elementwise_affine=True)
              (dropout1): Dropout(p=0.1, inplace=False)
              (dropout2): Dropout(p=0.1, inplace=False)
            )
            (1): TransformerEncoderLayer(
              (self_attn): MultiheadAttention(
                (out_proj): NonDynamicallyQuantizableLinear(in_features=128, out_features=128, bias=True)
              )
              (linear1): Linear(in_features=128, out_features=128, bias=True)
              (dropout): Dropout(p=0.1, inplace=False)
              (linear2): Linear(in_features=128, out_features=128, bias=True)
              (norm1): LayerNorm((128,), eps=1e-05, elementwise_affine=True)
              (norm2): LayerNorm((128,), eps=1e-05, elementwise_affine=True)
              (dropout1): Dropout(p=0.1, inplace=False)
              (dropout2): Dropout(p=0.1, inplace=False)
            )
            (2): TransformerEncoderLayer(
              (self_attn): MultiheadAttention(
                (out_proj): NonDynamicallyQuantizableLinear(in_features=128, out_features=128, bias=True)
              )
              (linear1): Linear(in_features=128, out_features=128, bias=True)
              (dropout): Dropout(p=0.1, inplace=False)
              (linear2): Linear(in_features=128, out_features=128, bias=True)
              (norm1): LayerNorm((128,), eps=1e-05, elementwise_affine=True)
              (norm2): LayerNorm((128,), eps=1e-05, elementwise_affine=True)
              (dropout1): Dropout(p=0.1, inplace=False)
              (dropout2): Dropout(p=0.1, inplace=False)
            )
          )
        )
        (decoder): TransformerDecoder(
          (layers): ModuleList(
            (0): TransformerDecoderLayer(
              (self_attn): MultiheadAttention(
                (out_proj): NonDynamicallyQuantizableLinear(in_features=128, out_features=128, bias=True)
              )
              (multihead_attn): MultiheadAttention(
                (out_proj): NonDynamicallyQuantizableLinear(in_features=128, out_features=128, bias=True)
              )
              (linear1): Linear(in_features=128, out_features=128, bias=True)
              (dropout): Dropout(p=0.1, inplace=False)
              (linear2): Linear(in_features=128, out_features=128, bias=True)
              (norm1): LayerNorm((128,), eps=1e-05, elementwise_affine=True)
              (norm2): LayerNorm((128,), eps=1e-05, elementwise_affine=True)
              (norm3): LayerNorm((128,), eps=1e-05, elementwise_affine=True)
              (dropout1): Dropout(p=0.1, inplace=False)
              (dropout2): Dropout(p=0.1, inplace=False)
              (dropout3): Dropout(p=0.1, inplace=False)
            )
            (1): TransformerDecoderLayer(
              (self_attn): MultiheadAttention(
                (out_proj): NonDynamicallyQuantizableLinear(in_features=128, out_features=128, bias=True)
              )
              (multihead_attn): MultiheadAttention(
                (out_proj): NonDynamicallyQuantizableLinear(in_features=128, out_features=128, bias=True)
              )
              (linear1): Linear(in_features=128, out_features=128, bias=True)
              (dropout): Dropout(p=0.1, inplace=False)
              (linear2): Linear(in_features=128, out_features=128, bias=True)
              (norm1): LayerNorm((128,), eps=1e-05, elementwise_affine=True)
              (norm2): LayerNorm((128,), eps=1e-05, elementwise_affine=True)
              (norm3): LayerNorm((128,), eps=1e-05, elementwise_affine=True)
              (dropout1): Dropout(p=0.1, inplace=False)
              (dropout2): Dropout(p=0.1, inplace=False)
              (dropout3): Dropout(p=0.1, inplace=False)
            )
            (2): TransformerDecoderLayer(
              (self_attn): MultiheadAttention(
                (out_proj): NonDynamicallyQuantizableLinear(in_features=128, out_features=128, bias=True)
              )
              (multihead_attn): MultiheadAttention(
                (out_proj): NonDynamicallyQuantizableLinear(in_features=128, out_features=128, bias=True)
              )
              (linear1): Linear(in_features=128, out_features=128, bias=True)
              (dropout): Dropout(p=0.1, inplace=False)
              (linear2): Linear(in_features=128, out_features=128, bias=True)
              (norm1): LayerNorm((128,), eps=1e-05, elementwise_affine=True)
              (norm2): LayerNorm((128,), eps=1e-05, elementwise_affine=True)
              (norm3): LayerNorm((128,), eps=1e-05, elementwise_affine=True)
              (dropout1): Dropout(p=0.1, inplace=False)
              (dropout2): Dropout(p=0.1, inplace=False)
              (dropout3): Dropout(p=0.1, inplace=False)
            )
          )
        )
        (out): Sequential(
          (0): Linear(in_features=128, out_features=128, bias=True)
        )
        (to_mu): Linear(in_features=128, out_features=128, bias=True)
        (to_logvar): Linear(in_features=128, out_features=128, bias=True)
        (decode_latent): Linear(in_features=128, out_features=128, bias=True)
      )
    )
    (lipmotion_tail): MLP(
      (layers): Sequential(
        (0): Linear(in_features=256, out_features=512, bias=True)
        (1): BatchNorm1d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (2): LeakyReLU(negative_slope=0.2)
        (3): Linear(in_features=512, out_features=120, bias=True)
      )
    )
    (eyemovement_tail): MLP(
      (layers): Sequential(
        (0): Linear(in_features=256, out_features=256, bias=True)
        (1): BatchNorm1d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (2): LeakyReLU(negative_slope=0.2)
        (3): Linear(in_features=256, out_features=256, bias=True)
        (4): BatchNorm1d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (5): LeakyReLU(negative_slope=0.2)
        (6): Linear(in_features=256, out_features=180, bias=True)
      )
    )
    (headmotion_tail): MLP(
      (layers): Sequential(
        (0): Linear(in_features=256, out_features=256, bias=True)
        (1): BatchNorm1d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (2): LeakyReLU(negative_slope=0.2)
        (3): Linear(in_features=256, out_features=256, bias=True)
        (4): BatchNorm1d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (5): LeakyReLU(negative_slope=0.2)
        (6): Linear(in_features=256, out_features=7, bias=True)
      )
    )
    (torsomotion_tail): MLP(
      (layers): Sequential(
        (0): Linear(in_features=256, out_features=256, bias=True)
        (1): BatchNorm1d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (2): LeakyReLU(negative_slope=0.2)
        (3): Linear(in_features=256, out_features=256, bias=True)
        (4): BatchNorm1d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
        (5): LeakyReLU(negative_slope=0.2)
        (6): Linear(in_features=256, out_features=54, bias=True)
      )
    )
  )
)
[Network MODA] Total number of parameters : 96.718 M

在这里插入图片描述

lip decoder:MLP

Sequential(
  (0): Linear(in_features=256, out_features=512, bias=True)
  (1): BatchNorm1d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (2): LeakyReLU(negative_slope=0.2)
  (3): Linear(in_features=512, out_features=120, bias=True)
)

batch norm 输出后的特征(x_1)基本都一样了

layer_0 的输出:

在这里插入图片描述

layer_1 的输出:全为负值

在这里插入图片描述

推测是模型根本没训练好,可能是学习率的问题,也可能是 target 的问题

这里把学习率从原本的 1e-4 调到了 1e-3 和 1e-5,都没有什么改变,loss 很大,尤其是 headmotion loss 大概在几十万,所以这里 target 的训练应该是有问题的

所以我又去看了看为什么 loss 这么大,发现 target_headmotion 和 target_torsomotion 的数据分布范围很大:

在这里插入图片描述
在这里插入图片描述

可以看看其他的 target 还是比较小的:

在这里插入图片描述
在这里插入图片描述

去 audio2repr_dataset.py 中看看数据是怎么处理的:

在这里插入图片描述
data: len=17,这里的 1200 表示 batch=2,每个 batch 帧数为 600

  • data_list[file_index][0]:audio_array,tensor([-0.8657, -0.9239, -0.8294, …, -0.0095, -0.0519, -0.1292]),torch.Size([640128])
  • data_list[file_index][1]:av_rate,533
  • data_list[file_index][2]:face_vertices,torch.Size([1200, 478, 3])
  • data_list[file_index][3]:face_vert_ref 均值,[478, 3]
  • data_list[file_index][4]:face_vert_ref 方差,[478, 3]
  • data_list[file_index][5]:face_headposes,[1200, 3]
  • data_list[file_index][6]:face_head_ref 均值,[3]
  • data_list[file_index][7]:face_head_ref 方差, [3]
  • data_list[file_index][8]:face_transposes, [1200, 3]
  • data_list[file_index][9]:face_trans_ref 均值, [3]
  • data_list[file_index][10]:face_trans_ref 方差, [3]
  • data_list[file_index][11]:face_scales, [1200, 1]
  • data_list[file_index][12]:face_scale_ref 均值, [1]
  • data_list[file_index][13]:face_scale_ref 方差, [1]
  • data_list[file_index][14]:torso_info, [1200, 18, 3]
  • data_list[file_index][15]:torso_info_ref 均值, [18, 3]
  • data_list[file_index][16]:torso_info_ref 方差, [18, 3]

4.3 推理

先使用 mediapipe 来提取面部关键点

# 一段从 utils.py 截出来的代码片,只是展示操作方式而已
import mediapipe as mp
mp_drawing_styles = mp.solutions.drawing_styles
mp_connections = mp.solutions.face_mesh_connections
def get_semantic_indices():
    semantic_connections = {
        'Contours':     mp_connections.FACEMESH_CONTOURS,
        'FaceOval':     mp_connections.FACEMESH_FACE_OVAL,
        'LeftIris':     mp_connections.FACEMESH_LEFT_IRIS,
        'LeftEye':      mp_connections.FACEMESH_LEFT_EYE,
        'LeftEyebrow':  mp_connections.FACEMESH_LEFT_EYEBROW,
        'RightIris':    mp_connections.FACEMESH_RIGHT_IRIS,
        'RightEye':     mp_connections.FACEMESH_RIGHT_EYE,
        'RightEyebrow': mp_connections.FACEMESH_RIGHT_EYEBROW,
        'Lips':         mp_connections.FACEMESH_LIPS,
        'Tesselation':  mp_connections.FACEMESH_TESSELATION
    }

    def get_compact_idx(connections):
        ret = []
        for conn in connections:
            ret.append(conn[0])
            ret.append(conn[1])
        
        return sorted(tuple(set(ret)))
    
    semantic_indexes = {k: get_compact_idx(v) for k, v in semantic_connections.items()}

    return semantic_indexes

generate_feature.py 得到的面部信息如下:

{
'Contours': [0, 7, 10, 13, 14, 17, 21, 33, 37, 39, 40, 46, 52, 53, 54, 55, 58, 61, 63, 65, 66, 67, 70, 78, 80, 81, 82, 84, 87, 88, 91, 93, 95, 103, 105, 107, 109, 127, 132, 133, 136, 144, 145, 146, 148, 149, 150, 152, 153, 154, 155, 157, 158, 159, 160, 161, 162, 163, 172, 173, 176, 178, 181, 185, 191, 234, 246, 249, 251, 263, 267, 269, 270, 276, 282, 283, 284, 285, 288, 291, 293, 295, 296, 297, 300, 308, 310, 311, 312, 314, 317, 318, 321, 323, 324, 332, 334, 336, 338, 356, 361, 362, 365, 373, 374, 375, 377, 378, 379, 380, 381, 382, 384, 385, 386, 387, 388, 389, 390, 397, 398, 400, 402, 405, 409, 415, 454, 466], 
'FaceOval': [10, 21, 54, 58, 67, 93, 103, 109, 127, 132, 136, 148, 149, 150, 152, 162, 172, 176, 234, 251, 284, 288, 297, 323, 332, 338, 356, 361, 365, 377, 378, 379, 389, 397, 400, 454], 
'LeftIris': [474, 475, 476, 477], 
'LeftEye': [249, 263, 362, 373, 374, 380, 381, 382, 384, 385, 386, 387, 388, 390, 398, 466], 
'LeftEyebrow': [276, 282, 283, 285, 293, 295, 296, 300, 334, 336], 
'RightIris': [469, 470, 471, 472], 
'RightEye': [7, 33, 133, 144, 145, 153, 154, 155, 157, 158, 159, 160, 161, 163, 173, 246], 
'RightEyebrow': [46, 52, 53, 55, 63, 65, 66, 70, 105, 107], 
'Lips': [0, 13, 14, 17, 37, 39, 40, 61, 78, 80, 81, 82, 84, 87, 88, 91, 95, 146, 178, 181, 185, 191, 267, 269, 270, 291, 308, 310, 311, 312, 314, 317, 318, 321, 324, 375, 402, 405, 409, 415], 
'Tesselation': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427, 428, 429, 430, 431, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465, 466, 467]}

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

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

相关文章

【工具】VS2019编译速度过慢问题的解决

一、发现问题 新下载的vs2022编译器,当写完代码后编译速度很慢,一开始以为是电脑的性能问题,毕竟自己的电脑跟个老古董一样了,但是偶然看到配置比我逊的电脑,编译的速度也很快让我燃起了信心。原来主要原因不是我的电脑…

SpringCache_概述、Cacheable、更新缓存、删除缓存、从0搭建缓存项目

文章目录 ①. Spring Cache概述②. 触发缓存入口 - Cacheable③. 更新缓存 - CachePut④. 删除缓存 - CacheEvict⑤. 组合操作- Caching⑥. 共享缓存配置 - CacheConfig⑦. 从0搭建缓存项目 ①. Spring Cache概述 ①. 如何找到Spring Cache的官方文档 ②.Spring 从 3.1开始定义…

听说C++有类和对象,所以好好八卦一下

文章目录 前言Ⅰ. 了解面向过程和面向对象Ⅱ. 类的引入和定义Ⅲ. 类的访问限定符及封装0x00 访问限定符0x01 封装 Ⅳ. 类的作用域Ⅴ. 类的实例化Ⅵ. 类对象模型0x00 类对象大小0x01 类对象存储方式 Ⅶ. this指针 前言 亲爱的夏目友人帐的小伙伴们,今天我们继续讲解…

黑豹程序员-架构师学习路线图-百科:Database数据库

文章目录 1、什么是Database2、发展历史3、数据库排行网4、总结 1、什么是Database 当今世界是一个充满着数据的互联网世界,各处都充斥着大量的数据。即这个互联网世界就是数据世界。 支撑这个数据世界的基石就是数据库,数据库也可以称为数据的仓库。 …

应用层协议 HTTP

一、应用层协议 我们已经学过 TCP/IP , 已然知道数据能从客户端进程经过路径选择跨网络传送到服务器端进程。 我们还需要知道的是,我们把数据从 A 端传送到 B 端, TCP/IP 解决的是顺丰的功能,而两端还要对数据进行加工处理或者使用&#xf…

泛微E-Office前台文件读取漏洞

一、漏洞描述 泛微E-Office是一款企业级的全流程办公自动化软件,它包括协同办公、文档管理、知识管理、工作流管理等多个模块,涵盖了企业日常工作中的各个环节。泛微E-Office能够帮助企业实现全流程数字化、自动化,提高工作效率和管理质量&a…

网络安全--安全认证、IPSEC技术

目录 1. 什么是数据认证,有什么作用,有哪些实现的技术手段? 2. 什么是身份认证,有什么作用,有哪些实现的技术手段? 3. 什么是VPN技术? 4. VPN技术有哪些分类? 5. IPSEC技术能够…

【Redis实战】击穿+雪崩+穿透

架构 短信登录 基于session实现登录 流程图 代码实现 Slf4j Service public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {/*** session用户key*/public static final String USER_CONSTANT "user";Overridepub…

Springboot学习笔记——2

Springboot学习笔记——2 一、打包与运行1.1、程序打包与运行&#xff08;windows版&#xff09;1.2、打包插件1.3、Boot工程快速启动&#xff08;Linux版&#xff09; 二、配置高级2.1、临时属性设置2.2、配置程序四级分类2.3、自定义配置文件 三、多环境开发3.1、多环境开发&…

【计算机网络-自顶向下方法】应用层(HTTP、FTP)

1. Principles of network applications 创建一个网络应用 创建一个网络应用的核心&#xff0c;是编写一个分布式程序&#xff0c;使其可以运行在不同的端系统上&#xff0c;并能通过网络相互通信。&#xff08;例如&#xff0c;web服务器软件与浏览器软件&#xff09;   应…

为什么很多编程语言中数组都是从0开始编号?

文章来源于极客时间前google工程师−王争专栏。 如何实现随机访问? 什么是数组&#xff1f; 数组&#xff08;Array&#xff09;是一种线性表数据结构。它用一组连续的内存空间&#xff0c;来存储一组具有相同类型的数据。 线性表&#xff0c;顾名思义&#xff0c;线性表就…

林沛满-TCP之在途字节数

本文整理自&#xff1a;《Wireshark网络分析的艺术 第1版》 作者&#xff1a;林沛满 著 出版时间&#xff1a;2016-02 我一直谨记斯蒂芬霍金的金玉良言—每写一道数学公式就会失去一半读者。不过为了深度分析网络包&#xff0c;有时候是不得不计算的&#xff0c;好在小学一年级…

DirectX12_Windows_GameDevelop_3:Direct3D的初始化

引言 查看龙书时发现&#xff0c;第四章介绍预备知识的代码不太利于学习。因为它不像是LearnOpenGL那样从头开始一步一步教你敲代码&#xff0c;导致你没有一种整体感。如果你把它当作某一块的代码进行学习&#xff0c;你跟着敲会发现&#xff0c;总有几个变量是没有定义的。这…

【C++设计模式之策略模式】分析及示例

描述 策略模式&#xff08;Strategy Pattern&#xff09;是一种行为型设计模式&#xff0c;它允许在运行时根据不同的情况选择算法的行为。该模式将算法的定义封装成一组易于切换和替换的类&#xff0c;使得算法可以独立于其使用者进行变化。 原理 策略模式通过将具体的算法…

FastThreadLocal 快在哪里 ?

FastThreadLocal 快在哪里 &#xff1f; 引言FastThreadLocalset如何获取当前线程私有的InternalThreadLocalMap &#xff1f;如何知道当前线程使用到了哪些FastThreadLocal实例 ? get垃圾回收 小结 引言 FastThreadLocal 是 Netty 中造的一个轮子&#xff0c;那么为什么放着…

前端到底有多卷?可以转行吗?

我前几天招人&#xff0c;前后端各招一个人。 后端一天大概60多个投简历的。 前端岗位发出去&#xff0c;我吃了个饭&#xff0c;1小时回来 收到300多份简历…… 是一位HR回复的前端卷到什么程度的回答&#xff01; 下面我们来看两组官方纰漏的数据&#xff1a; 2023届全国高…

Git 学习笔记 | Git 的简介与历史

Git 学习笔记 | Git 的简介与历史 Git 学习笔记 | Git 的简介与历史Git 简介Git 历史 Git 学习笔记 | Git 的简介与历史 Git 简介 Git是分布式版本控制系统&#xff08;Distributed Version Control System&#xff0c;简称 DVCS&#xff09;&#xff0c;分为两种类型的仓库&…

100M跨境电商服务器能同时容纳多少人访问?

​  随着“出国”“出海”需求的业务量增多&#xff0c;网络的不断发展&#xff0c;服务商开始在带宽资源配备上作出各种改进。无论是纯国际带宽还是优化回国带宽租用&#xff0c;我们都可以独享&#xff0c;并且享受到大带宽。一般&#xff0c;做跨境电商业务的群体&#xf…

黑客都是土豪吗?真实情况是什么?

黑客的利益链条真的这么大这么好么,连最外围的都可以靠信息不对称赚普通人大学毕业上班族想都不敢想的金钱数目,黑客们是不是基本都是土豪 网络技术可以称为黑客程度的技术是不是真的很吃香&#xff1f;如果大部分大学生的智力资源都用在学习网络技术&#xff0c;会不会出现僧…

如何杜绝聊天泄密事件的发生呢(企业如何管理通讯工具,防止员工聊天泄密)

在现代企业中&#xff0c;员工之间的沟通是必不可少的。然而&#xff0c;随着科技的发展&#xff0c;员工聊天泄密的风险也日益增加。企业需要采取一系列措施来防止员工聊天泄密&#xff0c;以保护企业的核心竞争力和商业机密。本文将介绍一些有效的防止员工聊天泄密的方法。 1…