| """Table 1 utterance-conditioning row / Finding 4 — utterance conditioning: inject the human utterance's acoustics via interaction features | |
| (cosine delivery-match / element-wise products). Plain concatenation cancels in the pairwise difference, | |
| so interactions are the only way the utterance can enter a linear pairwise ranker. | |
| python experiments/exp_utterance.py (~3 min) | |
| """ | |
| import sys | |
| import os | |
| sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)), "..")) | |
| import numpy as np | |
| from sklearn.linear_model import LogisticRegression | |
| from sklearn.preprocessing import StandardScaler | |
| from experiments import common as C | |
| def nrm(v): | |
| return v / (np.linalg.norm(v) + 1e-8) | |
| def feature(resp, utt, mode): | |
| a = C.arr(resp) | |
| base = np.concatenate([a[r] for r in C.POOL_FINAL]) | |
| if mode == "base": | |
| return base | |
| um = C.arr(utt)[C.R_MEAN()] | |
| resp_parts = [a[C.R_MEAN()], a[C.R_SEG3], a[C.R_SEG3 + 1], a[C.R_SEG3 + 2]] | |
| if mode == "+cos": | |
| return np.concatenate([base, np.array([float(nrm(p) @ nrm(um)) for p in resp_parts], dtype=np.float32)]) | |
| if mode == "+prod": | |
| return np.concatenate([base, a[C.R_MEAN()] * um]) | |
| raise ValueError(mode) | |
| for mode in ["base", "+cos", "+prod"]: | |
| X, y = [], [] | |
| for it in C.train_items(2500): | |
| try: | |
| g, b = feature(it.good_wav, it.utterance_wav, mode), feature(it.bad_wav, it.utterance_wav, mode) | |
| except Exception: | |
| continue | |
| X.append(g - b); y.append(1) | |
| X.append(b - g); y.append(0) | |
| X = np.array(X) | |
| sc = StandardScaler().fit(X) | |
| clf = LogisticRegression(max_iter=3000, C=0.5).fit(sc.transform(X), y) | |
| ans = {} | |
| for q in C.QS: | |
| fv = sc.transform([feature(o.wav, q.utterance_wav, mode) for o in q.options]) | |
| ans[q.qid] = [o.letter for o in q.options][int(np.argmax(clf.decision_function(fv)))] | |
| C.report(mode, ans) | |