DHMM_WP.cpp
上传用户:avbj512
上传日期:2013-09-18
资源大小:6239k
文件大小:11k
源码类别:

DSP编程

开发平台:

Visual C++

  1. // DHMM_WP.cpp:
  2. // Implementation of the DHMM_WP Module.
  3. // That is the transform of previous DHMM Code by WangPeng.
  4. //
  5. // Created 2001/08, By WangPeng, MDSR.
  6. //
  7. //////////////////////////////////////////////////////////////////////
  8. #include "stdafx.h"
  9. #include "DHMM_WP.h"
  10. #define KMEAN_LOOP_TIME 40
  11. //////////////////////////////////////////////////////////////////////
  12. // Private functions
  13. void kmean(
  14. double * v,
  15. double * CodeBook,
  16. int nTotalFrameNum,
  17. int nCodeBookSize,
  18. int n_feature_order
  19. );
  20. //////////////////////////////////////////////////////////////////////
  21. // API functions
  22. int DHMM_VQ_Train_Code_Book_WP(
  23. DYNA_2DIM_DOUBLE_ARRAY d2dda_train_vector,
  24. int n_train_vector_num,
  25. int n_code_word_dim,
  26. DYNA_2DIM_DOUBLE_ARRAY d2dda_initial_codebook, // 如果该指针为NULL,则随机
  27. // 初始化码本,否则利用该参
  28. // 作为初始码本
  29. DYNA_2DIM_DOUBLE_ARRAY d2dda_codebook,
  30. int n_codebook_size
  31. )
  32. {
  33. double* pd_v; // 一维动态数组形式的训练向量集
  34. double* pd_codebook; // 一维动态数组形式的码本
  35. int i, j, n_temp;
  36. int* pn_codeword_frame_index; // 随机初始化码本时,每个码本在训练向量集中的标号
  37. int n_codeword_equal_flag; // 随机初始化码本时,两个码本相同的标志
  38. PRO_LOG("tVQ = WP, K-mean loop time = %4d.n", KMEAN_LOOP_TIME);
  39. if((pd_v = (double*)new double[n_train_vector_num * n_code_word_dim]) == NULL)
  40. {
  41. DEBUG_PRINTF("Allocation of memory for train vectors failed!n");
  42. ASSERT(0);
  43. }
  44. if((pd_codebook = (double*)new double[n_codebook_size * n_code_word_dim]) == NULL)
  45. {
  46. DEBUG_PRINTF("Allocation of memory for codebook failed!n");
  47. ASSERT(0);
  48. }
  49. // 因为kmean的训练向量参数集v是一维动态数组,因此要把二维数组拷贝到一维数组中
  50. for(i=0;i<n_train_vector_num;i++)
  51. memcpy(pd_v + i * n_code_word_dim, d2dda_train_vector[i], n_code_word_dim * sizeof(double));
  52. // 若码本d2dda_codebook不为空,则把二维数组表示的码本拷贝到一维数组中
  53. if(d2dda_initial_codebook != NULL)
  54. {
  55. for(i=0;i<n_codebook_size;i++)
  56. memcpy(pd_codebook + i * n_code_word_dim, d2dda_initial_codebook[i], n_code_word_dim * sizeof(double));
  57. }
  58. // 若码本d2dda_codebook为空,则随机初始化码本
  59. else
  60. {
  61. pn_codeword_frame_index=(int *)new int[n_codebook_size];
  62. // srand( (unsigned)time( NULL ) );
  63. for(i=0;i<n_codebook_size;i++){
  64. if(i==0){
  65. n_temp=(int)((double)n_train_vector_num * ((double)rand() / (double)RAND_MAX));
  66. pn_codeword_frame_index[i]=n_temp;
  67. }
  68. else{
  69. n_codeword_equal_flag = 1;
  70. while(n_codeword_equal_flag == 1){
  71. pn_codeword_frame_index[i] = n_temp = (int)((double)n_train_vector_num * ((double)rand() / (double)RAND_MAX));
  72. n_codeword_equal_flag = 0;
  73. for(j=i-1;j>=0;j--){
  74. if(n_temp == pn_codeword_frame_index[j])
  75. n_codeword_equal_flag = 1;
  76. }
  77. }
  78. }
  79. memcpy(pd_codebook + i * n_code_word_dim, pd_v + n_temp * n_code_word_dim, n_code_word_dim * sizeof(double));
  80. }
  81. }
  82. kmean(
  83. pd_v,
  84. pd_codebook,
  85. n_train_vector_num,
  86. n_codebook_size,
  87. n_code_word_dim
  88. );
  89. for(i=0;i<n_codebook_size;i++)
  90. {
  91. memcpy(d2dda_codebook[i], pd_codebook + i * n_code_word_dim, n_code_word_dim * sizeof(double));
  92. }
  93. delete pd_v;
  94. delete pd_codebook;
  95. delete pn_codeword_frame_index;
  96. return 0;
  97. }
  98. static void kmean(
  99. double * v, // 用于训练码本的特征向量集
  100. double * CodeBook, // 码本
  101. int nTotalFrameNum, // 训练向量总数
  102. int nCodeBookSize, // 码本大小(码字个数)
  103. int n_feature_order // 特征(训练向量)维数
  104. )
  105. {
  106. int i,j,k,nTrainCount;
  107. int nTrainMode; // nTrainMode=0: initialize code book randomly
  108. // nTrainMode=1: initialize code book from old codebook
  109. double fTemp;
  110. double fMinDistance; // minimum of the distances between an training vector frame and all the code words
  111. double * fSumDistance; // sum of the distances between an training vector frame and all the code words
  112. double * fMeanFrame; // mean frame feature of all the frames whose minimum reach at the same code word
  113. int nWordClassFrameNum; // number of frames whose minimum distances reach at the same code word
  114. double fDistance; // distance between every frame of the training vectors and the current code words
  115. double * OldCodeBook; // codebook in last iteration
  116. double fCodeBookDistance; // code book distance between two consecutive iteration
  117. double fTotalDistortion; // sum of each training vector's quantization distortion
  118. double fAvgDistortion; // average quantization distortion
  119. int * nNearestWordIndex; // each training vector frame's nearest nearest code word's index
  120. int nFlagFeatureEqual; // 0: two feature vectors don't equal, 1: two feature vectors equal
  121. int nRandFrameIndex; // randomly chosen index of frame feature vector to update code word
  122. nNearestWordIndex=(int *)new int[nTotalFrameNum];
  123. OldCodeBook=(double *)new double[nCodeBookSize*n_feature_order];
  124. fSumDistance=(double *)new double[nCodeBookSize];
  125. fMeanFrame=(double *)new double[n_feature_order];
  126. memset(fSumDistance, 0, nCodeBookSize * sizeof(double));
  127. if(CodeBook != NULL)
  128. nTrainMode = 1;
  129. else
  130. nTrainMode = 0;
  131. ASSERT(nTrainMode == 1);
  132. // train code book
  133. if(nTrainMode==1){ // initialize code book from old codebook
  134. for(nTrainCount = 0; nTrainCount < KMEAN_LOOP_TIME; nTrainCount++){
  135. // save code book in last iteration
  136. memcpy(OldCodeBook, CodeBook, nCodeBookSize*n_feature_order*sizeof(double));
  137. printf("Training round: %dn", nTrainCount);
  138. // calculate distances between training vectors and code words and the min-distance code word index
  139. fAvgDistortion=fTotalDistortion=0.0F;
  140. for(i=0;i<nTotalFrameNum;i++){
  141. for(j=0;j<nCodeBookSize;j++){
  142. fDistance = 0.0F;
  143. for(k=0;k<n_feature_order;k++){
  144. fTemp = (*(v+i*n_feature_order+k)) - *(CodeBook+j*n_feature_order+k);
  145. fDistance += fTemp * fTemp;
  146. }
  147. if(j==0){
  148. fMinDistance = fDistance;
  149. *(nNearestWordIndex+i) = 0;
  150. }
  151. else{
  152. if( fDistance < fMinDistance ){
  153. fMinDistance = fDistance;
  154. *(nNearestWordIndex+i) = j;
  155. }
  156. }
  157. }
  158. fTotalDistortion += fMinDistance;
  159. fSumDistance[*(nNearestWordIndex+i)] += fMinDistance;
  160. }
  161. fAvgDistortion = fTotalDistortion/(double)nTotalFrameNum;
  162. DEBUG_PRINTF("Last round's average distortion: %-10fn", fAvgDistortion);
  163. // update code words
  164. // srand( (unsigned)time( NULL ) );
  165. for(i=0;i<nCodeBookSize;i++){
  166. nWordClassFrameNum=1;
  167. //memcpy(fMeanFrame, CodeBook+i*FEATURE_ORDER, FEATURE_ORDER*sizeof(double));
  168. memset(fMeanFrame, 0, n_feature_order*sizeof(double));
  169. for(j=0;j<nTotalFrameNum;j++){
  170. if( *(nNearestWordIndex+j) == i ){
  171. for(k=0;k<n_feature_order;k++)
  172. fMeanFrame[k] += (*(v+j*n_feature_order+k));
  173. nWordClassFrameNum++;
  174. }
  175. }
  176. // use mean vector to update code word
  177. if( nWordClassFrameNum>1 )
  178. for(k=0;k<n_feature_order;k++){
  179. fMeanFrame[k] /= (nWordClassFrameNum-1);
  180. *(CodeBook+i*n_feature_order+k) = fMeanFrame[k];
  181. }
  182. // use random vector outside the code book to replace the code word
  183. if( (nWordClassFrameNum==2 && fSumDistance[i] == 0) || nWordClassFrameNum==1 ){
  184. nFlagFeatureEqual=1;
  185. while( nFlagFeatureEqual==1 ){
  186. nRandFrameIndex = (int)((double)nTotalFrameNum * ((double)rand() / (double)RAND_MAX));
  187. for(j=0;j<nCodeBookSize;j++){
  188. for(k=0;k<n_feature_order;k++){
  189. if( *(CodeBook+j*n_feature_order+k) - (*(v+nRandFrameIndex*n_feature_order+k)) !=0 ){
  190. nFlagFeatureEqual=0;
  191. break;
  192. }
  193. }
  194. if( nFlagFeatureEqual==0 )
  195. break;
  196. }
  197. }
  198. memcpy(CodeBook+i*n_feature_order, v+nRandFrameIndex*n_feature_order, n_feature_order*sizeof(double));
  199. }
  200. }
  201. // calculate code book distance between this and last iteration
  202. fCodeBookDistance=0.0;
  203. for(i=0;i<nCodeBookSize;i++){
  204. for(j=0;j<n_feature_order;j++){
  205. fTemp = *(CodeBook+i*n_feature_order+j) - (*(OldCodeBook+i*n_feature_order+j));
  206. fCodeBookDistance += fTemp * fTemp;
  207. }
  208. }
  209. DEBUG_PRINTF("change of code book: %-10fn", fCodeBookDistance);
  210. } // end of:  for(nTrainCount=0;nTrainCount<40;nTrainCount++)
  211. } // end of: if(nTrainMode=1)
  212. PRO_LOG("tLast round's average distortion: %-10fn", fAvgDistortion);
  213. PRO_LOG("tchange of code book: %-10fn", fCodeBookDistance);
  214. /*
  215. else if(nTrainMode==0){ // initialize code book randomly
  216. nTrainCount=0;
  217. fCodeBookDistance=1.0;
  218. while(fCodeBookDistance>1.0e-3){
  219. // save code book in last iteration
  220. memcpy(OldCodeBook, CodeBook, nCodeBookSize*n_feature_order*sizeof(double));
  221. printf("Training round: %dn", nTrainCount);
  222. // calculate distances between training vectors and code words and the min-distance code word index
  223. fAvgDistortion=fTotalDistortion=0.0;
  224. for(i=0;i<nTotalFrameNum;i++){
  225. for(j=0;j<nCodeBookSize;j++){
  226. fDistance = 0.0;
  227. for(k=0;k<n_feature_order;k++){
  228. fTemp = (*(v+i*n_feature_order+k)) - *(CodeBook+j*n_feature_order+k);
  229. fDistance += fTemp * fTemp;
  230. }
  231. if(j==0){
  232. fMinDistance = fDistance;
  233. *(nNearestWordIndex+i) = 0;
  234. }
  235. else{
  236. if( fDistance < fMinDistance ){
  237. fMinDistance = fDistance;
  238. *(nNearestWordIndex+i) = j;
  239. }
  240. }
  241. }
  242. fTotalDistortion += fMinDistance;
  243. fSumDistance[*(nNearestWordIndex)] += fMinDistance;
  244. }
  245. fAvgDistortion = fTotalDistortion/(double)nTotalFrameNum;
  246. printf("Last round's average distortion: %-10fn", fAvgDistortion);
  247. // update code words
  248. srand( (unsigned)time( NULL ) );
  249. for(i=0;i<nCodeBookSize;i++){
  250. nWordClassFrameNum=1;
  251. memset(fMeanFrame, 0, n_feature_order*sizeof(double));
  252. for(j=0;j<nTotalFrameNum;j++){
  253. if( *(nNearestWordIndex+j) == i ){
  254. for(k=0;k<n_feature_order;k++)
  255. fMeanFrame[k] += (*(v+j*n_feature_order+k));
  256. nWordClassFrameNum++;
  257. }
  258. }
  259. // use mean vector to update code word
  260. if( nWordClassFrameNum>1 )
  261. for(k=0;k<n_feature_order;k++){
  262. fMeanFrame[k] /= (nWordClassFrameNum-1);
  263. *(CodeBook+i*n_feature_order+k) = fMeanFrame[k];
  264. }
  265. // use random vector outside the code book to replace the code word
  266. if( (nWordClassFrameNum==2 && fSumDistance[i] == 0) || nWordClassFrameNum==1 ){
  267. nFlagFeatureEqual=1;
  268. while( nFlagFeatureEqual==1 ){
  269. nRandFrameIndex = (int)((double)nTotalFrameNum * ((double)rand() / (double)RAND_MAX));
  270. for(j=0;j<nCodeBookSize;j++){
  271. for(k=0;k<n_feature_order;k++){
  272. if( *(CodeBook+j*n_feature_order+k) - (*(v+nRandFrameIndex*n_feature_order+k)) !=0 ){
  273. nFlagFeatureEqual=0;
  274. break;
  275. }
  276. }
  277. if( nFlagFeatureEqual==0 )
  278. break;
  279. }
  280. }
  281. memcpy(CodeBook+i*n_feature_order, v+nRandFrameIndex*n_feature_order, n_feature_order*sizeof(double));
  282. }
  283. }
  284. // calculate code book distance between this and last iteration
  285. fCodeBookDistance=0.0;
  286. for(i=0;i<nCodeBookSize;i++){
  287. for(j=0;j<n_feature_order;j++){
  288. fTemp = *(CodeBook+i*n_feature_order+j) - (*(OldCodeBook+i*n_feature_order+j));
  289. fCodeBookDistance += fTemp * fTemp;
  290. }
  291. }
  292. printf("change of code book: %-10fn", fCodeBookDistance);
  293. nTrainCount++;
  294. } // end of:  while(fCodeBookDistance>0){
  295. } // end of: else if(nTrainMode==0){
  296. */
  297. // release memory
  298. delete fMeanFrame;
  299. delete fSumDistance;
  300. delete nNearestWordIndex;
  301. delete OldCodeBook;
  302. }