2019年10月26日 星期六git
將每一個數據集當作是可計算的序列,每一個序列包含一個模態的數據(以分層結構存儲) github
Step1 下載 網絡
Step2 對齊(下載的數據頻率可能不同) 數據結構
sometimes the data needs to be aligned ide
Code 1>>>獲取情感態度標籤(label) cmumosi_highlevel.add_computational_sequences(mmdatasdk.cmu_mosi.labels,'cmumosi/')函數
Code 2>>> 使everything對齊ui
cmumosi_highlevel.align('Opinion Segment Labels') spa
舉例: debug
對於視頻模態的數據v0,用v0[2]來表示視頻的第三段 3d
>>> 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])能夠接受多個函數做爲參數,這時將各個函數分別執行並將結果拼接
使用glove
數據集結構(邏輯結構)
存儲結構:
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 ]]
(時間戳的起止點)
Pivot modality:核心模態
不一樣模態數據的採樣頻率不同,須要對齊到pivot modality上,一般狀況下,對齊到words
對齊的辦法:使用collapse函數
將不一樣模態數據按主要模態的時間軸進行分組,而後collapse函數將其進行池化
ATTN:本SDK將collapse函數應用到全部模態,可是Word模態沒法求均值,所以須要一個try:except,捕獲文本求均值產生的異常
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.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
因爲batchsize = 56
Dataloader的batchsize = batchsize * 3,所以len(y) == 168
劃分batch以後,train_loader內保存了dataset的一部分,也按照上邊的順序保存
例如:
train_loader.dataset[0]的返回結果表示一整條多模態數據
train_loader.dataset[0]以及train_loader.dataset[1]等:
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]'
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
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']]
對應的情感標籤:
在trainloader的基礎上,新建一個`train_iter` 變量以下
train_iter=tqdm_notebook(train_loader)
train_iter增長了sample的功能
事實上,train_iter就是train_loader的基礎上增長了進度條功能
sample的方法使用的是pyTorch中的dataloader
_________________________
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
————————————————————
數據集中共有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
在第一個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是提取的特徵數