Source code for updates

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

  The update module regroupse the update functions used for the group NMF"""

import theano.tensor as T
import theano
from theano.ifelse import ifelse


[docs]def beta_H(X, W, H, beta): """Update activation with beta divergence Parameters ---------- X : Theano tensor data W : Theano tensor Bases H : Theano tensor activation matrix beta : Theano scalar Returns ------- H : Theano tensor Updated version of the activations """ up = ifelse( T.eq(beta, 2), (T.dot(X, W)) / (T.dot(T.dot(H, W.T), W)), (T.dot(T.mul(T.power(T.dot(H, W.T), (beta - 2)), X), W)) / (T.dot(T.power(T.dot(H, W.T), (beta-1)), W))) return T.mul(H, up)
[docs]def beta_H_Sparse(X, W, H, beta, l_sp): """Update activation with beta divergence Parameters ---------- X : Theano tensor data W : Theano tensor Bases H : Theano tensor activation matrix beta : Theano scalar l_sp : Theano scalar sparsity constraint Returns ------- H : Theano tensor Updated version of the activations """ up = ifelse( T.eq(beta, 2), (T.dot(X, W)) / (T.dot(T.dot(H, W.T), W) + l_sp), (T.dot(T.mul(T.power(T.dot(H, W.T), (beta - 2)), X), W)) / (T.dot(T.power(T.dot(H, W.T), (beta-1)), W) + l_sp)) return T.mul(H, up)
[docs]def beta_H_groupSparse(X, W, H, beta, l_sp, start, stop): """Update activation with beta divergence Parameters ---------- X : Theano tensor data W : Theano tensor Bases H : Theano tensor activation matrix beta : Theano scalar l_sp : Theano scalar group sparsity constraint start : Theano vector beginning indexes for the sparsity groups stop : Theano vector stop indexes for the sparsity groups Returns ------- H : Theano tensor Updated version of the activations """ results, _ = theano.scan(fn=lambda start_i, stop_i, prior_results, H: T.set_subtensor( prior_results[:, start_i:stop_i].T, H[:, start_i:stop_i].T / H[:, start_i:stop_i].norm(2, axis=1)).T, outputs_info=T.zeros_like(H), sequences=[start, stop], non_sequences=H) cst = results[-1] up = ifelse( T.eq(beta, 2), (T.dot(X, W)) / (T.dot(T.dot(H, W.T), W) + l_sp * cst), (T.dot(T.mul(T.power(T.dot(H, W.T), (beta - 2)), X), W)) / (T.dot(T.power(T.dot(H, W.T), (beta-1)), W) + l_sp * cst)) return T.mul(H, up)
[docs]def beta_W(X, W, H, beta): """Update bases with beta divergence Parameters ---------- X : Theano tensor data W : Theano tensor Bases H : Theano tensor activation matrix beta : Theano scalar Returns ------- W : Theano tensor Updated version of the bases """ up = ifelse( T.eq(beta, 2), (T.dot(X.T, H)) / (T.dot(T.dot(H, W.T).T, H)), (T.dot(T.mul(T.power(T.dot(H, W.T), (beta - 2)), X).T, H)) / (T.dot(T.power(T.dot(H, W.T), (beta-1)).T, H))) return T.mul(W, up)
[docs]def H_beta_sub(X, W, Wsub, H, Hsub, beta): """Update group activation with beta divergence Parameters ---------- X : Theano tensor data W : Theano tensor Bases Wsub : Theano tensor group Bases H : Theano tensor activation matrix Hsub : Theano tensor group activation matrix beta : Theano scalar Returns ------- H : Theano tensor Updated version of the activations """ up = ifelse( T.eq(beta, 2), (T.dot(X, Wsub)) / (T.dot(T.dot(H, W.T), Wsub)), (T.dot(T.mul(T.power(T.dot(H, W.T), (beta - 2)), X), Wsub)) / (T.dot(T.power(T.dot(H, W.T), (beta-1)), Wsub))) return T.mul(Hsub, up)
[docs]def W_beta_sub(X, W, Wsub, H, Hsub, beta): """Update group activation with beta divergence Parameters ---------- X : Theano tensor data W : Theano tensor Bases Wsub : Theano tensor group Bases H : Theano tensor activation matrix Hsub : Theano tensor group activation matrix beta : Theano scalar Returns ------- H : Theano tensor Updated version of the activations """ up = ifelse( T.eq(beta, 2), (T.dot(X.T, Hsub)) / (T.dot(T.dot(H, W.T).T, Hsub)), (T.dot(T.mul(T.power(T.dot(H, W.T), (beta - 2)), X).T, Hsub)) / (T.dot(T.power(T.dot(H, W.T), (beta-1)).T, Hsub))) return T.mul(Wsub, up)
[docs]def W_beta_sub_withcst(X, W, Wsub, H, Hsub, beta, sum_grp, lambda_grp, card_grp): """Update group activation with beta divergence and similarity constraints [1]_. Parameters ---------- X : Theano tensor data W : Theano tensor Bases Wsub : Theano tensor group Bases H : Theano tensor activation matrix Hsub : Theano tensor group activation matrix beta : Theano scalar Returns ------- H : Theano tensor Updated version of the activations """ up = ifelse( T.eq(beta, 2), (T.dot(X.T, Hsub) + lambda_grp * sum_grp) / (T.dot(T.dot(H, W.T).T, Hsub) + lambda_grp * card_grp * Wsub), (T.dot(T.mul(T.power(T.dot(H, W.T), (beta - 2)), X).T, Hsub) + lambda_grp * sum_grp) / (T.dot(T.power(T.dot(H, W.T), (beta-1)).T, Hsub) + lambda_grp * card_grp * Wsub)) return T.mul(Wsub, up)
[docs]def group_H(X, W, H, beta, params): """Group udpate for the activation with beta divergence. Parameters ---------- X : Theano tensor data W : Theano tensor Bases H : Theano tensor activation matrix beta : Theano scalar params : Array :params[1][0]: k_cls number of vectors in the spk bases :params[1][1]: k_ses number of vectors in the session bases :params[0][3]: begining of the group (couple (spk, ses)) in the activation matrix :params[0][4]: end of the group (couple (spk, ses)) in the activation matrix Returns ------- W : Theano tensor Updated version of the bases """ k_cls = params[1][0] k_ses = params[1][1] start = params[0][3] stop = params[0][4] up_cls = H_beta_sub(X, W, W[:, 0:k_cls], H[start:stop, :], H[start:stop, 0:k_cls], beta) up_ses = H_beta_sub(X, W, W[:, k_cls:k_ses+k_cls], H[start:stop, :], H[start:stop, k_cls:k_ses+k_cls], beta) up_res = H_beta_sub(X, W, W[:, k_ses+k_cls:], H[start:stop, :], H[start:stop, k_ses+k_cls:], beta) return T.concatenate((up_cls, up_ses, up_res), axis=1)
[docs]def group_W(X, W, H, beta, params): """Group udpate for the bases with beta divergence and similarity constraints [1]_. Parameters ---------- X : Theano tensor data W : Theano tensor Bases H : Theano tensor activation matrix beta : Theano scalar params : array :params[0][0]: indice of the group to update (corresponding to a unique couple (spk,ses)) :params[1][0]: k_cls number of vectors in the spk bases :params[2]: [lambda1, lambda2] wieght applied on the constraints :params[3]: Sc, ensemble of session in which speaker c is present :params[4]: Cs, ensemble of speakers active in session s :params[1][1]: k_ses number of vectors in the session bases :params[5][0]: cardSc number of elements in Sc :params[5][1]: cardCs number of elements in Cs Returns ------- W : Theano tensor Updated version of the bases """ ind = params[0][0] cardSc = params[5][0] cardCs = params[5][1] k_cls = params[1][0] k_ses = params[1][1] lambdas = params[2] Sc = params[3] Cs = params[4] res_ses, up_ses = theano.scan( fn=lambda Cs, prior_result: prior_result + W[Cs, :, k_cls:k_ses+k_cls], outputs_info=T.zeros_like(W[0, :, k_cls:k_ses+k_cls]), sequences=Cs) res_cls, up_cls = 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) sum_cls = res_cls[-1] sum_ses = res_ses[-1] up_cls_with_cst = W[ind, :, 0:k_cls]*( (T.dot(T.mul(T.power(T.dot(H, W[ind].T), (beta - 2)), X).T, H[:, 0:k_cls]) + lambdas[0] * sum_cls) / (T.dot(T.power(T.dot(H, W[ind].T), (beta-1)).T, H[:, 0:k_cls]) + lambdas[0] * cardSc * W[ind, :, 0:k_cls])) up_cls_without_cst = W[ind, :, 0:k_cls]*( (T.dot(T.mul(T.power(T.dot(H, W[ind].T), (beta - 2)), X).T, H[:, 0:k_cls])) / (T.dot(T.power(T.dot(H, W[ind].T), (beta-1)).T, H[:, 0:k_cls]))) up_ses_with_cst = W[ind, :, k_cls:k_ses+k_cls]*( (T.dot(T.mul(T.power(T.dot(H, W[ind].T), (beta - 2)), X).T, H[:, k_cls:k_ses+k_cls]) + lambdas[1] * sum_ses) / (T.dot(T.power(T.dot(H, W[ind].T), (beta-1)).T, H[:, k_cls:k_ses+k_cls]) + lambdas[1] * cardCs * W[ind, :, k_cls:k_ses+k_cls])) up_ses_without_cst = W[ind, :, k_cls:k_ses+k_cls]*( (T.dot(T.mul(T.power(T.dot(H, W[ind].T), (beta - 2)), X).T, H[:, k_cls:k_ses+k_cls])) / (T.dot(T.power(T.dot(H, W[ind].T), (beta-1)).T, H[:, k_cls:k_ses+k_cls]))) up_cls = ifelse(T.gt(cardSc, 0), up_cls_with_cst, up_cls_without_cst) up_ses = ifelse(T.gt(cardCs, 0), up_ses_with_cst, up_ses_without_cst) up_res = W[ind, :, k_ses+k_cls:]*( (T.dot(T.mul(T.power(T.dot(H, W[ind].T), (beta - 2)), X).T, H[:, k_ses+k_cls:])) / (T.dot(T.power(T.dot(H, W[ind].T), (beta-1)).T, H[:, k_ses+k_cls:]))) return T.concatenate((up_cls, up_ses, up_res), axis=1)
[docs]def noise_W(X, W, Wn, H, beta, params): """Group udpate for the bases with beta divergence in the noise reference case. Only the one session case is considered here. Parameters ---------- X : Theano tensor data W : Theano tensor Bases Wn : Theano tensor noise bases H : Theano tensor activation matrix beta : Theano scalar params : array :params[0][0] : indice of the group to update (corresponding to a unique couple (spk,ses)) :params[1][0]: k_cls number of vectors in the spk bases :params[1][1]: k_ses number of vectors in the session bases :params[2]: [lambda1, lambda2] wieght applied on the constraints :params[3]: Sc, ensemble of session in which speaker c is present :params[5][0]: cardSc number of elements in Sc Returns ------- W : Theano tensor Updated version of the bases """ ind = params[0][0] cardSc = params[5][0] k_cls = params[1][0] k_ses = params[1][1] lambdas = params[2] Sc = params[3] res_cls, up_cls = 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) sum_cls = res_cls[-1] up_cls_with_cst = W[ind, :, 0:k_cls]*( (T.dot(T.mul(T.power(T.dot(H, W[ind].T), (beta - 2)), X).T, H[:, 0:k_cls]) + lambdas[0] * sum_cls) / (T.dot(T.power(T.dot(H, W[ind].T), (beta-1)).T, H[:, 0:k_cls]) + lambdas[0] * cardSc * W[ind, :, 0:k_cls])) up_cls_without_cst = W[ind, :, 0:k_cls]*( (T.dot(T.mul(T.power(T.dot(H, W[ind].T), (beta - 2)), X).T, H[:, 0:k_cls])) / (T.dot(T.power(T.dot(H, W[ind].T), (beta-1)).T, H[:, 0:k_cls]))) up_ses = W[ind, :, k_cls:k_ses+k_cls]*( (T.dot(T.mul(T.power(T.dot(H, W[ind].T), (beta - 2)), X).T, H[:, k_cls:k_ses+k_cls]) + lambdas[1] * Wn) / (T.dot(T.power(T.dot(H, W[ind].T), (beta-1)).T, H[:, k_cls:k_ses+k_cls]) + lambdas[1] * W[ind, :, k_cls:k_ses+k_cls])) up_cls = ifelse(T.gt(cardSc, 0), up_cls_with_cst, up_cls_without_cst) up_res = W[ind, :, k_ses+k_cls:]*( (T.dot(T.mul(T.power(T.dot(H, W[ind].T), (beta - 2)), X).T, H[:, k_ses+k_cls:])) / (T.dot(T.power(T.dot(H, W[ind].T), (beta-1)).T, H[:, k_ses+k_cls:]))) return T.concatenate((up_cls, up_ses, up_res), axis=1)
[docs]def group_W_nosum(X, W, H, sum_cls, sum_ses, beta, params): """Group udpate for the bases with beta divergence The contribution for the class similiraity constraint and the session similarity constraint are computed externally. This could be used for example to distribute the porcessing. The constraint are computed centrally once per epoch and the rest of the processing can be distributed. Parameters ---------- X : Theano tensor data W : Theano tensor Bases H : Theano tensor activation matrix beta : Theano scalar sum_cls : Theano scalar contribution from the class similarity constraint sum_ses : Theano scalar contribution from the session similarity constraint params : array :params[0][0]: indice of the group to update (corresponding to a unique couple (spk,ses)) :params[1][0]: k_cls number of vectors in the spk bases :params[1][1]: k_ses number of vectors in the session bases :params[2]: [lambda1, lambda2] wieght applied on the constraints :params[3]: Class distance :params[4]: session distance :params[5][0]: cardSc number of elements in Sc :params[5][1]: cardCs number of elements in Cs Returns ------- W : Theano tensor Updated version of the bases """ ind = params[0][0] cardSc = params[3][0] cardCs = params[3][1] k_cls = params[1][0] k_ses = params[1][1] lambdas = params[2] up_cls = W[ind, :, 0:k_cls]*( (T.dot(T.mul(T.power(T.dot(H, W[ind].T), (beta - 2)), X).T, H[:, 0:k_cls]) + lambdas[0] * sum_cls) / (T.dot(T.power(T.dot(H, W[ind].T), (beta-1)).T, H[:, 0:k_cls]) + lambdas[0] * cardSc * W[ind, :, 0:k_cls])) up_ses = W[ind, :, k_cls:k_ses+k_cls]*( (T.dot(T.mul(T.power(T.dot(H, W[ind].T), (beta - 2)), X).T, H[:, k_cls:k_ses+k_cls]) + lambdas[1] * sum_ses) / (T.dot(T.power(T.dot(H, W[ind].T), (beta-1)).T, H[:, k_cls:k_ses+k_cls]) + lambdas[1] * cardCs * W[ind, :, k_cls:k_ses+k_cls])) up_res = W[ind, :, k_ses+k_cls:]*( (T.dot(T.mul(T.power(T.dot(H, W[ind].T), (beta - 2)), X).T, H[:, k_ses+k_cls:])) / (T.dot(T.power(T.dot(H, W[ind].T), (beta-1)).T, H[:, k_ses+k_cls:]))) return T.concatenate((up_cls, up_ses, up_res), axis=1)