beam search as described by the paper of Hwang et al. and the paper of Graves et al.
(mat, classes, ignore_idx, lm, beamWidth=25, dict_list = [])
| 72 | beamState.entries[labeling] = BeamEntry() |
| 73 | |
| 74 | def ctcBeamSearch(mat, classes, ignore_idx, lm, beamWidth=25, dict_list = []): |
| 75 | "beam search as described by the paper of Hwang et al. and the paper of Graves et al." |
| 76 | |
| 77 | #blankIdx = len(classes) |
| 78 | blankIdx = 0 |
| 79 | maxT, maxC = mat.shape |
| 80 | |
| 81 | # initialise beam state |
| 82 | last = BeamState() |
| 83 | labeling = () |
| 84 | last.entries[labeling] = BeamEntry() |
| 85 | last.entries[labeling].prBlank = 1 |
| 86 | last.entries[labeling].prTotal = 1 |
| 87 | |
| 88 | # go over all time-steps |
| 89 | for t in range(maxT): |
| 90 | curr = BeamState() |
| 91 | |
| 92 | # get beam-labelings of best beams |
| 93 | bestLabelings = last.sort()[0:beamWidth] |
| 94 | |
| 95 | # go over best beams |
| 96 | for labeling in bestLabelings: |
| 97 | |
| 98 | # probability of paths ending with a non-blank |
| 99 | prNonBlank = 0 |
| 100 | # in case of non-empty beam |
| 101 | if labeling: |
| 102 | # probability of paths with repeated last char at the end |
| 103 | prNonBlank = last.entries[labeling].prNonBlank * mat[t, labeling[-1]] |
| 104 | |
| 105 | # probability of paths ending with a blank |
| 106 | prBlank = (last.entries[labeling].prTotal) * mat[t, blankIdx] |
| 107 | |
| 108 | # add beam at current time-step if needed |
| 109 | addBeam(curr, labeling) |
| 110 | |
| 111 | # fill in data |
| 112 | curr.entries[labeling].labeling = labeling |
| 113 | curr.entries[labeling].prNonBlank += prNonBlank |
| 114 | curr.entries[labeling].prBlank += prBlank |
| 115 | curr.entries[labeling].prTotal += prBlank + prNonBlank |
| 116 | curr.entries[labeling].prText = last.entries[labeling].prText # beam-labeling not changed, therefore also LM score unchanged from |
| 117 | curr.entries[labeling].lmApplied = True # LM already applied at previous time-step for this beam-labeling |
| 118 | |
| 119 | # extend current beam-labeling |
| 120 | for c in range(maxC - 1): |
| 121 | # add new char to current beam-labeling |
| 122 | newLabeling = labeling + (c,) |
| 123 | |
| 124 | # if new labeling contains duplicate char at the end, only consider paths ending with a blank |
| 125 | if labeling and labeling[-1] == c: |
| 126 | prNonBlank = mat[t, c] * last.entries[labeling].prBlank |
| 127 | else: |
| 128 | prNonBlank = mat[t, c] * last.entries[labeling].prTotal |
| 129 | |
| 130 | # add beam at current time-step if needed |
| 131 | addBeam(curr, newLabeling) |