Traitement automatique du langage naturel (TALN)

L’apprentissage semi-supervisé appliqué au Traitement Automatique du Langage Naturel (TALN) combine un petit corpus de textes annotés avec une grande quantité de données non annotées pour améliorer la compréhension et la génération du langage par les modèles. Cette approche permet de réduire le coût et l’effort liés à l’annotation manuelle tout en exploitant efficacement les vastes ressources textuelles disponibles. En TALN, l’apprentissage semi-supervisé est particulièrement utile pour des tâches telles que la classification de texte, l’analyse de sentiments, ou la reconnaissance d’entités nommées, où les données annotées sont souvent rares mais les données brutes abondantes.

Fonctions :

  • Traitement automatique du langage naturel (exemple)

    Le traitement automatique du langage naturel (TALN) est une branche de l’intelligence artificielle qui permet aux ordinateurs de comprendre, analyser et générer du texte ou de la parole en langage humain. Par exemple, les assistants vocaux comme Siri ou Alexa utilisent le TALN pour interpréter les commandes et répondre aux questions des utilisateurs.

    Exemple de code :

    import tensorflow as tf
    import numpy as np
    
    # Simulation de données textuelles (tokenisées)  
    # (En pratique on utilise un tokenizer + un dataset réel)
    vocab_size = 1000
    max_len = 20
    
    def generate_data(n_samples, labeled=True):
        X = np.random.randint(1, vocab_size, size=(n_samples, max_len))
        if labeled:
            # Labels binaires aléatoires
            y = np.random.randint(0, 2, size=(n_samples, 1))
            return X, y
        else:
            return X
    
    # 1000 phrases étiquetées
    X_labeled, y_labeled = generate_data(1000, labeled=True)
    
    # 9000 phrases non étiquetées
    X_unlabeled = generate_data(9000, labeled=False)
    
    # Validation (test)
    X_val, y_val = generate_data(1000, labeled=True)
    
    # Modèle simple LSTM pour classification binaire
    model = tf.keras.Sequential([
        tf.keras.layers.Embedding(vocab_size, 64, input_length=max_len),
        tf.keras.layers.Bidirectional(tf.keras.layers.LSTM(64)),
        tf.keras.layers.Dense(1)
    ])
    
    optimizer = tf.keras.optimizers.Adam()
    loss_fn = tf.keras.losses.BinaryCrossentropy(from_logits=True)
    batch_size = 64
    consistency_weight = 1.0
    epochs = 5
    
    # Fonction d'augmentation simple (ajoute un "bruit" lexical : remplace 10% des mots par un token aléatoire)
    def augment_text(batch_x):
        batch_x_aug = batch_x.copy()
        for i in range(batch_x.shape[0]):
            for j in range(batch_x.shape[1]):
                if np.random.rand() < 0.1:
                    batch_x_aug[i, j] = np.random.randint(1, vocab_size)
        return batch_x_aug
    
    # Dataset
    labeled_dataset = tf.data.Dataset.from_tensor_slices((X_labeled, y_labeled))
    labeled_dataset = labeled_dataset.shuffle(1000).batch(batch_size).repeat()
    
    unlabeled_dataset = tf.data.Dataset.from_tensor_slices(X_unlabeled)
    unlabeled_dataset = unlabeled_dataset.shuffle(9000).batch(batch_size).repeat()
    
    val_dataset = tf.data.Dataset.from_tensor_slices((X_val, y_val)).batch(batch_size)
    
    labeled_iter = iter(labeled_dataset)
    unlabeled_iter = iter(unlabeled_dataset)
    
    for epoch in range(epochs):
        print(f"Epoch {epoch+1}/{epochs}")
        total_loss = 0
        steps_per_epoch = len(X_labeled) // batch_size
    
        for step in range(steps_per_epoch):
            x_lab, y_lab = next(labeled_iter)
            x_unlab = next(unlabeled_iter)
    
            x_unlab_aug = augment_text(x_unlab.numpy())
    
            with tf.GradientTape() as tape:
                # Supervision classique
                logits_lab = model(x_lab, training=True)
                loss_sup = loss_fn(y_lab, logits_lab)
    
                # Consistency regularization sur non-étiquetées
                logits_unlab = model(x_unlab, training=True)
                logits_unlab_aug = model(x_unlab_aug, training=True)
    
                prob = tf.sigmoid(logits_unlab)
                prob_aug = tf.sigmoid(logits_unlab_aug)
    
                loss_consistency = tf.reduce_mean(tf.square(prob - prob_aug))
    
                loss = loss_sup + consistency_weight * loss_consistency
    
            grads = tape.gradient(loss, model.trainable_variables)
            optimizer.apply_gradients(zip(grads, model.trainable_variables))
    
            total_loss += loss.numpy()
    
        print(f"Loss: {total_loss/steps_per_epoch:.4f}")
    
    # Évaluation simple
    acc_metric = tf.keras.metrics.BinaryAccuracy()
    for x_batch, y_batch in val_dataset:
        logits = model(x_batch, training=False)
        preds = tf.sigmoid(logits)
        acc_metric.update_state(y_batch, preds)
    
    print(f"Validation Accuracy: {acc_metric.result().numpy():.4f}")

    Explication du code :

    import tensorflow as tf importe la bibliothèque TensorFlow, un framework majeur pour le machine learning et le deep learning.
    
    import numpy as np importe la bibliothèque NumPy, utile pour la manipulation efficace des tableaux et des opérations numériques.
    
    
    1. Génération et préparation des données textuelles simulées
    generate_data(n_samples, labeled=True) génère des séquences de tokens aléatoires représentant des phrases simulées. - Si labeled=True, on génère aussi des labels binaires aléatoires (0 ou 1). - Sinon, seules les séquences sont générées sans étiquette. On crée : 1000 phrases étiquetées (X_labeled, y_labeled), 9000 phrases non étiquetées (X_unlabeled), 1000 phrases pour la validation (X_val, y_val).
    2. Définition du modèle LSTM simple pour classification binaire
    Le modèle est un réseau séquentiel composé de : - une couche Embedding qui transforme les indices de mots en vecteurs denses de dimension 64, - une couche bidirectionnelle LSTM de 64 unités pour capturer les dépendances contextuelles dans la séquence, - une couche dense finale avec 1 neurone pour produire un logit (sortie avant sigmoid).
    3. Configuration de l’entraînement
    - optimizer = tf.keras.optimizers.Adam() : optimiseur Adam pour la mise à jour des poids. - loss_fn = tf.keras.losses.BinaryCrossentropy(from_logits=True) : fonction de perte binaire adaptée aux logits. - batch_size = 64, consistency_weight = 1.0 (poids pour la perte de consistance), epochs = 5 définissent les paramètres d’entraînement.
    4. Fonction d’augmentation de texte
    augment_text(batch_x) remplace aléatoirement 10 % des tokens d’une séquence par un token aléatoire, simulant du bruit lexical et créant une version augmentée des phrases.
    5. Création des datasets TensorFlow
    - labeled_dataset contient les données étiquetées, mélangées, découpées en batchs, et répétées. - unlabeled_dataset contient les données non étiquetées, également mélangées, batchées et répétées. - val_dataset contient les données de validation batchées.
    6. Boucle d’entraînement semi-supervisé
    Pour chaque époque et batch : - On récupère un batch étiqueté (x_lab, y_lab) et un batch non étiqueté (x_unlab). - On crée une version augmentée du batch non étiqueté (x_unlab_aug). - Calcul des logits sur données étiquetées et calcul de la perte supervisée (loss_sup) avec les vraies étiquettes. - Calcul des logits sur données non étiquetées normales et augmentées. - Conversion des logits en probabilités (sigmoid). - Calcul d’une perte de consistance (loss_consistency) : moyenne des carrés des différences entre les deux distributions de probabilités, pour encourager la stabilité des prédictions malgré l’augmentation. - La perte totale est la somme : loss = loss_sup + consistency_weight * loss_consistency. - Les gradients sont calculés puis appliqués pour mettre à jour les poids du modèle. - Affichage de la perte moyenne par époque.
    7. Évaluation finale
    - Calcul de la précision sur le jeu de validation en comparant les prédictions (après sigmoid) aux vraies étiquettes avec BinaryAccuracy(). - Affichage de la précision finale sur les données de validation. Ce code met en œuvre un entraînement semi-supervisé combinant une supervision classique sur un petit ensemble étiqueté et une régularisation par consistance sur un grand ensemble non étiqueté, ce qui aide à améliorer la robustesse et la performance du modèle sur des données textuelles.