Main Content

La traduction de cette page n'est pas à jour. Cliquez ici pour voir la dernière version en anglais.

Classification de séquences avec le Deep Learning

Cet exemple montre comment classer des données séquentielles avec un réseau LSTM (long short-term memory).

Vous pouvez utiliser un réseau LSTM pour entraîner un réseau de neurones profond à classer des données séquentielles. Un réseau LSTM vous permet d’entrer des données séquentielles dans un réseau et de réaliser des prédictions en fonction des pas de temps individuels des données séquentielles.

Cet exemple utilise le jeu de données Japanese Vowels comme indiqué dans [1] et [2]. Cet exemple entraîne un réseau LSTM à reconnaître le locuteur à partir de données de séries temporelles représentant deux voyelles japonaises prononcées à la suite. Les données d’apprentissage contiennent les données de séries temporelles de neuf locuteurs. Les séquences possèdent chacune 12 caractéristiques et sont de longueur variable. Le jeu de données contient 270 observations d’apprentissage et 370 observations de test.

Charger des données séquentielles

Chargez les données d’apprentissage Japanese Vowels. XTrain est un cell array contenant 270 séquences de dimension 12 de longueur variable. Y est un vecteur catégoriel d’étiquettes « 1 », « 2 », ..., « 9 », qui correspondent aux neuf locuteurs. Les entrées de XTrain sont des matrices de 12 lignes (une ligne pour chaque caractéristique) et un nombre variable de colonnes (une colonne pour chaque pas de temps).

[XTrain,YTrain] = japaneseVowelsTrainData;
XTrain(1:5)
ans=5×1 cell array
    {12x20 double}
    {12x26 double}
    {12x22 double}
    {12x20 double}
    {12x21 double}

Visualisez les premières séries temporelles dans un graphique. Chaque ligne correspond à une caractéristique.

figure
plot(XTrain{1}')
xlabel("Time Step")
title("Training Observation 1")
numFeatures = size(XTrain{1},1);
legend("Feature " + string(1:numFeatures),Location="northeastoutside")

Figure contains an axes object. The axes object with title Training Observation 1 contains 12 objects of type line. These objects represent Feature 1, Feature 2, Feature 3, Feature 4, Feature 5, Feature 6, Feature 7, Feature 8, Feature 9, Feature 10, Feature 11, Feature 12.

Préparer les données pour le remplissage

Pendant l’apprentissage, par défaut, le software divise les données d’apprentissage en mini-lots et remplit les séquences afin qu’elles aient la même longueur. Un remplissage excessif peut avoir un impact négatif sur les performances du réseau.

Pour éviter que le processus d’apprentissage ajoute trop de remplissage, vous pouvez trier les données d’apprentissage par longueur de séquence et choisir une taille de mini-batch afin que les séquences d’un mini-batch aient une longueur similaire. La figure suivante montre l’effet du remplissage des séquences avant et après le tri des données.

Accédez aux longueurs de séquence pour chaque observation.

numObservations = numel(XTrain);
for i=1:numObservations
    sequence = XTrain{i};
    sequenceLengths(i) = size(sequence,2);
end

Triez les données par longueur de séquence.

[sequenceLengths,idx] = sort(sequenceLengths);
XTrain = XTrain(idx);
YTrain = YTrain(idx);

Affichez les longueurs de séquence triées dans un graphique à barres.

figure
bar(sequenceLengths)
ylim([0 30])
xlabel("Sequence")
ylabel("Length")
title("Sorted Data")

Figure contains an axes object. The axes object with title Sorted Data contains an object of type bar.

Choisissez une taille de mini-batch de 27 afin de diviser les données d’apprentissage uniformément et de réduire la quantité de remplissage dans les mini-batchs. La figure suivante illustre le remplissage ajouté aux séquences.

miniBatchSize = 27;

Définir l’architecture du réseau LSTM

Définissez l’architecture du réseau LSTM. Spécifiez la taille d’entrée du réseau pour des séquences de taille de 12 (dimension des données d’entrée). Spécifiez une couche de neurones LSTM bidirectionnels avec 100 unités cachées et en sortie le dernier élément de la séquence. Enfin, spécifiez neuf classes en incluant une couche entièrement connectée de taille 9, suivie par une couche softmax (fonction exponentielle normalisée) et une couche de classification.

Si vous avez accès à des séquences complètes au moment de la prédiction, vous pouvez utiliser une couche de neurones LSTM bidirectionnels dans votre réseau. Une couche de LSTM bidirectionnels apprend à partir de la séquence complète à chaque pas de temps. Si vous n’avez pas accès à la séquence complète au moment de la prédiction, par exemple si vous réaliser des prévisions de valeurs ou des prédictions à chaque pas de temps, utilisez une couche de LSTM à la place.

inputSize = 12;
numHiddenUnits = 100;
numClasses = 9;

layers = [ ...
    sequenceInputLayer(inputSize)
    bilstmLayer(numHiddenUnits,OutputMode="last")
    fullyConnectedLayer(numClasses)
    softmaxLayer
    classificationLayer]
layers = 
  5x1 Layer array with layers:

     1   ''   Sequence Input          Sequence input with 12 dimensions
     2   ''   BiLSTM                  BiLSTM with 100 hidden units
     3   ''   Fully Connected         9 fully connected layer
     4   ''   Softmax                 softmax
     5   ''   Classification Output   crossentropyex

Spécifiez maintenant les options d’apprentissage. Spécifiez un solveur "adam", un seuil de gradient de 1 et un nombre maximal d’epochs de 50. Pour remplir les données afin qu’elles aient la même longueur que les séquences les plus longues, spécifiez la longueur de séquence comme étant "longest". Pour vous assurer que les données restent triées par longueur de séquence, précisez qu’il ne faut jamais mélanger les données.

Comme les mini-batchs sont petits avec des séquences courtes, l’apprentissage convient mieux au CPU. Définissez l’option ExecutionEnvironment sur "cpu". Si un GPU est disponible, vous pouvez réaliser l'apprentissage en définissant l’option ExecutionEnvironment sur "auto" (valeur par défaut).

options = trainingOptions("adam", ...
    ExecutionEnvironment="cpu", ...
    GradientThreshold=1, ...
    MaxEpochs=50, ...
    MiniBatchSize=miniBatchSize, ...
    SequenceLength="longest", ...
    Shuffle="never", ...
    Verbose=0, ...
    Plots="training-progress");

Entraîner le réseau LSTM

Entraînez le réseau LSTM avec les options d’apprentissage spécifiées avec trainNetwork.

net = trainNetwork(XTrain,YTrain,layers,options);

{"String":"Figure Training Progress (05-Nov-2022 09:58:24) contains 2 axes objects and another object of type uigridlayout. Axes object 1 contains 9 objects of type patch, text, line. Axes object 2 contains 9 objects of type patch, text, line.","Tex":[],"LaTex":[]}

Tester le réseau LSTM

Chargez l’ensemble des données de test et classez les séquences selon les locuteurs.

Chargez les données de test Japanese Vowels. XTest est un cell array contenant 370 séquences de dimension 12 de longueur variable. YTest est un vecteur catégoriel d’étiquettes « 1 », « 2 », ..., « 9 », qui correspondent aux neuf locuteurs.

[XTest,YTest] = japaneseVowelsTestData;
XTest(1:3)
ans=3×1 cell array
    {12x19 double}
    {12x17 double}
    {12x19 double}

Le réseau LSTM net a été entraîné avec des mini-batchs de séquences de longueur similaire. Assurez-vous que les données de test sont organisées de la même manière. Triez les données de test par longueur de séquence.

numObservationsTest = numel(XTest);
for i=1:numObservationsTest
    sequence = XTest{i};
    sequenceLengthsTest(i) = size(sequence,2);
end

[sequenceLengthsTest,idx] = sort(sequenceLengthsTest);
XTest = XTest(idx);
YTest = YTest(idx);

Classez les données de test. Pour réduire la quantité de remplissage introduit par le processus de classification, spécifiez la même taille de mini-batch que pour l’apprentissage. Pour appliquer le même remplissage que les données d’apprentissage, spécifiez la longueur de séquence à "longest".

YPred = classify(net,XTest, ...
    MiniBatchSize=miniBatchSize, ...
    SequenceLength="longest");

Calculez la précision de la classification des prédictions.

acc = sum(YPred == YTest)./numel(YTest)
acc = 0.9757

Références

[1] M. Kudo, J. Toyama, and M. Shimbo. "Multidimensional Curve Classification Using Passing-Through Regions." Pattern Recognition Letters. Vol. 20, No. 11–13, pages 1103–1111.

[2] UCI Machine Learning Repository: Japanese Vowels Dataset. https://archive.ics.uci.edu/ml/datasets/Japanese+Vowels

Voir aussi

| | | |

Sujets associés