CNTK, quoi de neuf ?

Voici maintenant presque 3 mois depuis notre dernier billet consacré à CNTK (Computational Network ToolKit), l'outil de Deep Learning développé par Microsoft Research et disponible en Open Source sur le repo/la forge communautaire GitHub.

Force est de constater que cet outil a bien évolué pendant ce laps de temps ! :-) Nouveau langage de définition, disponibilité d'une bibliothèque Python, intégration de la bibliothèque Intel MKL (Math Kernel Library) - pour ne citer que quelques nouveautés clé – sont au programme.

C'est pourquoi nous vous proposons, Morgan Funtowicz actuellement en stage au sein de l'équipe et moi-même, de faire ensemble le point sur les nouveautés apportées à ce dernier.

BrainScript, le langage officiel de définition

Dans notre précédent billet sur CNTK, nous faisions référence à un élément du Framework CNTK nommé NDL (Network Definition Language) permettant de modéliser la topologie de nos réseaux. Ce dernier, bien que relativement simple, apportait :

  • Une rigueur relative dans la déclaration,
  • L'impossibilité d'utiliser des expressions mathématiques « inline »,
  • Une verbosité assez importante,

Autant de voies d'améliorations qui ont été explorées et prises en compte !

Brainscript propose désormais un langage clair, conscrit et beaucoup plus strict que NDL. Citons pèle même à titre d'exemple les points suivants :

  • La casse est maintenant prise en compte
  • Il est désormais impératif d'encapsuler les chaines de caractères avec des « guillemets »
  • Il est aussi impératif de spécifier le nœud retourné par une macro
    • F(x) = [y = x + 1].y
  • Fini l'alternance de {} et/ou [] pour les macros, seuls les [] sont maintenant autorisés
  • Il est possible de définir des opérations inline
    • Avant : z = Plus( Times(W, x), b)
    • Après : z = W * x + b

Outre ces changements bienvenus d'ordre syntaxique, BrainScript permet d'aller plus loin que son prédécesseur, en fournissant des éléments de hauts niveaux, tels que :

  • Les expressions conditionnelles « if then else »
  • La mise en œuvre de scénarios Sequence-to-Sequence utilisés par exemple pour modéliser des transitions graphème - phonème

Les fonctionnalités ainsi proposées par BrainScript sont documentées et consultables ici et ici sur le wiki associé au projet CNTK sur le repo/la forge communautaire GitHub.

Dans l'hypothèse où vous utiliseriez déjà des modèles développés via le maintenant désormais déprécié langage NDL, un guide de migration vous est proposé ici sur le wiki.

Une Interface Python

La nécessité de devoir réapprendre un nouveau langage (NDL, désormais BrainScript) pouvait apparaître comme un facteur limitant quant à l'adoption la plus large possible de CNTK au sein de la communauté.

Les personnes partagent cette opinion seront ravies d'apprendre que les équipes de CNTK planchent depuis quelques temps sur un interfaçage simple avec le langage Python, un langage largement répandu dans le milieu (au même titre que R).

Ainsi, depuis la version 1.5, dévoilée mi-juin, il s'avère possible d'utiliser le langage Python afin de préciser les différents blocs définissants la topologie, l'optimisation et la lecture des données. Cet interfaçage permet de générer automatiquement les fichiers nécessaires à l'exécution de CNTK.

Pour plus d'information sur ce sujet, vous pouvez consulter la documentation afférente ici ; cette dernière couvre, au-delà des différentes étapes de l'installation, l'utilisation de cette interface.

Une nouvelle architecture pour la lecture de données

Dans les versions précédentes de CNTK, la lecture des données était réalisée via des modules, lesquels proposaient pour mémoire deux fonctionnalités principales :

  • La désérialisation / sérialisation des données.
  • La transformation des données.

Ces deux fonctionnalités étaient proposées de manière unifiée, dans un seul bloc, au sein d'un fichier de configuration.

Désormais, Ces opérations, à savoir sérialisation et transformations, sont distinctes au sein de CNTK. Les différents modules de lecture proposent un certain nombre de transformations relatives au lecteur.

A titre d'exemple, les transformations disponibles pour la lecture d'images sont :

  • Scaling
  • Flipping
  • Cropping
  • Mean Substraction
  • Color Jitting

Lesquelles peuvent-être chainées de la sorte :

 deserializers = ([
    type = "ImageDeserializer"
    module = "ImageReader"
 
    # Map file which maps images to labels
    file = "$ConfigDir$/train_map.txt"

    # Description of input streams
    input = [
            # Description of input stream to feed the Input node named "features"
            features = [
                transforms = (
                    [
                        type = "Crop"
                        # Possible values: Center, Random. Default: Center
                        cropType = "Random"
                        # Crop scale ratio.
                        cropRatio = 0.875
                        # Crop scale ratio jitter type
                        jitterType = "uniRatio"
                    ]:[
                        type = "Scale"
                        width = 224
                        height = 224
                        channels = 3
                        # Interpolation to use when scaling image to width x height size.
                        interpolations = "linear"
                    ]:[
                        type = "Mean"
                        # Stores mean values for each pixel in OpenCV matrix XML format.
                        meanFile = "$ConfigDir$/ImageNet1K_mean.xml"
                    ]:[
                        # Changes the image layout from HWC to CHW
                        type = "Transpose"
                    ]
                )
            ]
            # Description of input stream to feed the Input node named "labels"
            labels = [
                labelDim = 1000
            ]
        ]
    ]
])

Comme vous pouvez le constater, la séparation des transformations permet de gagner en clarté, en évitant ainsi tout effet de bord en modifiant la partie lecture de l'information.

Un partenariat avec Intel

Depuis ses débuts, l'outil CNTK reposait sur la bibliothèque ACML (AMD Core Math Library) afin de réaliser toutes les opérations mathématiques sur les matrices et les vecteurs.

Au-delà de la richesse des opérations proposées, cette dernière souffrait cependant de quelques problèmes connus qui, pour y palier, imposait dans la pratique de spécifier certaines variables d'environnement afin d'obtenir des résultats cohérents.

A partir de la version 1.6 de CNTK, sortie le 15 juillet dernier, la bibliothèque Intel MKL remplace comme invoqué en introduction ACML, et ce, via un partenariat avec Intel. Ce partenariat donne la possibilité à CNTK d'inclure la bibliothèque MKL (sous licence normalement) avec les binaires de l'outil.

Cette évolution au niveau du moteur de calcul autorise un gain de performances intéressant, pouvant allant jusqu'à un facteur 2 pour certains projets, tout en consommant moins de mémoire ! :-)

De plus, MKL permet de s'affranchir des différents problèmes relatifs à l'utilisation d'ACML soulignés ci-avant, améliorant de ce fait la stabilité des modèles et de l'apprentissage.

Pour plus d'information, nous vous invitons à lire l'article publié par Intel ici.

Du nouveau pour les réseaux convolutifs

Dans le domaine de la vision par ordinateur, les réseaux de neurones profonds tirant profit d'opérations de convolutions sont devenus la norme. Ces réseaux agissent comme des extracteurs d'informations, synthétisant celle-ci pour les couches suivantes.

Ces opérations de convolution et de pooling, sont destructrices d'informations, comme peut l'être la compression d'un fichier MP3.
Cependant, à l'image d'un fichier MP3 pour lequel il est possible de reproduire le son « quasi » original - que les mélomanes nous excusent de cette approximation grossière -, il est possible de reconstruire une image ayant transitée par les différentes couches d'un réseau de neurones convolutif.

Pour cela, on utilise des opérations inverses aux opérations de base :

  • Convolution : Deconvolution
  • Pooling : Unpooling

Bonne nouvelle ! CNTK intègre depuis la version 1.6 ces opérations nativement, permettant ainsi de reconstruire le signal initial, comme en témoigne l'image reconstruire ci-dessous :

Figure 1 : Visualisation de l'entrée en fonction des différentes activation (source)

Des bibliothèques pour l'évaluation de modèles entrainés

Enfin, pour terminer ce billet sur les nouveautés de CNTK quant à l'évaluer les modèles que vous aurez entrainés au préalable, sachez qu'une bibliothèque C++ est disponible directement dans les binaires à télécharger.

Pour la plateforme C#, un paquet NuGet est également disponible ici.

En guise de conclusion

Comme vous pouvez le constater au travers de ces quelques lignes, l'outil CNTK évolue en continu pour devenir de plus en plus puissant et pertinent. A ce titre, un certain nombre de projets en interne chez Microsoft sont en passe d'être migrés sur cette plateforme. Les possibilités grandissantes de ce dernier en font certainement un allié de choix pour vos futures expérimentations et développement.