User-Defined Functions/User-defined function examples

This page collects examples of function implementations for educational purposes, to illustrate various concepts related to parameter declaration, syntax, array abstraction, etc.

Non-negative matrix factorization

Also known as positive matrix factorization. See the article Non-negative matrix factorization for more information on what this factorization is and its uses. The algorithm here uses Lee and Seung's multiplicative update rule which is described in that article.

Given a source matrix of non-negative values, [math]\displaystyle{ A }[/math], decompose it into two matrices [math]\displaystyle{ W }[/math] and [math]\displaystyle{ H }[/math] so that [math]\displaystyle{ A=WH }[/math]. These new matrices have a new latent dimension not shared by A, which is usually smaller that either index of A.

Function NMF( a : NonNegative [I,J] ; I,J,K : Index ; iterations : number atom=30) ::= 
	Local w[I, K] := Random(over:I,K);
	Local h[K, J] := Random(over:K,J);
	Local ϵ := 1e-9;  { small epsilon to avoid division by zero }
	 
	For n:=1..iterations Do (
		{ Update H based on W }
		h := Relu(h * (Sum(w*a, I) / Max([ϵ,Sum( w * Sum(w*h, K),I)])));
		{ Update W based on H }
		w := Relu(w * (Sum(a*h, J) / Max([ϵ,Sum( Sum(w*h,K) * h, J)])));
	);
	_(w,h)

Download: Non-Negative Matrix Factorization.ana

The example model contains an example usage of this function.

Many Analytica concepts are demonstrated in this example.

The parameter qualifiers for «a» demonstrate both a data type qualifier (NonNegative) as well as explicit dimensionality, [I, J], in which the I and J refer to the second and third parameters of the function.

The first two lines initialize matrices w and h to i.i.d. random numbers between 0 and 1. The dimensionality declaration on the variable names is optional, but can help to catch mistakes.

The For..Do syntax illustrates how to iterate from 1 to «iterations».

The use of Relu(x) shows a shortcut for the equivalent Max( [0, x] ). The uses of Max( [ϵ, x ]) demonstrate how to find the largest of two or more values by providing both to the first parameter of Max as a list using brackets.

The iterative loop demonstrates iterative assignments to local variables, a side-effect that is allowed in Analytica.

Finally, the last line shows how to return two values from a function (which have different dimensionality) using the underscore function, _(w, h), which is synonymous with MultiResult(w,h). The caller would capture these using, e.g.,

Local (w,h) := NMF( A, I,J,K );

The example model demonstrates how to conveniently capture these in two global variables using ComputedBy.

Comments


You are not allowed to post comments.