資源簡介
在日常的生活中我們最經常使用的距離毫無疑問應該是歐式距離,但是對于一些特殊情況,歐氏距離存在著其很明顯的缺陷,比如說時間序列,舉個比較簡單的例子,序列A:1,1,1,10,2,3,序列B:1,1,1,2,10,3,如果用歐氏距離,也就是distance[i][j]=(b[j]-a[i])*(b[j]-a[i])來計算的話,總的距離和應該是128,應該說這個距離是非常大的,而實際上這個序列的圖像是十分相似的,這種情況下就有人開始考慮尋找新的時間序列距離的計算方法,然后提出了DTW算法,這種方法在語音識別,機器學習方便有著很重要的作用。
這個算法是基于動態規劃(DP)的思想,解決了發音長短不一的模板匹配問題,簡單來說,就是通過構建一個鄰接矩陣,尋找最短路徑和。
還以上面的2個序列作為例子,A中的10和B中的2對應以及A中的2和B中的10對應的時候,distance[3]以及distance[4]肯定是非常大的,這就直接導致了最后距離和的膨脹,這種時候,我們需要來調整下時間序列,如果我們讓A中的10和B中的10 對應 ,A中的1和B中的2對應,那么最后的距離和就將大大縮短,這種方式可以看做是一種時間扭曲,看到這里的時候,我相信應該會有人提出來,為什么不能使用A中的2與B中的2對應的問題,那樣的話距離和肯定是0了啊,距離應該是最小的吧,但這種情況是不允許的,因為A中的10是發生在2的前面,而B中的2則發生在10的前面,如果對應方式交叉的話會導致時間上的混亂,不符合因果關系。
接下來,以output[6][6](所有的記錄下標從1開始,開始的時候全部置0)記錄A,B之間的DTW距離,簡單的介紹一下具體的算法,這個算法其實就是一個簡單的DP,狀態轉移公式是output[i] [j]=Min(Min(output[i-1][j],output[i][j-1]),output[i-1][j-1])+distance[i] [j];最后得到的output[5][5]就是我們所需要的DTW距離.
代碼片段和文件信息
#include?
#include?
#include?
#define?VERY_BIG??(1e30)
/*?dtw.c?*/
/*?VERSION?2.0?Andrew?Slater?20/8/1999?*/
/*?Latest?changes?3/2006?by?John?Coleman?*/
/*?DEscriptION?*/
/*?Compute?a?distance?matrix?on?2?multi-parameter?vectors?from?2?utterances
???and?perform?dynamic?time?warping?on?the?distance?matrix?*/
/*?INPUT:?*/
/*?Two?ASCII?parameter?files?of?the?format:
???filex:
???X1a???X1b?...?X1n
???X2a???X2b?...?X2n
???...
???filey:
???Y1a???Y1b?...?Y1n
???Y2a???Y2b?...?Y2n
???...
where?a?b?...?n?are?parameters?(e.g.?f0?tongue-tip?x?co-ordinate)
??????1?...?n?is?a?time?series
??????X?and?Y?are?2?utterances
Distance?is?calculated?as:
???Dist[x1][y1]?=?(X1a?-?Y1a)^2?+?(X1b?-?Y1b)^2?+?...?+?(X1n?-?Y1n)^2?etc.
*/
/*?OUTPUTS:?*/
/*?output?file:?best?alignment?of?the?2?parameter?files?*/
/*?glob:?sum?of?global?distances?useful?as?a?similarity?measure?*/
int?main(argc?argv)
int?argc;
char?*argv[];
{
double?**globdist;
double?**Dist;
double?top?mid?bot?cheapest?total;
unsigned?short?int?**move;
unsigned?short?int?**warp;
unsigned?short?int?**temp;
unsigned?int?I?X?Y?n?i?j?k;
unsigned?int?xsize?=?atoi(argv[4]);
unsigned?int?ysize?=?atoi(argv[5]);
unsigned?int?params?=?atoi(argv[6]);
unsigned?int?debug;?/*?debug?flag?*/
float?**x?**y;?/*now?2?dimensional*/
FILE?*file1?*file2?*glob?*debug_file?*output_file;
if?(argc?<7?||?argc?>?8)
{fprintf(stderr“Usage:?dtw?infile1?infile2?outfile?xsize?ysize?params?[debug_file]\n“);
?exit(1);
}
?if?(argc?==?8)
???{
?????/*?open?debug?file?*/
?????if?((debug_file?=?fopen(argv[7]“wb“))?==?NULL)
???????{fprintf(stderr“Cannot?open?debug?file\n“);
???????exit(1);
???????}
?????debug?=?1;
???}
?/*?open?x-parameter?file?*/
if?((file1=fopen(argv[1]“rb“))==NULL)
{fprintf(stderr“File?%s?cannot?be?opened\n“argv[1]);
exit(1);
}
/*?open?y-parameter?file?*/
if?((file2=fopen(argv[2]“rb“))==NULL)
{fprintf(stderr“File?%s?cannot?be?opened\n“argv[2]);
exit(1);
}
if?(debug==1)?fprintf(debug_file“xsize?%d?ysize?%d?params?%d\n“xsizeysizeparams);
/*?allocate?memory?for?x?and?y?matrices?*/
if?((x?=?malloc(xsize?*?sizeof(float?*)))?==?NULL)
?????fprintf(stderr“Memory?allocation?error?(x)\n“);
for?(i=0;?i??????if?((x[i]?=?malloc(params?*?sizeof(float)))?==?NULL)
?????fprintf(stderr“Memory?allocation?error?(x)\n“);
if?((y?=?malloc(ysize?*?sizeof(float?*)))?==?NULL)
?????fprintf(stderr“Memory?allocation?error?(y)\n“);
for?(i=0;?i??????if?((y[i]?=?malloc(params?*?sizeof(float)))?==?NULL)
?????fprintf(stderr“Memory?allocation?error?(y)\n“);
?????/*?allocate?memory?for?Dist?*/
if?((Dist?=?malloc(xsize?*?sizeof(double?*)))?==?NULL)
?????fprintf(stderr“Memory?allocation?error?(Dist)\n“);
for?(i=0;?i?if?((Dist[i]?=?malloc(ysize?*?sizeof(double)))?==?NULL)
?????fprintf(stderr“Memory?allocation?error?(Dist)\n“);
?????/*?allocate?memory?for?globdist?*/
if?((globdist?=?malloc(xsize?*?sizeof(double?*)))?==?NULL)
??
- 上一篇:用STM32驅動的4*4行列矩陣鍵盤
- 下一篇:EDA365_Skill_V2.5
評論
共有 條評論