Juin 2017
Volume 32, numéro 6
Cet article a fait l'objet d'une traduction automatique.
Série de tests - Machine de Boltzmann restreinte avec C#
Par James McCaffrey
Un ordinateur Boltzmann restreint (RBM) est un composant logiciel fascinant qui présente certaines ressemblances avec un réseau neuronal base. Un RBM a deux jeux de nœuds, visibles et masqués. Chaque jeu de nœuds peut agir comme entrées ou de sorties par rapport à l’autre jeu. Chaque nœud possède une valeur égale à zéro ou un et ces valeurs sont calculées à l’aide de la probabilité plutôt que de façon déterministe.
Chaque nœud de couche visible est conceptuellement connecté à chaque nœud de couche masquée avec une constante numérique appelée un poids, généralement une valeur comprise entre-10.0 et +10.0. Chaque nœud possède une constante numérique associée appelée un décalage. La meilleure façon de commencer à comprendre ce qu’un RBM est est par le biais d’un diagramme. Jetez un coup d'œil à la figure 1.
Figure 1 exemple d’un ordinateur Boltzmann restreint
Dans Figure 1, les nœuds visibles agissent comme entrées. Il existe six visibles (nœuds d’entrée) et trois nœuds masqués (sortie). Les valeurs des nœuds visibles sont (1, 1, 0, 0, 0, 0) et les valeurs calculées des nœuds masqués sont (1, 1, 0). Il existe 6 * 3 = 18 poids qui connectent les nœuds. Notez qu’il n’y a aucun poids visible visible ou masqué-à-caché. Cette restriction est la raison pour laquelle le mot « restricted » est la partie du nom RBM.
Chacune des flèches rouges poids dans Figure 1 points dans les deux sens, indiquant que les informations puissent circuler dans les deux sens. Si nœuds sont base zéro indexée, le poids de visible [0] à [0] masqué est 2.78, le poids à partir de [5] visible masqué [2] est 0,10 et ainsi de suite. Les valeurs de décalage sont les petites flèches vertes dans chaque nœud afin que le décalage pour visible [0] est-0.62 et le décalage pour masqué [0] est +1.25 et ainsi de suite. La valeur de p à l’intérieur de chaque nœud est la probabilité que le nœud prend une valeur d’un. Ainsi, masqués [0] a p = 0.995, ce qui signifie que sa valeur calculée sera certainement un et en fait, il s’agit, mais étant donné que les anneaux est PROBABILISTES, la valeur de masqué [0] auraient pu être zéro.
Vous avez probablement à droite sur maintenant, telles que les poids et les valeurs de décalage proviennent, mais contiennent de nombreuses questions avec moi, vous verrez comment toutes les parties du puzzle ajustent peu de temps. Dans les sections qui suivent, je décrivent le mécanisme d’entrée-sortie RBM, expliquez où le poids et les valeurs de biais proviennent et présenter un programme de démonstration qui correspond à Figure 1et donner un exemple d’utilisation d’anneaux.
Cet article suppose que vous avez intermédiaires ou meilleures compétences de programmation, mais ne suppose pas que vous connaissez un peu anneaux. Le programme de démonstration est codé à l’aide de c#, mais vous ne devez avoir aucun mal à refactoriser le code à un autre langage, tels que Python ou JavaScript si vous le souhaitez. Le programme de démonstration est trop long pour être affichée dans son intégralité, mais le code source complet est disponible dans le téléchargement du fichier qui accompagne cet article. Toutes les vérifications des erreurs a été supprimé pour garder les idées principales plus clair possible
Le mécanisme d’entrée-sortie RBM
Le mécanisme d’entrée-sortie RBM est (quelque peu étonnamment) relativement simple et est expliqué plus en obtenir un exemple. Supposons, comme dans Figure 1, les nœuds visibles agissent comme des entrées et ont des valeurs (1, 1, 0, 0, 0, 0). La valeur du nœud masqué [0] est calculée comme suit : Les six poids à partir des nœuds visibles dans [0] masqués sont (2.78, 1.32, 0,80, 2.23,-4.27,-2.22) et la valeur d’écart pour masqué [0] est 1,25.
La valeur de p pour masqué [0] est la valeur sigmoïde logistique de la somme des produits de valeurs d’entrée multipliés par leurs poids associés, ainsi que le décalage du nœud cible. Autrement dit, multiplier chaque valeur de nœud d’entrée par le poids qui pointe à partir du nœud dans le nœud cible, ajoutez ces produits jusqu'à, ajouter dans la valeur de décalage du nœud cible et puis prennent la logistique sigmoïde de cette somme :
p[0] = logsig( (1 * 2.78) + (1 * 1.32) + (0 * 0.80) +
(0 * 2.23) + (0 * -4.27) + (0 * -2.22) + 1.25 )
= logsig( 2.78 + 1.32 + 1.25 )
= logsig( 5.36 )
= 0.995
La fonction sigmoïde logistique, qui apparaît dans plusieurs des algorithmes d’apprentissage, est définie comme :
logsig(x) = 1.0 / (1.0 + exp(-x))
où la fonction exp est définie comme :
exp(x) = e^x
e (nombre d’Euler) étant 2.71828 environ.
Par conséquent, à ce stade, la valeur de p pour masqué [0] a été calculée en tant que 0.995. Pour calculer la valeur zéro ou un finale pour le nœud [0] masqué, vous utiliseriez un générateur de nombres aléatoires pour produire une valeur pseudo-aléatoire comprise entre 0,0 et 1,0. Si le nombre aléatoire est inférieure à 0.995 (qui sera 99,5 % du temps), le nœud a la valeur un ; Sinon (0,05 % du temps), il est défini à zéro.
Les autres nœuds masqués seraient calculés de la même façon. Et si les nœuds masqués ont été agissant en tant qu’entrées, les valeurs des nœuds visibles sont calculées comme valeurs de sortie de la même façon.
Déterminer le poids et les valeurs de décalage
Déterminer un ensemble de RBM les valeurs de sortie pour un ensemble donné de valeurs d’entrée est facile, mais où vous les poids et les valeurs de décalage sont fournies ? Contrairement aux réseaux neuronaux, qui requièrent un jeu de données avec des valeurs d’entrée connus et les valeurs de sortie connus, correct, d’apprentissage, anneaux peut essentiellement l’apprentissage d’eux-mêmes, pour ainsi dire, à l’aide uniquement un ensemble de valeurs pour les nœuds visibles. Intéressant ! Supposez que vous avez un ensemble d’éléments de données de 12, comme suit :
(1, 1, 0, 0, 0, 0) // A
(0, 0, 1, 1, 0, 0) // B
(0, 0, 0, 0, 1, 1) // C
(1, 1, 0, 0, 0, 1) // noisy A
(0, 0, 1, 1, 0, 0) // B
(0, 0, 0, 0, 1, 1) // C
(1, 0, 0, 0, 0, 0) // weak A
(0, 0, 1, 0, 0, 0) // weak B
(0, 0, 0, 0, 1, 0) // weak C
(1, 1, 0, 1, 0, 0) // noisy A
(1, 0, 1, 1, 0, 0) // noisy B
(0, 0, 1, 0, 1, 1) // noisy C
Les valeurs de nœud visible RBM étant zéro et un, vous pouvez considérer les comme des fonctionnalités individuelles binaires (tels que « j’aime » et « n’aimez ») ou en tant qu’entiers d’encodage binaire. Supposons que chacun des éléments de 12 données représente le type d’une personne ou non dans les avis de six films : « Étranger », « Début », « Espion », « EuroTrip », « Gladiator, » « Spartacus ». Les deux premiers films sont science-fiction. Les deux films sont comédie (ainsi, en fonction de votre logique de humeur) et les deux derniers films historique (de).
La première personne aime « Étranger » et « Début », mais ne telles que les quatre autres films. Si vous examinez les données, vous pouvez l’imaginer qu’il existe trois types de personnes. Tapez « A » personnes tout comme les films de science-fiction uniquement. Tapez « B » comme seul comédie films et « C » comme uniquement l’historique des films. Notez qu’il existe certains bruit dans les données, et il existe des versions faibles et bruyantes de chaque type de personne.
Le nombre de nœuds visibles dans un RBM est déterminé par le nombre de dimensions dans les données d’entrée, six dans cet exemple. Le nombre de nœuds masqués est un paramètre libre que vous devez choisir. Supposons que vous définissez le nombre de nœuds masqués à trois. Étant donné que chaque valeur de nœud RBM peut avoir zéro ou un, avec trois nœuds masqués il existe un total de types de huit personnes qui peuvent être détectés : (0, 0, 0), (0, 0, 1), . . . (1, 1, 1).
Il existe plusieurs façons pour former un RBM. L’algorithme le plus couramment est appelée CD-1, ce qui signifie une divergence contrastive, seule étape. L’algorithme est très intelligent et n’est pas du tout évident. L’algorithme d’apprentissage CD-1 est présentée dans le pseudo-code général permettant de Figure 2.
Figure 2 l’algorithme d’apprentissage des CD-1
(v represents the visible nodes)
(h represents the hidden nodes)
(lr is a small learning rate value)
loop n times
for each data item
compute h from v
let posGrad = outer product(v, h)
compute v' from h
compute h' from v'
let negGrad = outer product(v', h')
let delta W = lr * (posGrad - negGrad)
let delta vb = lr * (v - v')
let delta hb = lr * (h - h')
end for
end loop
L’objectif de l’apprentissage est pour rechercher un ensemble de poids et d’écart valeurs afin que lorsque RBM est chargé un ensemble de valeurs d’entrée dans les nœuds visibles et génère un ensemble de nœuds dans les nœuds masqués, la sortie lorsque les nœuds masqués sont utilisés comme entrées, les valeurs de nœuds visibles d’origine seront (généralement), puis être régénérée. La seule façon d’I a pu comprendre que CD-1 a été en parcourant des exemples concrets.
Supposons que le taux d’apprentissage est défini sur 0.01 et qu’à un moment donné, l’élément actuel de la formation d’entrée est (0, 0, 1, 1, 0, 0) et les 18 poids sont :
0.01 0.02 0.03
0.04 0.05 0.06
0.07 0.08 0.09
0.10 0.11 0.12
0.13 0.14 0.15
0.16 0.17 0.18
L’index de ligne, 0 à 5, représente l’index d’un nœud visible et que l’index de la colonne 0 à 2, représente l’index d’un nœud masqué. Par conséquent, le poids à partir de la visible [0] [2] masqué est 0,03.
La première étape dans le CD-1 est à calculer les valeurs h à partir des valeurs v à l’aide du mécanisme PROBABILISTE décrit dans la section précédente. Supposons que h s’élève à (0, 1, 0). Ensuite, le dégradé positif est calculé comme produit externe de v et h:
0 0 0
0 0 0
0 1 0
0 1 0
0 0 0
0 0 0
Le produit externe n’est pas très courant dans les algorithmes d’apprentissage automatique de l’ordinateur (ou tous les algorithmes d’ailleurs), par conséquent, il est tout à fait possible vous n’avez pas encore vu avant. L’article de Wikipedia sur la rubrique donne une explication de bonne. Notez que la forme de la matrice de dégradé positive sera identique à la forme de la matrice de poids.
Ensuite, les valeurs h sont utilisées comme entrées, ainsi que les poids actuels, pour produire une sortie de nouvelles valeurs v ». Supposons que v' élève à (0, 1, 1, 1, 0, 0). Ensuite, v » est utilisée comme entrée pour calculer un nouveau h'. Supposons que h' est (0, 0, 1).
Le gradient négatif est le produit externe v ' et h' et est donc :
0 0 0
0 0 1
0 0 1
0 0 1
0 0 0
0 0 0
Le résultat de posGrad - negGrad est :
0 0 0
0 0 -1
0 +1 -1
0 +1 -1
0 0 0
0 0 0
Si vous examinez attentivement l’algorithme, vous verrez que les valeurs de cellule dans la matrice de dégradé delta peuvent être une des trois valeurs : 0, + 1 ou -1. Les valeurs de gradient delta de + 1 correspondent aux poids doivent être augmentés légèrement. Valeurs de -1 correspondent aux poids doivent être légèrement diminués. Intelligent ! La quantité d’augmentation ou de diminution est définie par une formation du taux de valeur. Par conséquent, le poids de visible [1] à [2] masqué aurait diminué de 0,01 et le poids de visible [2] à [1] masqué passerait par 0,01. Un petit rend de valeur de taux d’apprentissage formation prendre plus de temps, mais un taux d’apprentissage volumineux peut ignorer les valeurs de poids de bonne.
Par conséquent, le nombre d’itérations d’apprentissage doit être effectué ? En général, définissant le nombre d’itérations d’apprentissage et en choisissant une valeur de taux d’apprentissage sont des questions d’essais et erreurs. Dans le programme de démonstration qui accompagne cet article, j’ai utilisé un taux d’apprentissage de 0,01 et un nombre maximal d’itérations, la valeur 1 000. Après l’apprentissage, j’ai reçu le poids et les valeurs de décalage affichées dans Figure 1.
Interprétation d’un ordinateur Boltzmann restreint
OK et il est possible de prendre un jeu de données où chaque valeur est zéro ou un, puis définir un certain nombre de nœuds masqués, obtenir des poids et des valeurs de décalage. À quoi bon ?
Une façon de considérer un RBM est comme un type de machine de compression. Dans l’exemple de données de préférence film, si le flux d’une type une personne en tant qu’entrée (1, 1, 0, 0, 0, 0), vous allez généralement obtenir (1, 1, 0) en tant que sortie. Si vous flux comme entrée pour les nœuds masqués (1, 1, 0), vous obtenez presque toujours (1, 1, 0, 0, 0, 0) en tant que sortie dans les nœuds visibles. En d’autres termes, (1, 1, 0, 0, 0, 0) et légères variantes sont mappés aux (1, 1, 0). Ce comportement est étroitement lié à, mais pas tout à fait identique, analyse des facteurs de statistiques classique.
Examinons le programme de démonstration dans Figure 3. La démonstration correspond à l’exemple de type-je n’aime pas de film. La démonstration crée un RBM 6-3 et trains à l’aide des éléments de 12 données présentée dans la section précédente. Le codé en dur de données sont configurées comme suit :
int[][] trainData = new int[12][];
trainData[0] = new int[] { 1, 1, 0, 0, 0, 0 };
trainData[1] = new int[] { 0, 0, 1, 1, 0, 0 };
...
trainData[11] = new int[] { 0, 0, 1, 0, 1, 1 };
Démonstration de la figure 3 d’un ordinateur Boltzmann restreint
Dans la plupart des cas vous devez lire les données à partir d’un fichier texte à l’aide d’une méthode d’assistance. La démonstration RBM est créée et formée comme suit :
int numVisible = 6;
int numHidden = 3;
Machine rbm = new Machine(numVisible, numHidden);
double learnRate = 0.01;
int maxEpochs = 1000;
rbm.Train(trainData, learnRate, maxEpochs);
Le choix de la définition du nombre de nœuds masqués à trois était arbitraire et les valeurs de learnRate et maxEpochs ont été déterminés par essais et erreurs. Après l’apprentissage, RBM est utilisé comme suit :
int[] visibles = new int[] { 1, 1, 0, 0, 0, 0 };
int[] computedHidden = rbm.HiddenFromVis(visibles);
Console.Write("visible = ");
ShowVector(visibles, false);
Console.Write(" -> ");
ShowVector(computedHidden, true);
Si vous faire des essais avec le code, vous remarquerez que les valeurs masquées calculées sont presque toujours un des trois modèles. Type de personne A (ou version faible ou bruyante) génère presque toujours un (1, 1, 0). Type B génère (1, 0, 1). Et le type C génère (0, 1, 1). Et si vous les trois modèles en tant qu’entrées de flux, vous allez presque toujours obtenir les trois modèles d’entrée principales. Le point est que RBM a déduit que les données peuvent être placées dans un des trois compartiments. Les modèles de bits spécifique ne sont pas importantes.
Encore une autre interprétation de ce comportement est qu’un RBM agit comme un encodeur d’automatique. Et il est également possible d’enchaîner plusieurs anneaux afin de créer un système de prédiction appelé réseau convictions approfondie (DBN). En fait, il s’agit sans doute l’utilisation la plus courante d’anneaux.
Implémentation d’un ordinateur Boltzmann restreint
Une fois que vous comprenez comment fonctionne les anneaux, ils sont relativement simples. Mais le codage d’un programme de démonstration est un peu plus complexe que vous pourriez vous attendre. Il existe de nombreuses possibilités de conception pour une RBM. Examinons la démonstration exécution dans Figure 3.
La démonstration illustre l’exemple de préférence de film des sections précédentes de cet article, il y a six nœuds visibles. Le programme de démonstration définit un objet ordinateur avec 10 champs de membre. Les six premiers champs dans la définition de classe sont :
public class Machine
{
public Random rnd;
public int numVisible;
public int numHidden;
public int[] visValues;
public double[] visProbs;
public double[] visBiases;
...
Tous les champs sont déclarés avec une étendue publique par souci de simplicité. L’objet Random est utilisé lors de la conversion d’une probabilité du nœud à une valeur de zéro ou un concrète. Variables numVisible et numHidden (OK, OK, savoir qu’ils sont des objets) contenant le nombre de nœuds masqués et visibles. Entier tableau visValues contient les valeurs de zéro ou un des nœuds visibles. Notez que vous pouvez utiliser un type Boolean si vous le souhaitez. Double tableau visBiases contient les valeurs de décalage associées à chaque nœud visible. Tableau de type double visProbs contient les probabilités de nœud visible. Notez que le tableau visProbs n’est pas nécessaire, car les valeurs de nœud peuvent être calculées à la volée ; Toutefois, il est utile si vous souhaitez examiner le comportement de RBM pendant l’exécution de stocker les valeurs de probabilité.
Les quatre autres champs de classe de Machine sont :
public int[] hidValues;
public double[] hidProbs;
public double[] hidBiases;
public double[][] vhWeights;
Tableaux hidValues hidProbs et hidBiases sont les valeurs de nœud, les valeurs de décalage associées et probabilités de nœud, respectivement. L’objet vhWeights est une matrice de style de tableau de tableaux où l’index de ligne correspond à un nœud visible et que l’index de colonne correspond à un nœud masqué.
La méthode de classe de clé calcule les valeurs des nœuds masqués à l’aide de valeurs dans un paramètre qui correspond aux nœuds visibles. Définition de cette méthode commence par :
public int[] HiddenFromVis(int[] visibles)
{
int[] result = new int[numHidden];
...
Ensuite, les calculs des nœuds de couche cachée sont effectuées de nœud par nœud :
for (int h = 0; h < numHidden; ++h) {
double sum = 0.0;
for (int v = 0; v < numVisible; ++v)
sum += visibles[v] * vhWeights[v][h];
sum += hidBiases[h]; // Add the hidden bias
double probActiv = LogSig(sum); // Compute prob
double pr = rnd.NextDouble(); // Determine 0/1
if (probActiv > pr) result[h] = 1;
else result[h] = 0;
}
Le code reflète l’explication du mécanisme d’entrée-sortie expliqué plus haut. Fonction LogSig est une fonction d’assistance privée, car Microsoft .NET Framework n’a pas une fonction sigmoïde logistique intégrée (à moins que je suis conscient de).
La méthode clé se termine en retournant les valeurs calculées nœud masqué à l’appelant :
...
return result;
}
Le reste du code de démonstration implémente l’algorithme d’apprentissage CD-1 comme décrit précédemment. Le code n’est pas simple, mais si vous l’examinez attentivement, vous devez être en mesure d’établir les connexions entre les concepts RBM et l’implémentation.
Pour résumer
Les machines Boltzmann restreints sont simples et complexes en même temps. Le mécanisme d’entrée-sortie RBM est déterministe et PROBABILISTE (parfois appelé stochastique), mais il est relativement facile à comprendre et à implémenter. L’aspect le plus difficile d’anneaux, à mon avis, est de comprendre comment ils peuvent être utiles.
En tant que composant logiciel autonome, un RBM peut agir comme un ordinateur avec perte de la compression pour réduire le nombre de bits nécessaires pour représenter des données, ou peut agir comme un composant d’analyse PROBABILISTE facteur qui identifie les concepts clés dans un jeu de données. Lors de la concaténation, les anneaux peut créer une structure de réseaux neuronaux profonds appelée « convictions approfondie network » qui peut effectuer des prédictions.
Anneaux ont été inventé en 1986 par mon collègue Microsoft Paul Smolensky, mais acquise une attention accrue relativement récemment lorsque l’algorithme d’apprentissage CD-1 a été prévue par le chercheur et le collaborateur Microsoft Geoffrey Hinton. La plupart des informations présentées dans cet article est basée sur des conversations personnelles avec Smolensky et le document de recherche 2010, « A pratique Guide de formation restreint Boltzmann ordinateurs, » par Hinton.
Récupération d’urgence. James McCaffreyfonctionne pour Microsoft Research à Redmond, Washington Il a travaillé sur plusieurs produits Microsoft, y compris Internet Explorer et Bing. Dr. McCaffrey peut être atteint à jammc@microsoft.com.
Grâce aux experts techniques Microsoft suivants ayant révisé cet article : ANI Anirudh, Qiuyuan Huang et Paul Smolensky