zoukankan      html  css  js  c++  java
  • CMU-Multimodal SDK Version 1.1 (mmsdk)使用方法总结

    20191026日 星期六

         

    • mmdatasdk: module for downloading and procesing multimodal datasets using computational sequences.
    • mmmodelsdk: tools to utilize complex neural models as well as layers for building new models. The fusion models in prior papers will be released here.

         

    1. mmdatasdk

    将每个数据集看成是可计算的序列,每个序列包含一个模态的数据(以分层结构存储)

    关于csd格式文件(csd = computational sequential data):

    • 两个主要元素(key elements)
      • data:特征,根据video id等进行分类
        • 每个多模态数据源关联两个矩阵:特征和时间(timestamp),特征和时间矩阵都是numpy 2d array
      • metadata:完整性和版本信息
    • 存储在hdf5对象中

    本例中,csd文件中存储了提取出来的特征(用于可以将提取出来的特征进行分享)

         

    1. 步骤:

    Step1 下载

    Step2 对齐(下载的数据频率可能不一样)

    sometimes the data needs to be aligned

    Code 1>>>获取情感态度标签(label) cmumosi_highlevel.add_computational_sequences(mmdatasdk.cmu_mosi.labels,'cmumosi/')

    Code 2>>> 使everything对齐

    cmumosi_highlevel.align('Opinion Segment Labels')

    举例:

    对于视频模态的数据v0,用v0[2]来表示视频的第三段

         

    1. 单词级别的对齐:word level alignment

    >>> from mmsdk import mmdatasdk
    >>> cmumosi_highlevel=mmdatasdk.mmdataset(mmdatasdk.cmu_mosi.highlevel,'cmumosi/')
    >>> cmumosi_highlevel.align('glove_vectors',collapse_functions=[myavg])
    >>> cmumosi_highlevel.add_computational_sequences(mmdatasdk.cmu_mosi.labels,'cmumosi/')
    >>> cmumosi_highlevel.align('Opinion Segment Labels')

         

    From <https://github.com/A2Zadeh/CMU-MultimodalSDK>

    Align function:对齐函数,接受两个值:时间和特征(也就是前边的两个矩阵)

    cmumosi_highlevel.align('glove_vectors',collapse_functions=[myavg])可以接受多个函数作为参数,这时将各个函数分别执行并将结果拼接

         

    1. 特征提取:

    使用glove

         

    1. 数据集的数据结构分析

         

    数据集结构(逻辑结构)

         

    存储结构:

         

    1. 查看数值的方法:

    print(dataset[text_field]['5W7Z1C_fDaE[9]']['features'])

    输出

    [[b'its']
    [b'completely']
    [b'different']
    [b'from']
    [b'anything']
    [b'sp']
    [b'weve']
    [b'ever']
    [b'seen']
    [b'him']
    [b'do']
    [b'before']]

         

    print(dataset[label_field]['5W7Z1C_fDaE[10]']['intervals'])

    输出

    [[32.239227 34.50408 ]]

    (时间戳的起止点)

         

    1. 如何用HDF5格式表达多模态数据?

    Pivot modality:核心模态

    不同模态数据的采样频率不一样,需要对齐到pivot modality上,通常情况下,对齐到words

    对齐的办法:使用collapse函数

    将不同模态数据按主要模态的时间轴进行分组,然后collapse函数将其进行池化

         

    ATTN:本SDK将collapse函数应用到所有模态,但是Word模态无法求均值,因此需要一个try:except,捕获文本求均值产生的异常

         

    1. 读取数据样式:

    dataset=md.mmdataset(recipe)

    dataset变量结构如下:

         

    其中,'CMU_MOSI_ModifiedTimestampedWords' 模态的数据格式如下:

         

    data里边存储了文本数据及其时间戳:

         

    第一个维度:

    对于一个batch(也就是变量train、变量test)来说,5个维度的含义如下:

    print(batch[0].shape)

    #wordvectors,paddedtomaxlen

    print(batch[1].shape)

    #visualfeatures

    print(batch[2].shape)

    #acousticfeatures

    print(batch[3])

    #labels

    print(batch[4])

    #lengths

         

    rain_loader = DataLoader(train, shuffle=False, batch_size=batch_sz, collate_fn=multi_collate)

    上述四个变量,在训练中通过train_loader赋值给train_iter,再划分成每轮次循环中的batch

         

    在文件train.py中:

        for batch in train_iter:

            model.zero_grad()

            t, v, a, y, l = batch

            batch_size = t.size(0)

    t,v,a,y,l=batch

    # t,v,a,y,l中存储了一个batchsize中的所有数据

         

    使用MOSI数据集,第一个batchsize之后,tval的维度如下:

    t: [33, 56]

    v: [33, 56, 47]

    a: [33, 56, 74]

    l: [56]

         

    第二个batchsize之后,tval的维度如下:

    t: [42, 56]

    v: [42, 56, 47]

    a: [42, 56, 74]

    l: [56]

         

    最后一个batchsize之后,上述变量的维度如下:

    t: [59, 49]

    v: [59, 49, 47]

    a: [59, 49, 74]

    l: [49]

         

    debug模式下对上述y变量进行inspect,得到结果如下:

         

    且有len(y) == 168

         

    1. 对上述数据的分析:

      由于batchsize = 56

      Dataloader的batchsize = batchsize * 3,因此len(y) == 168

         

    划分batch之后,train_loader内保存了dataset的一部分,也按照上边的顺序保存

    例如:

    train_loader.dataset[0]的返回结果表示一整条多模态数据

         

         

         

    1. 数据的物理含义:

    train_loader.dataset[0]以及train_loader.dataset[1]等:

    • train_loader.dataset的第一个维度表示数据条数,对应一段视频中的文本声音图像及其label

    train_loader.dataset[0][0]中存储了三种模态的数据(文本声音图像)

    train_loader.dataset[0][1]中存储了label(情感标签)

    train_loader.dataset[0][2]中存储了视频对应的字符串(视频文件名)

         

    ATTN

    train_loader.dataset[0][0]是一个list,list中有三个元素,是三个array,表示三种模态的数据

    例如train_loader.dataset[67][2]返回:

    Out[12]: u'Oz06ZWiO20M[22]'

         

    1. 多模态数据的获取方式:

    train_loader.dataset[0][0][0]是wordvector(是一个array)

    train_loader.dataset[0][0][1]是visual feature(是一个array)

    train_loader.dataset[0][0][2]是acoustic feature(是一个array)

    上述三个array构成了一个list

         

    1. 总结:

    • train_loader.dataset是一个list
    • train_loader.dataset[0]或train_loader.dataset[99]等,是tuple(三元组),三元组由两个array和一个字符串构成
      • train_loader.dataset[0][0]中存储了三种模态的数据(文本声音图像),是一个tuple
        • train_loader.dataset[0][0][0]是一个ndarray,表示word vector,一个值对应说话人说的一个单词
        • train_loader.dataset[0][0][1]表示视觉信号ndarray,其列数等于视觉信号提取出来的特征维度(47),其行数等于说话人说的单词数
        • train_loader.dataset[0][0][2]表示听觉信号ndarray,其列数等于听觉信号提取出来的特征维度(74),其行数等于说话人说的单词数
      • train_loader.dataset[0][1]中存储了label(情感标签),是ndarray
      • train_loader.dataset[0][2]中存储了视频对应的字符串(视频文件名)

         

    1. 对各个维度的分析:

    wordvector的维度比较低,通常少于10维

    visual feature和acoustic feature在对齐之后含有多个array(本例中,每个音视频array有46维长度)

    即:

    train_loader.dataset[78][0][2]表示音频模态数据,但是这个数据包括14个特征向量(其他样本可能包含不同数值)

         

    相当于以下14个tensor,每个tensor有46维:

    train_loader.dataset[78][0][2][0]

    ... ...

    train_loader.dataset[78][0][2][13]

         

    总结:

    MOSI数据集是语素级的,以数据集中编号为'8qrpnFRGt2A'的视频的第15小段为例,该段视频中人物说了14个字(word),因此对应的另外两种模态中,有14个array,验证方法是:

         

    如图,train_loader.dataset[78][0][2].__len__()==14,因此说明语素级别上数据集是对齐的

    在数据集中可以查找到对应的这句话

    [['it']

    ['fell']

    ['like']

    ['i']

    ['was']

    ['watching']

    ['one']

    ['of']

    ['those']

    ['army']

    ['of']

    ['one']

    ['commercials']

    ['sometimes']]

         

    对应的情感标签:

         

         

    1. 网络的训练流程:

    在trainloader的基础上,新建一个`train_iter` 变量如下

    train_iter=tqdm_notebook(train_loader)

    train_iter增加了sample的功能

    事实上,train_iter就是train_loader的基础上增加了进度条功能

    sample的方法使用的是pyTorch中的dataloader

         

    _________________________

    1. 补充1

    collate函数是pytorch中用Dataloader来处理数据集的概念,而不是多模态处理中的概念

    collate取"拼接"之意

    defmulti_collate(batch):

         

    这个函数对一个batch的数据进行拼接

    把batch[1]取出来作为label(就是y)

    batch[0][0]取出来作为文本模态(就是t

    batch[0][1]以及batch[0][2]取出来作为视觉和音频模态(就是v和a,多维tensor)

    返回值是:

    returnsentences,visual,acoustic,labels,lengths

         

    ————————————————————

    1. 补充2

    数据集中共有1281条数据,即:

    X_train_l.__len__()==1281

    问题:最后整理出来的每个batch下的t,v,a,y,l进行拼接,得到1281条y和1281条l,但是v,a,t却只有1014条

    debug模式下,发现在某一轮batch循环中,batchsize=56,有:

    y.__len__() == l.__len__() == 56,

    但是a,v,t的长度却是32

         

    进一步分析a,v,t的维度,有:

    In[14]: a.shape

    Out[14]: torch.Size([48, 56, 74])

    In[15]: v.shape

    Out[15]: torch.Size([48, 56, 47])

    因此,上边a,v,t的length和y,l的length不一样,其原因在于:代码中拼接a,v,t时选错了维度

    解决方案:

    需要将a,v,t的前两个维度互换位置

    t=list(np.array(t).transpose((1,0)))

    第一步:torch.tensor转换成ndarray

    第二步:ndarray前两维互换

    第三步:转换成list

    ATTN:

    如果使用list(array1)的形式,则只将最外层转换成list,里边还是array

    如果使用array1.tolist()方法,则整个array的每一层都变成了list

         

    1. 补充3

    在第一个batch中,将t,v,a,y,l转换成ndarray之后的shape如下:

    t的shape为(40,56)

    v的shape为(40,56,47)

    a的shape为(40,56,74)

    y的shape为(56,1)

    l的shape为(56,)

         

    此时的ndarray的各个轴进行过变换

    第二维(56)表示batchsize

    第一维表示语素的个数(单词数)

    第三维表示模态特征(应作为X_train的一行,进行拼接)

         

    整理数据的代码:

    forbatchintrain_iter:

    #batch=list(batch)

    #X_train_tmp=X_train_tmp+batch

    t,v,a,y,l=batch

         

    t=list(np.array(t).transpose((1,0)))

    v=list(np.array(v).transpose((1,0,2)))

    a=list(np.array(a).transpose((1,0,2)))

    y=list(np.array(y))

    l=list(np.array(l).reshape((-1,1)))

    ifcnt==0:

    X_train_t=t

    X_train_v=v

    X_train_a=a

    Y_train=y

    X_train_l=l

    cnt+=1

    else:

    X_train_t+=t

    X_train_v+=v

    X_train_a+=a

    Y_train+=y

    X_train_l+=l

    cnt+=1

         

    上述代码之后:

    X_train_a是一个list(len==1281),每个元素是一个array,每个array的shape是(40, 74)

    X_train_a[0].shape

    Out[3]: (40, 74)

    其中,40是语素的个数,74是提取的特征数

  • 相关阅读:
    万恶的"unrecognized selector sent to instance"颤抖吧
    QT 中 QGLWidget 不能够嵌入到 QGraphicsView 中及解决方案
    程序代码里的幽默精神
    objectivec 中如何使用 c++?
    基于FPGA的跨时钟域信号处理——同步设计的重要
    亚稳态
    行为级和RTL级的区别
    FPGA同步复位,异步复位以及异步复位同步释放实例分析
    基于FPGA的跨时钟域信号处理——专用握手信号
    FPGA中亚稳态——让你无处可逃
  • 原文地址:https://www.cnblogs.com/sddai/p/11743582.html
Copyright © 2011-2022 走看看