In [1]:
#import cubehelix
from joblib import Parallel, delayed
import matplotlib
import matplotlib.pyplot as plt
from matplotlib import gridspec
import numpy as np
import os
import pandas as pd
import seaborn as sns
import msaf # Develop branch
import mir_eval # Uri's fork: https://github.com/urinieto/mir_eval
#from mir_eval.segment import tree
#import tree
from fsegment_tree import tree
import fsegment_tree as segment_tree
mir_eval.segment = segment_tree
# Beatuiful seaborn plots
sns.set(style="ticks")
%matplotlib inline
# Colorhelix config
#cx = cubehelix.cmap(reverse=True, start=0.2, rot=-0.4, minLight=0.0, maxLight=1.0)
# SALAMI Path
#SALAMI_path = "/home/uri/datasets/Segments/references/"
In [2]:
cx = sns.cubehelix_palette(reverse=False, start=0.2, rot=-0.4, dark=0.45, light=1.0, as_cmap=True)
In [3]:
def gen_synthetic_labels(bounds):
labels = []
[labels.append(np.random.random(len(level) - 1)) for level in bounds]
return labels
def evaluate_flat(ref_times, est_times, w, trim=False):
ref_times = np.asarray(ref_times).flatten()
est_times = np.asarray(est_times).flatten()
ref_inter = np.asarray(zip(ref_times[:], ref_times[1:]))
est_inter = np.asarray(zip(est_times[:], est_times[1:]))
p, r, f = mir_eval.segment.detection(ref_inter, est_inter, trim=trim, window=w)
R2E, E2R = mir_eval.segment.deviation(ref_inter, est_inter, trim=trim)
print "F: %.2f\t P: %.2f\t R: %.2f" % (f * 100, p * 100, r * 100)
print "R2E: %.2f\t E2R: %.2f" % (R2E, E2R)
return f, p, r
def evaluate_hier(bounds1, bounds2, levels1=None, levels2=None, title=None, figsize=(7,3),
ratios=[1,1], transitive=False, plot=True):
labels1 = gen_synthetic_labels(bounds1)
labels2 = gen_synthetic_labels(bounds2)
tree1 = tree.SegmentTree(bounds1, labels1, levels1)
tree2 = tree.SegmentTree(bounds2, labels2, levels2)
res = 0.1
for ws in [0.5, 3.0, 15, 30, None]:
if ws is None:
w = None
else:
w = int(ws / res)
T_o, T_u, T_f = mir_eval.segment.hmeasure(tree1, tree2, transitive=transitive, window=w, res=res)
if ws is None:
ws = np.inf
print "w: %.1f\t Tu: %.2f\t To: %.2f" % (ws, T_u * 100, T_o * 100)
if plot:
plt.figure(figsize=figsize)
gs = gridspec.GridSpec(2, 1, height_ratios=ratios)
plt.subplot(gs[0])
msaf.plotting.plot_tree(tree1, title="Reference", res=None, cmap_id=cx)
plt.xlabel('')
plt.subplot(gs[1])
msaf.plotting.plot_tree(tree2, title="Estimation", res=None, cmap_id=cx)
plt.tight_layout()
def remove_level(bounds, levels, level_id):
for i, level in enumerate(levels):
if level_id == level:
bounds.pop(i)
levels.pop(i)
break
In [4]:
# Synthetic example
est_bounds = [[0, 30, 100], [0, 10, 30, 40, 80, 100], [0, 10, 25, 30, 40, 50, 80, 95, 100]]
est_labels = gen_synthetic_labels(est_bounds)
est_tree = tree.SegmentTree(est_bounds, est_labels)
plt.figure(figsize=(7,2))
msaf.plotting.plot_tree(est_tree, title="Hierarchical Segmentation", res=None, cmap_id=cx)
plt.tight_layout()
#plt.savefig("../figs/hier-example.pdf")
In [5]:
# Synthetic example (2)
orig_size = matplotlib.rcParams["font.size"]
matplotlib.rcParams["font.size"] = 14.
est_bounds = [[0, 30], [0, 10, 30], [0, 10, 25, 30]]
est_labels = gen_synthetic_labels(est_bounds)
est_tree = tree.SegmentTree(est_bounds, est_labels)
plt.figure(figsize=(5,1.75))
msaf.plotting.plot_tree(est_tree,
#title="Hierarchical Segmentation",
res=None,
cmap_id=cx)
plt.xticks([5, 17.5, 27.5], ["$i$", "$j$", "$k$"])
plt.tight_layout()
plt.xlabel("Time")
# Annotate level 2
plt.gca().text(5, 0.165, '$H(i,i)$', horizontalalignment='center', verticalalignment='center')
plt.gca().text(17.5, 0.165, '$H(j,j)$', horizontalalignment='center', verticalalignment='center')
plt.gca().text(27.5, 0.165, '$H(k,k)$', horizontalalignment='center', verticalalignment='center')
#plt.gca().text(35, 0.165, '$H(m,m)$', horizontalalignment='center', verticalalignment='center')
# Annotate level 1
plt.gca().text(20, 0.5, '$H(j,k)$', horizontalalignment='center', verticalalignment='center')
# Annotate level 0
plt.gca().text(15, .845, '$H(i,k)$', horizontalalignment='center', verticalalignment='center')
#plt.savefig("../figs/hier-example.pdf", bbox_inches='tight', pad_inches=0.01)
matplotlib.rcParams["font.size"] = orig_size
In [6]:
# Flat vs flat
f1 = [[0, 10, 20, 30, 40, 50, 60]]
f2 = [[0, 20, 40, 60]]
f, p, r = evaluate_flat(f1, f2, 3, trim=True)
print 'Reduced'
evaluate_hier(f1, f2, title="Flat vs Flat", figsize=(7,2.5), transitive=False)
print 'Full'
evaluate_hier(f1, f2, title="Flat vs Flat", figsize=(7,2.5), transitive=True, plot=False)
#plt.savefig("../figs/flat-flat.pdf")
In [7]:
#Hierarchical vs Flat Large Scale
h1 = [[0, 20, 40, 60], [0, 10, 20, 30, 40, 50, 60]]
f2 = [[0, 20, 40, 60]]
print 'Reduced'
evaluate_hier(h1, f2, title="Hierarchical vs Flat Large Scale", figsize=(7,2.5), transitive=False)
print 'Full'
evaluate_hier(h1, f2, title="Hierarchical vs Flat Large Scale", figsize=(7,2.5), transitive=True, plot=False)
#plt.savefig("../figs/hier-flatlarge.pdf")
In [116]:
#Hierarchical vs Flat Large Scale
h1 = [[0, 20, 40, 60], [0, 10, 20, 30, 40, 50, 60]]
f2 = [[0, 10, 50, 60]]
print 'Reduced'
evaluate_hier(h1, f2, title="Hierarchical vs Flat Large Scale", figsize=(7,2.5), transitive=False)
print 'Full'
evaluate_hier(h1, f2, title="Hierarchical vs Flat Large Scale", figsize=(7,2.5), transitive=True, plot=False)
#plt.savefig("../figs/hier-flatlarge.pdf")
In [119]:
#Hierarchical vs Flat Larger Scale
h1 = [[0, 20, 40, 60], [0, 10, 20, 30, 40, 50, 60]]
f2 = [[0, 40, 60]]
print 'Reduced'
evaluate_hier(h1, f2, title="Hierarchical vs Flat Large Scale", figsize=(7,2.5), transitive=False)
print 'Full'
evaluate_hier(h1, f2, title="Hierarchical vs Flat Large Scale", figsize=(7,2.5), transitive=True, plot=False)
plt.tight_layout()
plt.savefig("../figs/hier-flatlarger.pdf")
In [110]:
# Hierarchical vs Flat Small Scale
h1 = [[0, 20, 40, 60], [0, 10, 20, 30, 40, 50, 60]]
f2 = [[0, 10, 20, 30, 40, 50, 60]]
print 'Reduced'
evaluate_hier(h1, f2, title="Hierarchical vs Flat Small Scale", figsize=(7,2.5), transitive=False)
print 'Full'
evaluate_hier(h1, f2, title="Hierarchical vs Flat Small Scale", figsize=(7,2.5), transitive=True, plot=False)
plt.savefig("../figs/hier-flatsmall.pdf")
In [111]:
# Hierarchical vs Flat Smaller Scale
h1 = [[0, 20, 40, 60], [0, 10, 20, 30, 40, 50, 60]]
f2 = [[0, 10, 15, 20, 25, 30, 35, 40, 45, 50, 60]]
print 'Reduced'
evaluate_hier(h1, f2, title="Hierarchical vs Flat Small Scale", figsize=(7,2.5), transitive=False)
print 'Full'
evaluate_hier(h1, f2, title="Hierarchical vs Flat Small Scale", figsize=(7,2.5), plot=False, transitive=True)
plt.savefig("../figs/hier-flatsmaller.pdf")
In [8]:
# Hierarchical vs Hierarchical
h1 = [[0, 20, 40, 60], [0, 10, 20, 30, 40, 50, 60]]
h2 = [[0, 40, 60], [0, 20, 40, 60], [0, 10, 20, 30, 40, 50, 60]]
print 'Reduced'
evaluate_hier(h1, h2, title="Hierarchical vs Hierarchical", figsize=(7,3), transitive=False)
print 'Full'
evaluate_hier(h1, h2, title="Hierarchical vs Hierarchical", figsize=(7,3), plot=False, transitive=True)
#plt.savefig("../figs/hier-hiercomp.pdf")
In [91]:
reload(segment_tree)
Out[91]:
In [9]:
jams_file = "SALAMI_636.jams"
hier_bounds1, hier_labels1, hier_levels1 = msaf.io.read_hier_references('../test/' + jams_file, annotation_id=0)
hier_bounds2, hier_labels2, hier_levels2 = msaf.io.read_hier_references('../test/' + jams_file, annotation_id=1)
# Remove the function level
hier_levels1 = list(hier_levels1)
hier_levels2 = list(hier_levels2)
remove_level(hier_bounds1, hier_levels1, "function")
remove_level(hier_bounds2, hier_levels2, "function")
# Evaluate
print 'Reduced'
evaluate_hier(hier_bounds1, hier_bounds2, hier_levels1, hier_levels2, title="SALAMI vs SALAMI", figsize=(7,3), transitive=False)
print 'Full'
evaluate_hier(hier_bounds1, hier_bounds2, hier_levels1, hier_levels2, title="SALAMI vs SALAMI", figsize=(7,3), transitive=True, plot=False)
#plt.savefig("../figs/SALAMI-SALAMI.pdf")
In [11]:
%prun evaluate_hier(hier_bounds1, hier_bounds2, hier_levels1, hier_levels2, title="SALAMI vs SALAMI", figsize=(7,3), transitive=True, plot=False)
In [114]:
jams_file = "SALAMI_636.jams"
olda_file = "SALAMI_636_OLDA.jams"
hier_bounds1, hier_labels1, hier_levels1 = msaf.io.read_hier_references('../test/' + jams_file)
hier_bounds2, hier_labels2, hier_levels2 = msaf.io.read_hier_references('../test/' + olda_file)
# Remove the function level from SALAMI
hier_levels1 = list(hier_levels1)
remove_level(hier_bounds1, hier_levels1, "function")
# Evaluate
print 'Reduced'
evaluate_hier(hier_bounds1, hier_bounds2, hier_levels1, hier_levels2, title="SALAMI vs OLDA", figsize=(7,5), ratios=[1,3],
transitive=False)
print 'Full'
evaluate_hier(hier_bounds1, hier_bounds2, hier_levels1, hier_levels2, title="SALAMI vs OLDA", figsize=(7,5), ratios=[1,3],
transitive=True, plot=False)
plt.savefig("../figs/SALAMI-OLDA.pdf")
In [ ]:
# Automatically set w
def analyze_salami(salami_file, windows):
# Read annotations
try:
bounds1, labels1, levels1 = msaf.io.read_hier_references(salami_file.ref_file, annotation_id=0)
bounds2, labels2, levels2 = msaf.io.read_hier_references(salami_file.ref_file, annotation_id=1)
# Convert to tree
labels1 = gen_synthetic_labels(bounds1)
labels2 = gen_synthetic_labels(bounds2)
tree1 = tree.SegmentTree(bounds1, labels1, levels1)
tree2 = tree.SegmentTree(bounds2, labels2, levels2)
# Evaluate
print "Evaluating %s..." % salami_file.ref_file
res = 0.1
results = {}
results["file"] = os.path.basename(salami_file.ref_file)
for ws in windows:
if ws is None:
w = None
else:
w = int(ws / res)
T_o, T_u, T_f = mir_eval.segment.hmeasure(tree1, tree2, transitive=True, window=w, res=res)
if ws is None:
ws = np.inf
results["Tf_" + str(ws)] = T_f
results["To_" + str(ws)] = T_o
results["Tu_" + str(ws)] = T_u
except:
return []
return results
n_jobs = 8
salami_files = msaf.io.get_dataset_files("/home/uri/datasets/Segments/", ds_name="SALAMI")
windows = [0.5, 3, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60]
# Run in parallel
raw_results = Parallel(n_jobs=n_jobs)(delayed(analyze_salami)(salami_file, windows)
for salami_file in salami_files[:])
# Aggregate results in pandas format
results = pd.DataFrame()
for r in raw_results:
if r != []:
results = results.append(r, ignore_index=True)
In [205]:
print len(results)
print len(salami_files)
print results.mean()
print results.mean().values
print results.mean().keys()
In [206]:
results.to_csv("searching_w.csv")
In [229]:
plt.figure(figsize=(6,3))
Tf_keys = ["Tf_" + str(w) for w in windows]
To_keys = ["To_" + str(w) for w in windows]
Tu_keys = ["Tu_" + str(w) for w in windows]
plt.plot(windows, results[Tf_keys].mean().values, label="$T_f = \frac{2T_u T_o}{T_u + T_o}$")
plt.plot(windows, results[To_keys].mean().values, label="$T_o$")
plt.plot(windows, results[Tu_keys].mean().values, label="$T_u$")
plt.plot(windows[np.argmax(results[Tf_keys].mean().values)],
np.max(results[Tf_keys].mean().values), 'rD')
plt.ylim((0.4,1))
plt.legend(loc='lower right')
plt.xlabel("Window size (seconds)")
plt.ylabel("$T$-measures")
sns.despine()
plt.tight_layout()
plt.savefig("../figs/exploring_w.pdf")
In [ ]: