Blog Archives

Testing and Validation CNTK models using C#


…continue from the previous post.
Once the model is build and Loss and Validation functions are satisfied our expectation, we need to validate and test the model using the data which was not part of the training data set (unseen data). The model validation is very important because we want to see if our model is trained well,so that can evaluates unseen data approximately same as the training data. Otherwise the model which cannot predict the output is called overfitted model. Overfitting can happen when the model was trained long enough that shows very high performance for the training data set, but for the testing data evaluate bad results.
We will continue with the implementation from the prevision two posts, and implement model validation. After the model is trained, the model and the trainer are passed to the Evaluation method. The evaluation method loads the testing data and calculated the output using passed model. Then it compares calculated (predicted) values with the output from the testing data set and calculated the accuracy. The following source code shows the evaluation implementation.

private static void EvaluateIrisModel(Function ffnn_model, Trainer trainer, DeviceDescriptor device)
{
    var dataFolder = "Data";//files must be on the same folder as program
    var trainPath = Path.Combine(dataFolder, "testIris_cntk.txt");
    var featureStreamName = "features";
    var labelsStreamName = "label";

    //extract features and label from the model
    var feature = ffnn_model.Arguments[0];
    var label = ffnn_model.Output;

    //stream configuration to distinct features and labels in the file
    var streamConfig = new StreamConfiguration[]
        {
            new StreamConfiguration(featureStreamName, feature.Shape[0]),
            new StreamConfiguration(labelsStreamName, label.Shape[0])
        };

    // prepare testing data
    var testMinibatchSource = MinibatchSource.TextFormatMinibatchSource(
        trainPath, streamConfig, MinibatchSource.InfinitelyRepeat, true);
    var featureStreamInfo = testMinibatchSource.StreamInfo(featureStreamName);
    var labelStreamInfo = testMinibatchSource.StreamInfo(labelsStreamName);

    int batchSize = 20;
    int miscountTotal = 0, totalCount = 20;
    while (true)
    {
        var minibatchData = testMinibatchSource.GetNextMinibatch((uint)batchSize, device);
        if (minibatchData == null || minibatchData.Count == 0)
            break;
        totalCount += (int)minibatchData[featureStreamInfo].numberOfSamples;

        // expected labels are in the mini batch data.
        var labelData = minibatchData[labelStreamInfo].data.GetDenseData<float>(label);
        var expectedLabels = labelData.Select(l => l.IndexOf(l.Max())).ToList();

        var inputDataMap = new Dictionary<Variable, Value>() {
            { feature, minibatchData[featureStreamInfo].data }
        };

        var outputDataMap = new Dictionary<Variable, Value>() {
            { label, null }
        };

        ffnn_model.Evaluate(inputDataMap, outputDataMap, device);
        var outputData = outputDataMap[label].GetDenseData<float>(label);
        var actualLabels = outputData.Select(l => l.IndexOf(l.Max())).ToList();

        int misMatches = actualLabels.Zip(expectedLabels, (a, b) => a.Equals(b) ? 0 : 1).Sum();

        miscountTotal += misMatches;
        Console.WriteLine($"Validating Model: Total Samples = {totalCount}, Mis-classify Count = {miscountTotal}");

        if (totalCount >= 20)
            break;
    }
    Console.WriteLine($"---------------");
    Console.WriteLine($"------TESTING SUMMARY--------");
    float accuracy = (1.0F - miscountTotal / totalCount);
    Console.WriteLine($"Model Accuracy = {accuracy}");
    return;

}

The implemented method is called in the previous Training method.

 EvaluateIrisModel(ffnn_model, trainer, device);

As can be seen the model validation has shown that the model predicts the data with high accuracy, which is shown on the following picture.

This was the latest post in series of blog posts about using Feed forward neural networks to train the Iris data using CNTK and C#.

The full source code for all three samples can be found here.

Advertisements

Train Iris data by Batch using CNTK and C#


In the previous post we have seen how to train NN model by using MinibatchSource. Usually we should use it when we have large amount of data. In case of small amount of the data, all data can be loaded in memory, and all can be passed to each iteration in order to train the model. This blog post will implement this kind of feeding the trainer.
We will reused the previous implementation, so the starting point can be previous source code. For data loading we have to define a new method. The Iris data is stored in text format like the following:

sepal_length,sepal_width,petal_length,petal_width,species
5.1,3.5,1.4,0.2,setosa(1 0 0)
7.0,3.2,4.7,1.4,versicolor(0 1 0)
7.6,3.0,6.6,2.1,virginica(0 0 1)
...

The output column is encoded to 1-N-1 encoding rule we have seen previously.
The method will read all the data from the file, parse the data and create two float arrays:

  • float[] feature, and
  • float[] label.

As can be seen both arrays are 1D, which means all data will be inserted in 1D, because the CNTK requires so.  Since the data is in 1D array, we should also provide the dimensionality of the data so te CNTK can resolve what values for each features. The following listing shows the loading Iris data in two 1D array returned as tuple.

static (float[], float[]) loadIrisDataset(string filePath, int featureDim, int numClasses)
{
    var rows = File.ReadAllLines(filePath);
    var features = new List<float>();
    var label = new List<float>();
    for (int i = 1; i < rows.Length; i++)
    {
        var row = rows[i].Split(',');
        var input = new float[featureDim];
        for (int j = 0; j < featureDim; j++)
        {
            input[j] = float.Parse(row[j], CultureInfo.InvariantCulture);
        }
        var output = new float[numClasses];
        for (int k = 0; k < numClasses; k++)
        {
            int oIndex = featureDim + k;
            output[k] = float.Parse(row[oIndex], CultureInfo.InvariantCulture);
        }

        features.AddRange(input);
        label.AddRange(output);
    }

    return (features.ToArray(), label.ToArray());
}

Once the data is loaded we should change very little amount of the previous code in order to implement batching instead of using minibatchSource. At the beginning we provides several variable to define the NN model structure. Then we call the loadIrisDataset, and define xValues and yValues, which we use in order to create feature and label input variables. Then we create dictionary which connect the feature and labels with data values which we will pass to the trainer later.
The next code is the same as in the previous version in order to create NN model, Loss and Evaluation functions, and learning rate.

Then we create loop, for 800 iteration. Once the iteration reaches the maximum value the program outputs the model properties and terminates.
Above said it implemented in the following code.

public static void TrainIriswithBatch(DeviceDescriptor device)
{
    //data file path
    var iris_data_file = "Data/iris_with_hot_vector.csv";

    //Network definition
    int inputDim = 4;
    int numOutputClasses = 3;
    int numHiddenLayers = 1;
    int hidenLayerDim = 6;
    int sampleSize = 130;

    //load data in to memory
    var dataSet = loadIrisDataset(iris_data_file, inputDim, numOutputClasses);

    // build a NN model
    //define input and output variable
    var xValues = Value.CreateBatch<float>(new NDShape(1, inputDim), dataSet.Item1, device);
    var yValues    = Value.CreateBatch<float>(new NDShape(1, numOutputClasses), dataSet.Item2, device);

    // build a NN model
    //define input and output variable and connecting to the stream configuration
    var feature = Variable.InputVariable(new NDShape(1, inputDim), DataType.Float);
    var label = Variable.InputVariable(new NDShape(1, numOutputClasses), DataType.Float);

    //Combine variables and data in to Dictionary for the training
    var dic = new Dictionary<Variable, Value>();
    dic.Add(feature, xValues);
    dic.Add(label, yValues);

    //Build simple Feed Froward Neural Network model
    // var ffnn_model = CreateMLPClassifier(device, numOutputClasses, hidenLayerDim, feature, classifierName);
    var ffnn_model = createFFNN(feature, numHiddenLayers, hidenLayerDim, numOutputClasses, Activation.Tanh, "IrisNNModel", device);

    //Loss and error functions definition
    var trainingLoss = CNTKLib.CrossEntropyWithSoftmax(new Variable(ffnn_model), label, "lossFunction");
    var classError = CNTKLib.ClassificationError(new Variable(ffnn_model), label, "classificationError");

    // set learning rate for the network
    var learningRatePerSample = new TrainingParameterScheduleDouble(0.001125, 1);

    //define learners for the NN model
    var ll = Learner.SGDLearner(ffnn_model.Parameters(), learningRatePerSample);

    //define trainer based on ffnn_model, loss and error functions , and SGD learner
    var trainer = Trainer.CreateTrainer(ffnn_model, trainingLoss, classError, new Learner[] { ll });

    //Preparation for the iterative learning process
    //used 800 epochs/iterations. Batch size will be the same as sample size since the data set is small
    int epochs = 800;
    int i = 0;
    while (epochs > -1)
    {
        trainer.TrainMinibatch(dic, device);

        //print progress
        printTrainingProgress(trainer, i++, 50);

        //
        epochs--;
    }
    //Summary of training
    double acc = Math.Round((1.0 - trainer.PreviousMinibatchEvaluationAverage()) * 100, 2);
    Console.WriteLine($"------TRAINING SUMMARY--------");
    Console.WriteLine($"The model trained with the accuracy {acc}%");
}

If we run the code, the output will be the same as we got from the previous blog post example:

The full source code with training data can be downloaded
here.

Using SSH Keys for License generation and validation in .NET Applications


license_generationpng

This blog post is going to present how can you implement license functionality in your .NET application. Providing license in your .NET application is very challenging because there is no standard procedure for the implementation. You are free to use whatever you want. But be notice, there is no license which is 100% safe and cannot be cracked or bypassed.

For this purpose I have selected the CocoaFob library for registration code generation and verification in Objective-C applications. Mainly the library is for Objective -C based applications, like iQS mobile applications and other OSX based applications.  This is very interesting library but you cannot use it in .NET applications, there is no implementation for .NET Framework.

The library uses DSA to generate registration keys, which is very hard for hackers to produce key generators. The library is also specific because it generates license key in human readable form, when the bytes are converted in to Base32 string to avoid ambiguous characters. It also groups codes in sets of five characters separated by dashes. Also DSA has encryption algorithm generates the license which is different every time because of a random element introduced during the process.

So the License key is produced using a 512-bit DSA key looks like on the following sample:

GAWQE-FCUGU-7Z5JE-WEVRA-PSGEQ-Y25KX-9ZJQQ-GJTQC-CUAJL-ATBR9-WV887-8KAJM-QK7DT-EZHXJ-CR99C-A

More information about CocoaFob can be found at GitHub page: https://github.com/glebd/cocoafob

The library is using BouncyCastle.Crypto Nuget package for DSA encryption and decryption.

The library CocoaFob for .NET contains two classes:

  1. LicenseData class which provide License properties which is used in license generation. It an be anything: Name, Product number, email, date of expiration etc.
  2. LicenseGenerator  class which is responsible for encrypting and validating the license.

For this blog post the License data class has the flowing implementation:

public class LicenseData
{

protected internal string productCode;
protected internal string name;
protected internal string email;

public virtual string toLicenseStringData()
{
 StringBuilder result = new StringBuilder();
 if (productCode != null)
 {
 result.Append(productCode);
 result.Append(',');
 }

 //name is mandatory property
 if (name == null)
 throw new System.Exception("name cannot be null");
 result.Append(name);

 if (email != null)
 {
 result.Append(',');
 result.Append(email);
 }
 return result.ToString();
}
......
}

As can be seen from the code snippet above the License data contains username, product key and email address. Also, only name property is mandatory, which means you can generate license key based on the user name only.

Generating the License Key

One we have License data we can process of License key generation. License is generated using DSA encryption which uses SSH private key.  You can generate public and private SSH keys  using any of the available tools, eg. OpenSSH, GitHub bash, …. More information about private and public key generation you can find at this link. Once we have public and private keys we can generate license and validate it. One important thing to remember is that you have to care about your private key. It should always be secure and no one should have access to it.

The public key is used for license validation, and it is usualy packed with the application as a part of the deployment stuff. So the process of generating the license is show on the flowing code snippet:

public string makeLicense(LicenseData licenseData)
{
     if (!CanMakeLicenses)
     {
       throw new System.InvalidOperationException("The LicenseGenerator cannot make licenses as it was not configured with a private key");
     }
     try
     {
        //
        var dsa = SignerUtilities.GetSigner("SHA1withDSA");
        dsa.Init(true, privateKey);
        //
        string stringData = licenseData.toLicenseStringData();
        byte[] licBytes = Encoding.UTF8.GetBytes(stringData);
        dsa.BlockUpdate(licBytes, 0, licBytes.Length);
        //
        byte[] signed = dsa.GenerateSignature();
        string license = ToLicenseKey(signed);
        return license;
    }
    catch (Exception e)
    {
        throw new LicenseGeneratorException(e);
    }
}

First the DSA encryption is created based on the publicKey we have provided as an argument. Then licBytes is generated from the License data, and converted in to UTF8 formatted bytes. Then we have update DSA provider with licBytes. Now the DSA provider can generate signature in bytes. The signature is converted in to LicenseKey by calling ToLicenseKey method. The method is shown on the following code snippet:

private string ToLicenseKey(byte[] signature)
{
    /* base 32 encode the signature */
    var result = Base32.ToString(signature);

    /* replace O with 8 and I with 9 */
    result = result.Replace("O", "8").Replace("I", "9");

    /* remove padding if any. */
    result = result.Replace("=", "");
           

    /* chunk with dashes */
    result = split(result, 5);
    return result;
}

The magic happen in this method during the conversion of signature from bytes to human readable string. Conversion is done using Base32 string helper method.

Verify the License Key

The License verification process is defined in varifyLicense method. You have to provide SSH publicKey as well as

public virtual bool verifyLicense(LicenseData licenseData, string license)
{
	if (!CanVerifyLicenses)
	{
		throw new System.InvalidOperationException("The LicenseGenerator cannot verify licenses as it was not configured with a public key");
	}
    try
     {
        //Signature dsa = Signature.getInstance("SHA1withDSA", "SUN");
        var dsa = SignerUtilities.GetSigner("SHA1withDSA");
        dsa.Init(false, publicKey);

        //
        string stringData = licenseData.toLicenseStringData();
        byte[] msgBytes = Encoding.UTF8.GetBytes(stringData);
        dsa.BlockUpdate(msgBytes, 0, msgBytes.Length);


        var dec = FromLicenseKey(license);
        var retVal = dsa.VerifySignature(dec);
        //
        return retVal; 
	}
    catch (Exception e)
    {
        throw new LicenseGeneratorException(e);
    }
}

As can be seen from the code above, the validation process is done by generating licenseData, converting the license Key in to signatere and the validation process return true is the license is valid, otherwize return false.

The whole project is published at git hub, an can be downloaded from http://github.com/bhrnjica/cocoafob

 

Testing the Library

The Library solution contains unit test project which you can see how to use this library in the real scenario in order to implement licensing in .NET app.

Happy programming!

Silverlight 4 Business Application Part 3 of n


Implementation of the Login Dialog in Silverlight application by using MVVM pattern

imageIn the third article, of the series of the Silvelright Business application development, I will present Login dialog implementation by applying  MVVM pattern. Problems looks very simple but if you want to implement in MVVM fashion you could encounter some problems. MVVM pattern became very popular in Silverlight and WPF application development and it seams to be standard development pattern. More information about the pattern can be found on various blogs, internet sites and forums.  One of the first and the best article about MVVM patern is MSND article about MVVM patern by Josh Smith and it can be found here.

This tutorial assume that you know basic principles of the MVVM pattern as well as Silverlight application.

In tis tutorial we will use the MVVM toolkit the implementation of the MVVM pattern developed by Laurent Bugnion, which you can download at http://mvvmlight.codeplex.com/. Before we start the tutorial, download the toolkit and install it as it decribed on the codeplex site.

The idea of the Login dialog, presented here, not depends of the MVVM light toolkit, so it can be easily implemented with other MVVM pattern, like PRISM and others.

Start Visual Studio 2010, and select File->New –>Project, select Silverlight Application in the same way we implemented in Part 2. Instead of Silverlight Aplication, select MvvmLight (SL4) template as picture below shows. After we choose the template, and click OK, Visual Studio designer created Silverlight application which support MVVM pattern.

The picture below shows The New Project dialog window:

image

As you can see Visual Studio created Silverlight application, but not the ASP.NET web application project. For this tutorial we don’t need it.

image

The picture above shows project files and how files are arranged in the project. The folder ViewModel contains the ViewModels implementations. Lets create View folder, it will contain Views implementation.

Implementation of MainView and MainViewModel

MainViewContent will be our main content for the Silverlight application. It will be shown after we logged in.

1. Right Click on the recently created View folder, and choose Add->New Item

2. Select Silverlight User Control and give it name MainViewContent.xaml

image

3. In the XAML file put the following code:

<Grid x:Name="LayoutRoot" Background="White">
        <TextBlock Text="MAIN CONTENT OF THE SILVERLIGHT APPLICATION"
                   HorizontalAlignment="Center"
                   VerticalAlignment="Top"
                   FontSize="16" FontFamily="Arial Black" />
</Grid>

Implementation is simple. Just TextBlox with some text.

Now we need to create MainViewModelContent:

4. Right Click on the ViewModel folder, and choose Add->New Class

5. Name it MainViewModelContent.cs

Implementation of the MainViewModelContent is in the following listing:

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using GalaSoft.MvvmLight;

namespace SLPart3MvvmLoginDialog.ViewModel
{
    public class MainViewModelContent : ViewModelBase
    {

    }
}

The implementation is empty cause we want the empty view model without interaction with the view .

Implementation of LoginView and LoginViewModel

Similar as previous we create LoginView.Xaml and LoginViewModel.cs.

Xaml implementation of the LoginView contains controls and layout depicted in the first picture of the article. Here is the main xaml code:

<Border BorderThickness="1" BorderBrush="Black">
        <Grid x:Name="LayoutRoot1" Background="White">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*" />
                <ColumnDefinition Width="120" />
                <ColumnDefinition Width="120" />
                <ColumnDefinition Width="*" />
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="40" />
                <RowDefinition Height="30" />
                <RowDefinition Height="28" />
                <RowDefinition Height="28" />
                <RowDefinition Height="40" />
                <RowDefinition Height="28" />
                <RowDefinition Height="*" />
            </Grid.RowDefinitions>

            <Rectangle x:Name="rectangle1" Stroke="Black" StrokeThickness="1" Fill="#FFDE8836" Grid.ColumnSpan="4" />
            <TextBlock Grid.Row="2" x:Name="textBlock2" Text="User Name:" Padding="5" HorizontalAlignment="Right"
                       VerticalAlignment="Center" Grid.Column="1" Margin="0,9" />
            <TextBlock x:Name="textBlock3" Text="Password:" Grid.Row="3" Padding="5" HorizontalAlignment="Right"
                       VerticalAlignment="Center" Grid.Column="1" Margin="0,9" />
            <TextBox Grid.Column="2" Grid.Row="2" x:Name="textBox1" Margin="2" Text="{Binding UserName, Mode=TwoWay}" />
            <PasswordBox Grid.Column="2" Grid.Row="3" x:Name="passwordBox1" Margin="2"  Password="{Binding Password, Mode=TwoWay}"/>

            <Button Content="Cancel" Grid.Column="1" Grid.Row="5" x:Name="radButton1" Margin="5,2" />
            <Button Content="Login" x:Name="radButton2" Grid.Column="2" Grid.Row="5" Margin="5,2" >
                <i:Interaction.Triggers>
                    <i:EventTrigger EventName="Click">
                        <mvvmcmd:EventToCommand Command="{Binding LoginCommand, Mode=OneWay}"
                                CommandParameter="{Binding Main, Source={StaticResource Locator}}"/>
                    </i:EventTrigger>
                </i:Interaction.Triggers>
            </Button>
            <TextBlock x:Name="textBlock1" Text="Login Dialog" VerticalAlignment="Center" HorizontalAlignment="Center"
                       Grid.ColumnSpan="2" Margin="10,5,5,12" Grid.Column="1" FontFamily="Portable User Interface"
                       FontSize="20" FontStretch="SemiCondensed" FontWeight="SemiBold" Foreground="Black"/>
        </Grid>
</Border>

The main part of this xaml code above is that the MainViewModel is passed as a parameter of the Login button EventToCommand, and if the login is correct, the LoginModelView change IsLoggedIn property to true. Then main page switch the visibility property of the LoginView to Collapsed, and MainContentView to Visible.

Implementation of the LoginViewModel.cs is show on the next listing:

//Constructor
public LoginViewModel()
  {
    this.LoginCommand = new RelayCommand<object>(this.OnLogging, this.CanLogging);
  }
//Wnen the user click Login button in LoginView
private void OnLogging(object arg)
  {
   var vm = arg as MainViewModel;
   if (vm == null)
      return;

   //proces of logging
   vm.IsLogged = true;
   }

private bool CanLogging(object arg)
   {

     return true;
   }

ModelView coresponding classes is always derived from the ModelViewBase.

Putting all together in MainPage and ManViewModel

Now, when you implemented Login  and MainContent, we need put these objects in to MainPage. The MainPage is responsible of showing and hiding these views.

Implementation of the MainPage.xaml

<Grid x:Name="LayoutRoot">

        <my:MainViewContent Visibility="{Binding Main.IsLogged,
                      ConverterParameter=mainView,
                      Converter={StaticResource MainPageBoolLoginToVisibilityConverter1},
                      Source={StaticResource Locator}}"/>
            <my:LoginView Visibility="{Binding Main.IsLogged,
            ConverterParameter=loginView,
            Converter={StaticResource MainPageBoolLoginToVisibilityConverter1},
            Source={StaticResource Locator}}" HorizontalAlignment="Center" VerticalAlignment="Center" />
    </Grid>

Implementation of the MainViewModel

public const string IsLoggedPropertyName = "IsLogged";
private bool _islogged;
public bool IsLogged
 {
   get
    {
      return _islogged;
    }
   set
    {
      if (value != _islogged)
      {
        _islogged = value;
        RaisePropertyChanged(IsLoggedPropertyName);
      }
    }
  }

public MainViewModel()
  {
    if (IsInDesignMode)
    {
     // Code runs in Blend --> create design time data.
    }
    else
    {
     // Code runs "for real"
    }
}

As you can see we implemented IsLogged property, which is the switch between Login and MainViewContent. With BoolToVisibilityConverter class, we were implemented changing visibility of the Views. The converter class is in the source code of the project attached with this tutorial.
Now at the end we have to implement LoginVieModel and MainContentViewModel in to Locator class.
The implementation is very simple and you can see it in the sourcecode project. Now run the application and clik the Login button, The MainContentView appears.

Summary

This article present the simple technique you can easily implement in your Silverlight application with full fashion of the MVVM pattern.

The source code can be download from  here.