c数组错误 – 期望元素被初始化,但它们不是,并且我的setter有时
我在创建一个二维数组并用值填充它然后读取数组并获得完全不同的值时遇到了麻烦.奇怪的是我有两个维护两个数组,其中一个是正确存储值,另一个不是.我很确定我也不会覆盖元素.我假设我犯了一些愚蠢的错误,对于那些对C不太可怕的人来说这是显而易见的.
请注意我正在实现viterbi algorithm,但是我理解并且有一个有效的python实现的一般算法,它只是c中的数组给我带来了悲伤. 我在做什么: 1)Malloc两个数组,它们用作2D数组,但我分配了一个连续的内存块.我没有明确地初始化数组,因为我应该填写其中的每个条目作为viterbi算法的前进步骤. double *viterbi_table = malloc(sizeof(double) * n_samples * n_states); int *best_path_table = malloc(sizeof(int) * n_samples * n_states); 2)对于维特比算法的前向部分,我浏览观察到的数据,并计算每个状态最可能的状态和概率. for (t = 1; t < n_samples; t++) // for each piece of observed data { for (i = 0; i < n_states; i++) { max_state_index = 0; max_p = -DBL_MAX; // calculate the max state and probability by looping through all the states // yada yada... // IMPORTANT PART: We set the array values here viterbi_table[t * n_samples + i] = max_p; best_path_table[t * n_samples + i] = max_state_index; printf("tbest_path_table[%d][%d] or [%d] = %d => %dn",i,t,t * n_samples + i,best_path_table[t * n_samples + i],max_state_index); } // IMPORTANT PART: print out rows of best path table to see if what we thought we inserted is in there if (debug) { printf("best_path,[ ",t); for (i = 0; i < n_states; i++) { printf("[%d],%d ",best_path_table[t * n_samples + i]); } printf("]n"); } } 3)我运行代码,而不是让我设置的数组元素与我认为我设置的数组相匹配,而是得到看起来像未初始化元素的大的负数或正数.是什么赋予了?我为这些块分配了一个值.这是显示问题的选定输出部分. t=36 => sample=X best_path_table[0][36] or [1404] = 0 => 0 best_path_table[1][36] or [1405] = 0 => 0 best_path_table[2][36] or [1406] = 0 => 0 best_path_table[3][36] or [1407] = 0 => 0 ... best_path,[ [1404],1399607453 [1405],-1070347604 [1406],1399607453 [1407],0 ... ] 通过对比,下面的一个是正确的. t=37 => sample=X best_path_table[0][37] or [1443] = 3 => 3 best_path_table[1][37] or [1444] = 3 => 3 best_path_table[2][37] or [1445] = 3 => 3 ... best_path,[ [1443],3 [1444],3 [1445],... ] 当我为一小段数据运行代码时,请说< 12观察,我没有这样的问题.当我运行它以获得更长的数据时,我的大多数最佳路径表未正确填充 - 看起来这样的模式是这样的: observation# 1) correct 2-3) garbage 4) correct 4-5) garbage and so on 码 见this gist.它与第三方库没有依赖关系. 编辑: 维特比表的第一行在算法的前向部分之前的步骤中初始化. for (i = 0; i < n_states; i++) { state_i = states[i]; sample_t = samples[0]; viterbi_table[i*n_samples] = prior(state_i,true) + emission(sample_t,state_i,true); } EDIT2: 在代码的先前版本中,我正在进行更标准的2D阵列初始化(在非连续块中)和相应的阵列访问.这给了我更大的输入数据总线错误,这完全有意义. double **viterbi_table = malloc(sizeof * viterbi_table * n_states); int **best_path_table = malloc(sizeof * best_path_table * n_states); ... viterbi_table[j][t - 1] = ... EDIT3,解决方案评论: 事实证明这是一个愚蠢的下标错误.维特比和最佳路径数组的大小为n_samples * n_states,即17 * 39 = 663.这可以排除任何1404的索引,如我的例子所示. 具体问题是我的数组索引很乱,因为我错误地使用了n_samples而不是n_states.对于给定的观察指数t(30)和给定的状态指数i(14),计算如下: // Original,wrong t * n_samples + i = 30 * 39 + 14 = 1184 // New,correct t * n_states + i = 30 * 17 + 14 = 524 变量t已经编码了我们所处的样本数,因此我们只需将其乘以状态数即可. EDIT4,固定代码: 解决方法
我使用assert添加了一个宏CHECK_SUBSCRIPT来检查下标是否在范围内.它解雇了 – 有一个失控的下标.
资源 评论已删除. #include <assert.h> #include <float.h> #include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #define CHECK_SUBSCRIPT(x,n_samples) assert((x) >= 0 && (x) < (n_samples) * n_states) typedef enum { false,true } bool; typedef double (*prob_function_def)(char,char,bool); int n_states = 17; int n_observations = 17; char states[17] = { 'X','0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; char observations[17] = { 'X','F'}; void viterbi_log ( char *samples,int n_samples,char *best_path,prob_function_def prior,prob_function_def transition,prob_function_def emission,bool debug ) { printf("nviterbi...n"); int i,j,max_state_index; char state_i,state_j,sample_t; double trans_p,max_p; double *viterbi_table = malloc(sizeof(double) * n_samples * n_states); int *best_path_table = malloc(sizeof(int) * n_samples * n_states); for (int n33 = 0; n33 < n_samples * n_states; n33++) { CHECK_SUBSCRIPT(n33,n_samples); viterbi_table[n33] = 3.14159; best_path_table[n33] = 314159; } if (debug) printf("nInitialization:n"); for (i = 0; i < n_states; i++) { state_i = states[i]; sample_t = samples[0]; CHECK_SUBSCRIPT(i*n_samples,n_samples); viterbi_table[i*n_samples] = prior(state_i,true); if (debug) { printf("t"); printf("log(prior[%c]) + log(emission[%c][%c]) = %en",sample_t,viterbi_table[i*n_samples]); } } if (debug) printf("nForward:n"); for (t = 1; t < n_samples; t++) { sample_t = samples[t]; if (debug) printf("t=%d => sample=%cn",sample_t); for (i = 0; i < n_states; i++) { state_i = states[i]; max_state_index = 0; max_p = -DBL_MAX; for (j = 0; j < n_states; j++) { state_j = states[j]; CHECK_SUBSCRIPT(((t-1)*n_samples)+j,n_samples); trans_p = viterbi_table[((t - 1) * n_samples) + j] + transition(state_i,true) + emission(sample_t,true); if (trans_p > max_p) { max_state_index = j; max_p = trans_p; } } CHECK_SUBSCRIPT(t*n_samples+i,n_samples); viterbi_table[t * n_samples + i] = max_p; best_path_table[t * n_samples + i] = max_state_index; printf("tbest_path_table[%d][%d] or [%d] = %d => %dn",max_state_index); } if (debug) { printf("best_path,[ "); for (i = 0; i < n_states; i++) { CHECK_SUBSCRIPT(t*n_samples+i,n_samples); printf("[%d],best_path_table[t * n_samples + i]); } printf("]n"); } } if (debug) { printf("nbest path table:n"); for (t = n_samples - 1; t > 0; t--) { printf("t=%d,t); for (i = 0; i < n_states; i++) { CHECK_SUBSCRIPT(t*n_samples+i,best_path_table[t * n_samples + i]); } printf("]n"); } } free(viterbi_table); free(best_path_table); } double prior_prob (char state_i,char state_j,bool log_prob) { if (!log_prob) return 0.25; else return -1.3862943611198906; } double transition_prob (char state_i,bool log_prob) { if (!log_prob) { if (state_i == 0 && state_j == 0) return 0.9; else if (state_i == 0 || state_j == 0) return 0.1; else if (state_i == state_j) return 0.9; else return 0.1; } else { if (state_i == 0 && state_j == 0) return -0.10536051565782628; else if (state_i == 0 || state_j == 0) return -2.3025850929940455; else if (state_i == state_j) return -0.10536051565782628; else return -2.3025850929940455; } } double emission_prob (char observation,char state,bool log_prob) { if (!log_prob) { if (state == observation) return 0.8; else return 0.2; } else { if (state == observation) return -0.2231435513142097; else return -1.6094379124341003; } } void dtmf_example() { bool debug = true; char *samples = "XXXXXXXXXXXXXX6X66XXXXXXXXXXXXXXXXXXXXX"; int n_samples = strlen(samples); char *best_path = malloc(sizeof(int) * n_samples); viterbi_log(samples,n_samples,best_path,&prior_prob,&transition_prob,&emission_prob,debug); printf("nbest path = { "); for (int t = 0; t < n_samples; t++) printf("%d ",best_path[t]); printf("}n"); } int main(void) { dtmf_example(); return 0; } 断言: best_path_table[13][16] or [637] = 0 => 0 best_path_table[14][16] or [638] = 0 => 0 best_path_table[15][16] or [639] = 0 => 0 best_path_table[16][16] or [640] = 0 => 0 best_path,[ [624],0 [625],0 [626],0 [627],0 [628],0 [629],0 [630],0 [631],7 [632],0 [633],0 [634],0 [635],0 [636],0 [637],0 [638],0 [639],0 [640],0 ] t=17 => sample=6 Assertion failed: ((t*n_samples+i) >= 0 && (t*n_samples+i) < (n_samples) * n_states),function viterbi_log,file viterbi3.c,line 89. Abort trap: 6 这是CHECK_SUBSCRIPT: CHECK_SUBSCRIPT(t*n_samples+i,n_samples); viterbi_table[t * n_samples + i] = max_p; best_path_table[t * n_samples + i] = max_state_index; (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |