# VB NMF Example

← All NMath Core Code Examples

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

Imports CenterSpace.NMath.Core
Imports System.IO

Namespace CenterSpace.NMath.Core.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. Let's 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 - that's 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||. Let's 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. Let's 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, that's 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 Stats Code Examples
Top