Pendant mon stage chez Norsys Afrique, j'ai eu la chance de travailler sur un projet d'analyse de sentiment qui allait devenir l'une de mes expériences d'apprentissage les plus précieuses. Ce projet a non seulement confirmé ma passion pour les applications concrètes de l'IA, mais m'a aussi appris l'importance de combler l'écart entre les connaissances théoriques et leur mise en œuvre réelle.
Le défi : comprendre le sentiment client à grande échelle
Norsys Afrique avait besoin d'un système capable d'analyser les retours clients issus de plusieurs canaux :
- Mentions sur les réseaux sociaux
- Tickets de support client
- Avis sur les produits
- Réponses aux enquêtes
L'objectif était de catégoriser automatiquement le sentiment et de fournir des enseignements exploitables pour améliorer l'expérience client et les décisions de l'entreprise.
Approche technique
1. Collecte et prétraitement des données
Le premier défi consistait à rassembler et nettoyer des données textuelles hétérogènes :
import pandas as pd
import re
from textblob import TextBlob
import nltk
from nltk.corpus import stopwords
class DataPreprocessor:
def __init__(self):
self.stop_words = set(stopwords.words('french', 'arabic', 'english'))
def clean_text(self, text):
# Remove special characters and normalize
text = re.sub(r'[^\w\s]', '', text)
text = text.lower()
# Remove stopwords
words = text.split()
words = [word for word in words if word not in self.stop_words]
return ' '.join(words)
def preprocess_dataset(self, df):
df['cleaned_text'] = df['text'].apply(self.clean_text)
return df2. Architecture du modèle avec TensorFlow
J'ai conçu une approche hybride combinant des techniques classiques de TAL et de l'apprentissage profond :
import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Embedding, LSTM, Dense, Dropout
from tensorflow.keras.preprocessing.text import Tokenizer
from tensorflow.keras.preprocessing.sequence import pad_sequences
class SentimentAnalysisModel:
def __init__(self, vocab_size=10000, max_length=100):
self.vocab_size = vocab_size
self.max_length = max_length
self.tokenizer = Tokenizer(num_words=vocab_size)
def build_model(self):
model = Sequential([
Embedding(self.vocab_size, 128, input_length=self.max_length),
LSTM(64, return_sequences=True),
Dropout(0.3),
LSTM(32),
Dropout(0.3),
Dense(16, activation='relu'),
Dense(3, activation='softmax') # Positive, Negative, Neutral
])
model.compile(
optimizer='adam',
loss='categorical_crossentropy',
metrics=['accuracy']
)
return model
def train_model(self, X_train, y_train, X_val, y_val):
model = self.build_model()
# Tokenize and pad sequences
X_train_seq = self.tokenizer.texts_to_sequences(X_train)
X_train_padded = pad_sequences(X_train_seq, maxlen=self.max_length)
X_val_seq = self.tokenizer.texts_to_sequences(X_val)
X_val_padded = pad_sequences(X_val_seq, maxlen=self.max_length)
# Train the model
history = model.fit(
X_train_padded, y_train,
validation_data=(X_val_padded, y_val),
epochs=50,
batch_size=32,
verbose=1
)
return model, history3. Développement de l'API Flask
Pour rendre le modèle accessible, j'ai créé une API REST :
from flask import Flask, request, jsonify
import pickle
import numpy as np
app = Flask(__name__)
# Load the trained model
model = tf.keras.models.load_model('sentiment_model.h5')
tokenizer = pickle.load(open('tokenizer.pkl', 'rb'))
@app.route('/predict', methods=['POST'])
def predict_sentiment():
try:
data = request.get_json()
text = data['text']
# Preprocess the text
cleaned_text = preprocess_text(text)
# Tokenize and pad
sequence = tokenizer.texts_to_sequences([cleaned_text])
padded_sequence = pad_sequences(sequence, maxlen=100)
# Make prediction
prediction = model.predict(padded_sequence)
sentiment = np.argmax(prediction[0])
# Map to sentiment labels
sentiment_labels = {0: 'Negative', 1: 'Neutral', 2: 'Positive'}
confidence = float(np.max(prediction[0]))
return jsonify({
'sentiment': sentiment_labels[sentiment],
'confidence': confidence,
'text': text
})
except Exception as e:
return jsonify({'error': str(e)}), 500
if __name__ == '__main__':
app.run(debug=True)Performances du modèle
Je n'ai pas revérifié les performances de ce modèle face aux journaux d'entraînement d'origine du stage ; je ne publie donc ni exactitude, ni précision, ni rappel, ni score F1.
Ce que ce type de système change :
- Délai de traitement : les retours sont catégorisés à mesure qu'ils arrivent, au lieu d'attendre dans une file de relecture
- Régularité : le même modèle applique les mêmes critères à chaque texte, ce qui supprime les écarts d'un évaluateur à l'autre
- Débit : une fois déployé derrière l'API Flask, le volume est limité par l'infrastructure et non par le nombre d'analystes
Je n'ai pas accès aux données internes de coûts ou d'effectifs de Norsys Afrique ; je n'attache donc ici ni économie chiffrée ni « X fois plus rapide » — cela demanderait leur propre point de référence pour être mesuré.
Difficultés et solutions
1. Prise en charge multilingue
Difficulté : traiter des textes en français, en arabe et en anglais Solution : détection de la langue et chaînes de prétraitement distinctes
2. Jeu de données déséquilibré
Difficulté : bien plus d'échantillons neutres que positifs ou négatifs Solution : suréchantillonnage avec SMOTE et pondération des classes à l'entraînement
3. Traitement en temps réel
Difficulté : exigences sur le temps de réponse de l'API Solution : optimisation du modèle et stratégies de mise en cache
# Caching implementation
from functools import lru_cache
@lru_cache(maxsize=1000)
def cached_prediction(text_hash, text):
return model.predict(padded_sequence)Ce que j'en ai retenu
Compétences techniques acquises :
- TensorFlow / Keras : développement de modèles d'apprentissage profond
- Techniques de TAL : prétraitement du texte, tokenisation, plongements lexicaux
- Développement d'API : Flask, services REST, gestion des erreurs
- Déploiement de modèles : contraintes de production, optimisation des performances
Compétences transversales développées :
- Résolution de problèmes : décomposer des besoins complexes
- Communication : expliquer des concepts techniques à des interlocuteurs non techniques
- Gestion de projet : tenir des délais et des livrables
- Documentation : produire une documentation technique complète
Améliorations futures
- Architectures avancées : expérimenter BERT et les modèles transformers
- Traitement en flux : mettre en place Kafka pour une analyse de sentiment en temps réel
- Analyse multimodale : intégrer images et vidéos
- Tests A/B : un cadre pour comparer les performances des modèles
Structure du dépôt de code
sentiment-analysis/
├── data/
│ ├── raw/
│ └── processed/
├── models/
│ ├── sentiment_model.h5
│ └── tokenizer.pkl
├── src/
│ ├── preprocessing.py
│ ├── model_training.py
│ └── api.py
├── tests/
└── requirements.txt
Conclusion
Ce projet a marqué un tournant dans ma compréhension de la façon dont l'IA peut résoudre de vrais problèmes d'entreprise. L'alliance entre connaissances théoriques et mise en œuvre pratique m'a appris qu'un projet d'IA réussi exige :
- Un problème clairement défini : comprendre le besoin métier
- Des données de qualité : le socle de tout projet d'apprentissage automatique
- Un développement itératif : amélioration et tests continus
- Une conception centrée utilisateur : bâtir des solutions que les gens veulent vraiment utiliser
L'expérience chez Norsys Afrique a renforcé ma passion pour la création d'applications d'IA concrètes qui changent réellement quelque chose aux opérations d'une entreprise.
Vous avez une agence d'excursions, un riad ou un commerce ? Envoyez-moi votre site ou votre fiche Google : je vous dirai, en langage clair, où les visiteurs hésitent et ce que je corrigerais en premier. Demander mon audit gratuit.