Source code for costs

# -*- coding: utf-8 -*-
"""
cost.py
~~~~~~~
.. topic:: Contents

    The cost module regroups the cost functions used for the group NMF"""
import theano.tensor as T
from theano.ifelse import ifelse
import theano


[docs]def beta_div(X, W, H, beta): """Compute beta divergence D(X|WH) Parameters ---------- X : Theano tensor data W : Theano tensor Bases H : Theano tensor activation matrix beta : Theano scalar Returns ------- div : Theano scalar beta divergence D(X|WH)""" div = ifelse( T.eq(beta, 2), T.sum(1. / 2 * T.power(X - T.dot(H, W), 2)), ifelse( T.eq(beta, 0), T.sum(X / T.dot(H, W) - T.log(X / T.dot(H, W)) - 1), ifelse( T.eq(beta, 1), T.sum(T.mul(X, (T.log(X) - T.log(T.dot(H, W)))) + T.dot(H, W) - X), T.sum(1. / (beta * (beta - 1.)) * (T.power(X, beta) + (beta - 1.) * T.power(T.dot(H, W), beta) - beta * T.power(T.mul(X, T.dot(H, W)), (beta - 1))))))) return div
[docs]def group_div(X, W, H, beta, params): """Compute beta divergence D(X|WH), intra-class distance and intra-session distance for a particular (class, session) couple [1]_. Parameters ---------- X : Theano tensor data W : Theano tensor Bases H : Theano tensor activation matrix beta : Theano scalar params : Theano tensor Matrix of parameter related to class/session. :params[0][0]: index for the (class, session) couple :params[1][0]: number of vector basis related to class :params[1][1]: number of vector basis related to session :params[2]: weight on the class/session similarity constraints :params[3]: sessions in which class c appears :params[4]: classes present in session s Returns ------- cost : Theano scalar total cost div : Theano scalar beta divergence D(X|WH) sum_cls : Theano scalar intra-class distance sum_ses : Theano scalar intra-session distance""" ind = params[0][0] k_cls = params[1][0] k_ses = params[1][1] lambdas = params[2] Sc = params[3] Cs = params[4] res_ses, up = theano.scan( fn=lambda Cs, prior_result: prior_result + eucl_dist( W[ind, :, k_cls:k_cls+k_ses], W[Cs, :, k_cls:k_cls+k_ses]), outputs_info=T.zeros_like(beta), sequences=Cs) sum_ses = ifelse(T.gt(Cs[0], 0), res_ses[-1], T.zeros_like(beta)) res_cls, up = theano.scan( fn=lambda Sc, prior_result: prior_result + eucl_dist( W[ind, :, 0:k_cls], W[Sc, :, 0:k_cls]), outputs_info=T.zeros_like(beta), sequences=Sc) sum_cls = ifelse(T.gt(Sc[0], 0), res_cls[-1], T.zeros_like(beta)) betaDiv = beta_div(X, W[ind].T, H, beta) cost = lambdas[0] * sum_cls + lambdas[1] * sum_ses + betaDiv return cost, betaDiv, sum_cls, sum_ses
[docs]def noise_div(X, W, Wn, H, beta, params): """Compute beta divergence D(X|WH) noise-related distance (distance to a noise reference) and intra-speaker distance for a particular class (only one noise session considered here). Parameters ---------- X : Theano tensor data W : Theano tensor Bases H : Theano tensor activation matrix beta : Theano scalar params : Theano tensor Matrix of parameter related to class/session. :params[0][0]: index for the (class, session) couple :params[1][0]: number of vector basis related to class :params[1][1]: number of vector basis related to session :params[2]: weight on the class/session similarity constraints :params[3]: sessions in which class c appears Returns ------- cost : Theano scalar total cost div : Theano scalar beta divergence D(X|WH) sum_cls : Theano scalar intra-class distance sum_ses : Theano scalar distance to noise reference""" ind = params[0][0] k_cls = params[1][0] k_ses = params[1][1] lambdas = params[2] Sc = params[3] sum_ses = eucl_dist(W[ind, :, k_cls:k_cls+k_ses], Wn) res_cls, up = theano.scan( fn=lambda Sc, prior_result: prior_result + eucl_dist( W[ind, :, 0:k_cls], W[Sc, :, 0:k_cls]), outputs_info=T.zeros_like(beta), sequences=Sc) sum_cls = ifelse(T.gt(Sc[0], 0), res_cls[-1], T.zeros_like(beta)) betaDiv = beta_div(X, W[ind].T, H, beta) cost = lambdas[0] * sum_cls + lambdas[1] * sum_ses + betaDiv return cost, betaDiv, sum_cls, sum_ses
[docs]def cls_sum(W, params): """Compute summ of basis for a particular class. To be used in the constrained multiplicative update rules [1]_. Parameters ---------- W : Theano tensor Bases params : Theano tensor Matrix of parameter related to class/session. :params[0][0]: number of vector basis related to class :params[1]: sessions in which class c appears Returns ------- sum_cls : Theano scalar sum of the basis for the class""" k_cls = params[0][0] Sc = params[1] res_cls, up = theano.scan( fn=lambda Sc, prior_result: prior_result + W[Sc, :, 0:k_cls], outputs_info=T.zeros_like(W[0, :, 0:k_cls]), sequences=Sc) return res_cls[-1]
[docs]def ses_sum(W, params): """Compute sum of basis for a particular session. To be used in the constrained multiplicative update rules [1]_. Parameters ---------- W : Theano tensor Bases params : Theano tensor Matrix of parameter related to class/session. :params[0][0]: number of vector basis related to class :params[1]: class that appear in session s Returns ------- sum_ses : Theano scalar sum of the basis for the session""" k_cls = params[0][0] k_ses = params[0][1] Cs = params[1] res_ses, up = theano.scan( fn=lambda Cs, prior_result: prior_result + W[Cs, :, k_cls:k_cls+k_ses], outputs_info=T.zeros_like(W[0, :, k_cls:k_ses+k_cls]), sequences=Cs) return res_ses[-1]
[docs]def eucl_dist(X, Y): """Compute Euclidean distance between X and Y Parameters ---------- X : Theano tensor Y : Theano tensor Returns ------- out : Theano scalar Euclidean distance""" return T.sum((1. / 2) * (T.power(X, 2) + T.power(Y, 2) - 2 * T.mul(X, Y)))