Microsoft Cognitive Toolkit + VS Code = Awesome

Hello World!

In this article I’m going to go through how to set up CNTK with Visual Studio Code and take advantage of those PASCAL GPUs I know everybody has these days.  I will also do a breif overview of what CNTK and Visual Studio Code are and why they are so incredible for machine learning scientists.

CNTKIntellisense

What is Microsoft Cognitive Toolkit (CNTK)

CNTK is Microsoft’s deep learning tool kit.  Everybody is hot on Tensor Flow and Keras and Theano, but did you know that Microsoft has been doing deep learning since before it was cool?  Microsoft has been doing A.I. almost since its inception and well, CNTK is a result of over 40 years of R&D.  Multi GPU, Multi Node, blazing performance.  It is used internally at Microsoft to build all of the amazing algorithms that are surfaced in nearly every product.  Not only this, I can install it via script in less than 30 minutes with 2 or 3 button clicks, get Jupyter Notebooks with Tutorials AND it runs on Windows 10!  Thank goodness a hardcore multi-gpu, multi-node easy to use framework that works in the same environment I do my day to day business.  No more needs for dual booting and dealing with complicated configuration that I don’t understand.  Here is the process I used to get CNTK installed.  Here are steps for other platforms.

What is Visual Studio Code

Visual Studio Code is a light weight almost sublime like environment for coding in a variety of languages.  There are a few key reasons I’m drawn to Visual Studio Code.

  1. The Python Extension by Don is amazing.
  2. Intellisense! Intellisense! Intellisense!
  3. Streamlined Jupyter Integration
  4. Works with CNTK, Keras, on Linux
  5. Folder Structure Based (no .pyproj or .sln files)

What does this mean?  From a Scientist’s perspective its basically a happy hybrid between Anaconda’s Spyder (with better intellisense and way faster), Sublime, and PyCharm.  Visual Studio Code takes the best of each of these environments and mashes it together.  How does it do this?  Well, perhaps its just me, but my coding workflow is:

  1. Write some code in a cell block to figure out how the algorithm works.
  2. Maybe have a folder dedicated to model development.
  3. Have a folder for model inference libraries.
  4. Its all being delivered via Flask eventually.
  5. I can write code in the cell blocks, get it working, migrate it to the production library section, run it interactively to check that it works and move on.
  6. Yeah, I probably do charts some where in there to check model performance.

How to Configure VS Code to use CNTK

Alright, so I’m assuming you got both up and running and you figured out how to install the Python Tools for Visual Studio Code.  From here its pretty easy.  Pick your folder.

  1. From Visual Studio Code.  File -> Open Folder
    1. This is your root folder for the project (mine was C:\projects\ML\CNTK)
  2. Create 2 new files inside the .vscode folder that is created
    1. launch.json
    2. settings.json
    3. folderstructure_CNTK_VSCode
  3. Add this exact code to both:
    1. {
          "python.pythonPath": "C:\\local\\Anaconda3-4.1.1-Windows-x86_64\\envs\\cntk-py34\\python"
      }
    2. This code is correct unless you changed the install path for CNTK’s Anaconda, but you should just accept default locations so all tutorials work out well.
  4. In your environment variables for your system, add the following path: “c:\local\cntk\cntk”
    1. Again this is based on the install path for cntk, I extracted to c:\local just like the install tutorial on CNTK’s github page.

At this point you are ready to test.  Try out this code to see if it works:

#%%
# Import the relevant components
import numpy as np
import sys
import os
from cntk import Trainer, cntk_device, StreamConfiguration, learning_rate_schedule, UnitType
from cntk.device import cpu, set_default_device
from cntk.learner import sgd
from cntk.ops import *

# Define the network
input_dim = 2
num_output_classes = 2

np.random.seed(0)

# Helper function to generate a random data sample
def generate_random_data_sample(sample_size, feature_dim, num_classes):
    # Create synthetic data using NumPy. 
    Y = np.random.randint(size=(sample_size, 1), low=0, high=num_classes)

    # Make sure that the data is separable 
    X = (np.random.randn(sample_size, feature_dim)+3) * (Y+1)
    
    # Specify the data type to match the input variable used later in the tutorial 
    # (default type is double)
    X = X.astype(np.float32)    
    
    # converting class 0 into the vector "1 0 0", 
    # class 1 into vector "0 1 0", ...
    class_ind = [Y==class_number for class_number in range(num_classes)]
    Y = np.asarray(np.hstack(class_ind), dtype=np.float32)
    return X, Y   

mysamplesize = 32
features, labels = generate_random_data_sample(mysamplesize, input_dim, num_output_classes)


import matplotlib.pyplot as plt
%matplotlib inline

# given this is a 2 class () 
colors = ['r' if l == 0 else 'b' for l in labels[:,0]]

plt.scatter(features[:,0], features[:,1], c=colors)
plt.xlabel("Scaled age (in yrs)")
plt.ylabel("Tumor size (in cm)")
plt.show()

#%%
input = input_variable(input_dim, np.float32)
# Define a dictionary to store the model parameters
mydict = {"w":None,"b":None} 

def linear_layer(input_var, output_dim):
    
    input_dim = input_var.shape[0]
    weight_param = parameter(shape=(input_dim, output_dim))
    bias_param = parameter(shape=(output_dim))
    
    mydict['w'], mydict['b'] = weight_param, bias_param

    return times(input_var, weight_param) + bias_param

output_dim = num_output_classes
z = linear_layer(input, output_dim)
label = input_variable((num_output_classes), np.float32)
loss = cross_entropy_with_softmax(z, label)

eval_error = classification_error(z, label)

learning_rate = 0.5
lr_schedule = learning_rate_schedule(learning_rate, UnitType.minibatch) 
learner = sgd(z.parameters, lr_schedule)
trainer = Trainer(z, loss, eval_error, [learner])

from cntk.utils import get_train_eval_criterion, get_train_loss

# Define a utility function to compute the moving average sum.
# A more efficient implementation is possible with np.cumsum() function
def moving_average(a, w=10):
    if len(a) < w: 
        return a[:]    
    return [val if idx < w else sum(a[(idx-w):idx])/w for idx, val in enumerate(a)]


# Defines a utility that prints the training progress
def print_training_progress(trainer, mb, frequency, verbose=1):
    training_loss, eval_error = "NA", "NA"

    if mb % frequency == 0:
        training_loss = get_train_loss(trainer)
        eval_error = get_train_eval_criterion(trainer)
        if verbose: 
            print ("Minibatch: {0}, Loss: {1:.4f}, Error: {2:.2f}".format(mb, training_loss, eval_error))
        
    return mb, training_loss, eval_error

#%%
# Initialize the parameters for the trainer
minibatch_size = 25
num_samples_to_train = 20000
num_minibatches_to_train = int(num_samples_to_train  / minibatch_size)

training_progress_output_freq = 50

plotdata = {"batchsize":[], "loss":[], "error":[]}

for i in range(0, num_minibatches_to_train):
    features, labels = generate_random_data_sample(minibatch_size, input_dim, num_output_classes)
    
    # Specify input variables mapping in the model to actual minibatch data to be trained with
    trainer.train_minibatch({input : features, label : labels})
    batchsize, loss, error = print_training_progress(trainer, i, 
                                                     training_progress_output_freq, verbose=1)
    
    if not (loss == "NA" or error =="NA"):
        plotdata["batchsize"].append(batchsize)
        plotdata["loss"].append(loss)
        plotdata["error"].append(error)

You should be able to execute this via the “Run Cell” button that appears above the #%% symbols.  You should see something similar to below appear in the results window that has now appears on the second half of the editor screen.

CNTK_Chart_Algo_Test

Viola!  There you have it!  CNTK + Visual Studio Code using a Pascal (TitanX) GPU on Windows 10.  I’ll leave it up to you all to figure out how to add a second or third GPU to the equation!

6 thoughts on “Microsoft Cognitive Toolkit + VS Code = Awesome

  1. Totally agree with your assessment. I’ve spent much time trying to get other frameworks to work. CNTK is cross platform and more scalable (supporting multiple machines), and as you pointed out is more easily installed.

    I found that I had to make a couple of tweaks to you code…
    1. Used the default generated launch.json for Python, rather than your one liner of “{
    “python.pythonPath”: “C:\\local\\Anaconda3-4.1.1-Windows-x86_64\\envs\\cntk-py34\\python”
    }” (although I still used that line in settings.json.
    2. Removed “cntk_device” from the import list.
    3. Commented out “%matplotlib inline”

    After that it worked great!

  2. Pingback: Dealing with Pesky Image Names in Cocos | DaCrook

  3. Your code works well but line 75 should be changed to “trainer = Trainer(z, (loss, eval_error), [learner])” due to the CNTK’s recent update.

    • You just create a new folder. Make sure you install CNTK via the latest instructions, CNTK has undergone many revisions and been released since this article. This article was written when CNTK was in beta.

Leave a Reply to Chris Cancel reply

Your email address will not be published. Required fields are marked *