Spaces:
Running on Zero
Running on Zero
File size: 3,576 Bytes
a22c748 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 | import numpy as np
import re
_FOLDINGS = {
'AO': 'AA',
'AX': 'AH',
'AX-H': 'AH',
'AXR': 'ER',
'HV': 'HH',
'IX': 'IH',
'EL': 'L',
'EM': 'M',
'EN': 'N',
'NX': 'N',
'ENG': 'NG',
'PCL': 'P',
'TCL': 'T',
'KCL': 'K',
'BCL': 'B',
'DCL': 'D',
'GCL': 'G',
'H#': 'SIL',
'PAU': 'SIL',
'EPI': 'SIL',
'UX': 'UW'
}
def align(seq, probs):
def distance(r, c):
category = seq[r]
timestep = c
return probs[timestep, category]
nrow = len(seq)
ncol = probs.shape[0] # time steps
M = warp(range(nrow), range(ncol), distance)
alignment = traceback(M[1:, 1:], seq)
return alignment, M[1:, 1:]
def warp(S, T, d):
nrow = len(S)
ncol = len(T)
M = np.full((nrow+1, ncol+1), np.inf)
M[0, 0] = 0
# Some optimization is being left on the table; this should be computable
# for a whole column at a time
for r in range(1, nrow+1):
for c in range(1, ncol+1):
# need -1 offset for cost because of extra first row
# and first column in M that isn't present in the
# `probs` matrix
cost = d(r-1, c-1)
M[r, c] = cost + min(M[r, c-1], M[r-1, c-1])
return M
def traceback(M, sequence):
nrow, ncol = M.shape
seq = [nrow-1]
r = nrow-1
c = ncol-1
curr_prob = M[r, c]
while c >= 0:
if r == 0:
seq += [0 for x in range(ncol - len(seq))]
break
if M[r-1, c-1] > M[r, c-1]:
seq.append(r)
c -= 1
else:
c -= 1
r -= 1
seq.append(r)
rs = seq[::-1]
rs = [sequence[r] for r in rs]
return rs
def collapse(s):
a = [s[0]]
for symbol in s[1:]:
if a[-1] != symbol:
a.append(symbol)
return a
def fold_phone(p):
stress_mark = re.findall(r'\d+', p)
if stress_mark:
stress_mark = stress_mark[0]
else:
stress_mark = ''
phone_label = re.sub(r'\d', '', p)
if phone_label in _FOLDINGS:
phone_label = _FOLDINGS[phone_label]
return phone_label + stress_mark
def load_dictionary(dname, cmuformat=True):
mapping = dict()
if cmuformat:
with open(dname, 'r') as d:
for line in d:
line = line.strip()
if not line or line.startswith(';;;'):
continue
all_items = line.split()
if len(all_items) < 2:
continue
word = all_items[0]
word = re.sub(r'\(\d*\)', '', word)
# NLTK cmudict uses ``WORD <variant_index> PHONE ...``; skip the index.
pron_start = 2 if len(all_items) >= 3 and all_items[1].isdigit() else 1
pronunciation = all_items[pron_start:]
pronunciation = [fold_phone(p) for p in pronunciation]
if not pronunciation:
continue
if word not in mapping:
mapping[word] = [pronunciation]
else:
mapping[word].append(pronunciation)
mapping['sil'] = [['H#'], []]
return mapping
else:
print('Custom dictionary formats not supported yet. Please format use CMU dict formatting and run again.')
sys.exit(1)
|