[+] Kernel density estimation
This commit is contained in:
File diff suppressed because one or more lines are too long
+68
@@ -0,0 +1,68 @@
|
|||||||
|
import json
|
||||||
|
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
import numpy as np
|
||||||
|
from parselmouth import Sound
|
||||||
|
from scipy.stats import gaussian_kde
|
||||||
|
|
||||||
|
from statistics import *
|
||||||
|
|
||||||
|
|
||||||
|
Feature = Literal['pitch', 'f1', 'f2', 'f3', 'tilt']
|
||||||
|
Gender = Literal['f', 'm']
|
||||||
|
|
||||||
|
|
||||||
|
_kde_functions: dict[Feature, dict[Gender, gaussian_kde]] = {}
|
||||||
|
|
||||||
|
|
||||||
|
def load_kde():
|
||||||
|
"""
|
||||||
|
Load statistical results into kernel density functions
|
||||||
|
|
||||||
|
:return: Kernel density functions for F and M for pitch, f1, f2, f3, tilt
|
||||||
|
"""
|
||||||
|
if _kde_functions:
|
||||||
|
return _kde_functions
|
||||||
|
|
||||||
|
data: dict[Feature, dict[Gender, list[float]]] = {**json.loads(Path('results/frequency-data.json').read_text()),
|
||||||
|
**json.loads(Path('results/tilt-data.json').read_text())}
|
||||||
|
|
||||||
|
# Lowercase keys
|
||||||
|
data = {k.lower(): data[k] for k in data}
|
||||||
|
|
||||||
|
# Fit KDE functions
|
||||||
|
for feature in data:
|
||||||
|
_kde_functions[feature] = {}
|
||||||
|
for gender in data[feature]:
|
||||||
|
kde = gaussian_kde(data[feature][gender], 'scott')
|
||||||
|
_kde_functions[feature][gender] = kde
|
||||||
|
|
||||||
|
return _kde_functions
|
||||||
|
|
||||||
|
|
||||||
|
def calculate_feature_means(audio: Sound) -> dict[Feature, float]:
|
||||||
|
s = calculate_freq_statistics(calculate_freq_info(audio))
|
||||||
|
return {'pitch': s.pitch.mean, 'f1': s.f1.mean, 'f2': s.f2.mean, 'f3': s.f3.mean, 'tilt': tilt(audio)}
|
||||||
|
|
||||||
|
|
||||||
|
def _calculate_fem_prob(feature: Feature, value: float) -> float:
|
||||||
|
"""
|
||||||
|
Calculate probability of a feature sounding feminine
|
||||||
|
|
||||||
|
:return: Ratio between 0 and 1
|
||||||
|
"""
|
||||||
|
f = load_kde()[feature]['f'].evaluate([value])[0]
|
||||||
|
m = load_kde()[feature]['m'].evaluate([value])[0]
|
||||||
|
return f / (f + m)
|
||||||
|
|
||||||
|
|
||||||
|
def calculate_feature_classification(audio: Sound):
|
||||||
|
"""
|
||||||
|
Run statistical classification based on kernel density estimation.
|
||||||
|
|
||||||
|
:param audio: Audio
|
||||||
|
:return: Statistical results {'means': {'pitch': ..., 'f1': ...}, 'fem_prob': {'pitch': ..., 'f1': ...}}
|
||||||
|
"""
|
||||||
|
means = calculate_feature_means(audio)
|
||||||
|
fem_prob = {feature: _calculate_fem_prob(feature, means[feature]) for feature in means}
|
||||||
|
return {'means': means, 'fem_prob': fem_prob}
|
||||||
+2
-3
@@ -280,7 +280,6 @@ def collect_visualize_freq():
|
|||||||
df = pd.DataFrame({headers[i]: f_means[:, i] for i in range(4)})
|
df = pd.DataFrame({headers[i]: f_means[:, i] for i in range(4)})
|
||||||
dm = pd.DataFrame({headers[i]: m_means[:, i] for i in range(4)})
|
dm = pd.DataFrame({headers[i]: m_means[:, i] for i in range(4)})
|
||||||
args = dict(orient='h', scale='width', inner='quartile', linewidth=0.5)
|
args = dict(orient='h', scale='width', inner='quartile', linewidth=0.5)
|
||||||
sns.histplot()
|
|
||||||
sns.violinplot(data=df, color=COLOR_PINK, **args)
|
sns.violinplot(data=df, color=COLOR_PINK, **args)
|
||||||
sns.violinplot(data=dm, color=COLOR_BLUE, **args)
|
sns.violinplot(data=dm, color=COLOR_BLUE, **args)
|
||||||
[c.set_alpha(0.7) for c in ax.collections]
|
[c.set_alpha(0.7) for c in ax.collections]
|
||||||
@@ -346,7 +345,7 @@ def collect_visualize_tilt():
|
|||||||
plt.show()
|
plt.show()
|
||||||
|
|
||||||
# Write JSON
|
# Write JSON
|
||||||
data = {'f': f_means.tolist(), 'm': m_means.tolist()}
|
data = {'tilt': {'f': f_means.tolist(), 'm': m_means.tolist()}}
|
||||||
Path('results/tilt-data.json').write_text(json.dumps(data), 'utf-8')
|
Path('results/tilt-data.json').write_text(json.dumps(data), 'utf-8')
|
||||||
|
|
||||||
|
|
||||||
@@ -364,7 +363,7 @@ if __name__ == '__main__':
|
|||||||
# call_id_vox_celeb(combine_id_freq)
|
# call_id_vox_celeb(combine_id_freq)
|
||||||
|
|
||||||
# 3. Collect statistics and draw visualizations
|
# 3. Collect statistics and draw visualizations
|
||||||
collect_visualize_freq()
|
# collect_visualize_freq()
|
||||||
|
|
||||||
###########
|
###########
|
||||||
# 1. Compute and save all the spectral tilt for vox1
|
# 1. Compute and save all the spectral tilt for vox1
|
||||||
|
|||||||
Reference in New Issue
Block a user