# VB NMF Example

← All NMath Code Examples

```Imports System
Imports System.Text
Imports System.Collections.Generic

Imports CenterSpace.NMath.Core

Imports System.IO

Namespace CenterSpace.NMath.Examples.VisualBasic

A .NET example in Visual Basic illustrating Non-negative Matrix Factorization (NMF)
Module NMFExample

Sub Main()
Load the example data into a DataFrame
Dim Frame As DataFrame = DataFrame.Load("NMFExample.dat", False, False, ",", True)

Construct a Nonnegative Matrix Factorization object that will perform 200
iterations when computing the factors.
Dim Fact As NMFact = New NMFact(200)

Now, perform the factorization data = WH Imports the the default initial
initial values for WH (which are uniform random in (0, 1) ), the default
update algorithm (NMFMultiplicativeUpdate) and k = 2.
Fact.Factor(Frame, 2)

Look at the results. Note that since the initial values for W and H are
random, the results will not be exactly the same on each run of the
program.
Console.WriteLine()
Console.WriteLine("Output 0, Default initial W, H, and algorithm -----------------")
PrintResults(Fact)
Note that the values of W and H are not close to the expected values

Set up some initial values for W and H so we can play with some of the
factorizations parameters and observe the effects without the random
variations induced by random initial values.
Dim RNG As RandGenUniform = New RandGenUniform(124)
Dim initialW As DoubleMatrix = New DoubleMatrix(3, 2, RNG)
Dim initialH As New DoubleMatrix(2, 4, RNG)

Factor and print the results
Fact.Factor(Frame, 2, initialW, initialH)
Console.WriteLine()
Console.WriteLine()
Console.WriteLine("Output 1 -------------------------------------------------------")
PrintResults(Fact)

Note that the factorization is pretty darn good - the cost function
is on the order of 10e-18 and the difference of the elements of WH
and V are all on the order of 10e-9 or 10e-10. But we are not close
to the expected results. This shows the non-uniqueness of NMF
solutions. Lets up the number of iterations to, say, 1000 and see
if our factorization improves:
Fact.NumIterations = 1000
initialW = New DoubleMatrix(3, 2, RNG)
initialH = New DoubleMatrix(2, 4, RNG)
Fact.Factor(Frame, 2, initialW, initialH)
Console.WriteLine()
Console.WriteLine()
Console.WriteLine("Output 2, 1000 iterations ----------------------------------")
PrintResults(Fact)

Cost goes way down, all the elements of V - WH are 0 or on the order
of 10e-15 - thats basically 0 within the limits of a double precision
number (15 significant digits). Within machine precision, the
factorization is exact and the solution is definitely a local minimum
of the function ||V - WH||. Lets try and make it converge to the
expected solution by setting the initial values very close to the
expected values.
initialW = New DoubleMatrix("3x2[1 5  2 1  3 4]")
initialW = initialW + 0.01
initialH = New DoubleMatrix("2x4[1 4 3 2  8 1 2 7]")
initialH = initialH - 0.01
Fact.Factor(Frame, 2, initialW, initialH)
Console.WriteLine()
Console.WriteLine()
Console.WriteLine("Output 3, initial W, H close to expected values --------------------")
PrintResults(Fact)

Wow. We still converge to the same solution as before. That solution
must be a very strong attractor for this algorithm. Lets try a
different algorithm. The GD-CLS algorithm uses the multiplicative
method, which is basically a version of the gradient descent (GD)
optimization scheme, to approximate the basis vector matrix W. H
is calculated Imports a constrained least squares (CLS).
Fact.UpdateAlgorithm = New NMFGdClsUpdate()
Dim delta As Double = 0.01
initialW = New DoubleMatrix("3x2[1 5  2 1  3 4]")
initialW = initialW + delta
initialH = New DoubleMatrix("2x4[1 4 3 2  8 1 2 7]")
initialH = initialH + delta
Fact.Factor(Frame, 2, initialW, initialH)
Console.WriteLine()
Console.WriteLine()
Console.WriteLine("Output 4, GD-CLS algorithm initial W, H close to expected values -----")
PrintResults(Fact)

Now, thats more like it. We can find the expected solution if we
out right on top of it.

Console.WriteLine()
Console.WriteLine("Press Enter Key")
End Sub

Sub PrintResults(ByVal Fact As NMFact)
Matrices rounded for better legibility

Look at the results:
Console.WriteLine()
Console.WriteLine("Factored Matrix: ")
Console.WriteLine(Fact.V.ToTabDelimited("G5"))
Console.WriteLine()
Console.WriteLine("W: ")
Console.WriteLine(Fact.W.ToTabDelimited("G5"))
Console.WriteLine()
Console.WriteLine("H: ")
Console.WriteLine(Fact.H.ToTabDelimited("G5"))
Console.WriteLine()
Console.WriteLine("Cost (error) = " & Fact.Cost)

Look at the product of the factors and the difference from
the factored matrix V
Dim WH As DoubleMatrix = NMathFunctions.Product(Fact.W, Fact.H)
Dim D As DoubleMatrix = Fact.V - WH
Console.WriteLine()
Console.WriteLine("WH = ")
Console.WriteLine(WH.ToTabDelimited("G5"))
Console.WriteLine()
Console.WriteLine("V - WH = ")
Console.WriteLine(D.ToTabDelimited("G5"))
Console.WriteLine()

End Sub
End Module
End Namespace

```
← All NMath Code Examples
Top