#!/usr/bin/env python # coding: utf-8 # # Genre recognition: experiment # Goal: observe the effect of $\lambda_g$. # # Conclusion: A value of $\lambda_s$ between 1 and 10 seems reasonable (when $\lambda_g = \lambda_d = 100$). # # Observation: # * Too sparse is very slow (17h) and gives poor accuracy. # * Sparsity is proportional to $\lambda_s$. # * Increasing sparsity correlates with decreasing Dirichlet energy, which makes sense as the energy of the sparse codes diminishes. It trades with reconstruction error. # ## Hyper-parameters # ### Parameter under test # In[1]: Pname = 'ls' Pvalues = [0.1, 1, 10, 100, 1e3] # Regenerate the graph or the features at each iteration. regen_graph = False regen_features = True # ### Model parameters # In[2]: p = {} # Preprocessing. # Graph. p['K'] = 10 + 1 # 5 to 10 + 1 for self-reference p['dm'] = 'cosine' p['Csigma'] = 1 p['diag'] = True p['laplacian'] = 'normalized' # Feature extraction. p['m'] = 128 # 64, 128, 512 p['ls'] = 1 p['ld'] = 100 p['le'] = None p['lg'] = 100 # Classification. p['scale'] = None p['Nvectors'] = 6 p['svm_type'] = 'C' p['kernel'] = 'linear' p['C'] = 1 p['nu'] = 0.5 # ### Numerical parameters # In[3]: # Dataset (10,100,644 | 5,100,149 | 2,10,644). p['Ngenres'] = 5 p['Nclips'] = 100 p['Nframes'] = 149 # Graph. p['tol'] = 1e-5 # Feature extraction. p['rtol'] = 1e-6 # 1e-3, 1e-5, 1e-7 p['N_inner'] = 500 p['N_outer'] = 50 # Classification. p['Nfolds'] = 10 p['Ncv'] = 20 p['dataset_classification'] = 'Z' # ## Processing # In[4]: import numpy as np import time texperiment = time.time() # Result dictionary. res = ['accuracy', 'accuracy_std'] res += ['sparsity', 'atoms'] res += ['objective_g', 'objective_h', 'objective_i', 'objective_j'] res += ['time_features', 'iterations_inner', 'iterations_outer'] res = dict.fromkeys(res) for key in res.keys(): res[key] = [] def separator(name, parameter=False): if parameter: name += ', {} = {}'.format(Pname, p[Pname]) dashes = 20 * '-' print('\n {} {} {} \n'.format(dashes, name, dashes)) # Fair comparison when tuning parameters. # Randomnesses: dictionary initialization, training and testing sets. np.random.seed(1) # In[5]: #%run gtzan.ipynb #%run audio_preprocessing.ipynb if not regen_graph: separator('Graph') get_ipython().run_line_magic('run', 'audio_graph.ipynb') if not regen_features: separator('Features') get_ipython().run_line_magic('run', 'audio_features.ipynb') # Hyper-parameter under test. for n_exp, p[Pname] in enumerate(Pvalues): if regen_graph: separator('Graph', True) get_ipython().run_line_magic('run', 'audio_graph.ipynb') if regen_features: separator('Features', True) get_ipython().run_line_magic('run', 'audio_features.ipynb') separator('Classification', True) get_ipython().run_line_magic('run', 'audio_classification.ipynb') # Collect results. for key in res: res[key].append(globals()[key]) # Baseline, i.e. classification with spectrograms. p['dataset_classification'] = 'X' p['scale'] = 'minmax' # Todo: should be done in pre-processing. if not regen_graph and not regen_features: # Classifier parameters are being tested. for p[Pname] in Pvalues: separator('Baseline', True) get_ipython().run_line_magic('run', 'audio_classification.ipynb') else: separator('Baseline') get_ipython().run_line_magic('run', 'audio_classification.ipynb') # ## Results # In[6]: print('{}: {}'.format(Pname, Pvalues)) for key, value in res.items(): if key is not 'atoms': print('{}: {}'.format(key, value)) def plot(*args, **kwargs): plt.figure(figsize=(8,5)) x = range(len(Pvalues)) log = 'log' in kwargs and kwargs['log'] is True pltfunc = plt.semilogy if log else plt.plot for var in args: pltfunc(x, res[var], '.-', label=var) plt.xlim(0, len(Pvalues)-1) plt.title('{} vs {}'.format(', '.join(args), Pname)) plt.xlabel(Pname) plt.ylabel(' ,'.join(args)) plt.xticks(x, Pvalues) plt.grid(True); plt.legend(loc='best'); plt.show() # Classification results. plot('accuracy') # Features extraction results. if regen_features: plot('objective_g', 'objective_i', 'objective_j', log=True) plot('sparsity') plot('time_features') plot('iterations_inner') plot('iterations_outer') for i, fig in enumerate(res['atoms']): print('Dictionary atoms for {} = {}'.format(Pname, Pvalues[i])) fig.show() print('Experiment time: {:.0f} seconds'.format(time.time() - texperiment)) # ### Unweighted objectives # In[3]: import numpy as np import matplotlib.pyplot as plt get_ipython().run_line_magic('matplotlib', 'inline') def plot(*args, **kwargs): plt.figure(figsize=(8,5)) x = range(len(Pvalues)) log = 'log' in kwargs and kwargs['log'] is True pltfunc = plt.semilogy if log else plt.plot params = {} params['linestyle'] = '-' params['marker'] = '.' params['markersize'] = 10 for i, var in enumerate(args): if 'err' in kwargs: pltfunc = plt.errorbar params['yerr'] = res[kwargs['err'][i]] params['capsize'] = 5 pltfunc(x, res[var], label=var, **params) for i,j in zip(x, res[var]): plt.annotate('{:.2f}'.format(j), xy=(i,j), xytext=(5,5), textcoords='offset points') margin = 0.25 / (len(Pvalues)-1) params['markersize'] = 10 plt.xlim(-margin, len(Pvalues)-1+margin) plt.title('{} vs {}'.format(', '.join(args), Pname)) plt.xlabel(Pname) plt.ylabel(' ,'.join(args)) plt.xticks(x, Pvalues) plt.grid(True); plt.legend(loc='best'); plt.show() Pname = 'ls' Pvalues = np.array([0.1,1,10,100,1e3]) res = {} res['objective_j'] = [113358.04443359375, 101607.73315429688, 61985.699462890625, 2192.4869537353516, 2192.4869537353516] res['objective_i'] = [35003.662499999999, 160855.953125, 661727.109375, 113624.37744140625, 113624.37744140625] res['objective_g'] = [47058.1787109375, 87632.51953125, 479402.734375, 2531210.7421875, 2531210.7421875] res['objective_j'] /= np.array(100) # lg res['objective_i'] /= Pvalues # ld res['objective_g'] /= np.array(100) # ls plot('objective_g', 'objective_i', 'objective_j', log=True) print('g(Z) = ||X-DZ||_2^2, h(Z) = ||Z-EX||_2^2, i(Z) = ||Z||_1, j(Z) = tr(Z^TLZ)')