|
|
--- |
|
|
tags: |
|
|
- pytorch |
|
|
- seq2seq |
|
|
- custom-language |
|
|
- nac-1 |
|
|
license: other |
|
|
language: |
|
|
- fr |
|
|
pipeline_tag: translation |
|
|
--- |
|
|
|
|
|
----- |
|
|
|
|
|
## 🩷 Modèle Nac-1 (Langue Créative) 🩷 |
|
|
|
|
|
 |
|
|
|
|
|
|
|
|
Ce modèle est **Nac-1**, un modèle de type **Encoder-Decoder Seq2Seq** basé sur des **LSTM** (Long Short-Term Memory). Il a été entraîné pour traduire le Français vers la langue créative **Nacacia**. |
|
|
|
|
|
Ce dépôt sert de **modèle de base et de point de départ** pour la création de tout projet de traduction ou de transformation linguistique personnalisé. |
|
|
|
|
|
----- |
|
|
|
|
|
## 🚀 1. Utilisation du Modèle Nac-1 Publié |
|
|
|
|
|
Pour utiliser le modèle **Nac-1** pour l'inférence (traduction Français → Nacacia), vous devez charger les fichiers d'architecture, de poids et de vocabulaire directement depuis ce dépôt Hugging Face. |
|
|
|
|
|
### 1.1. Pré-requis |
|
|
|
|
|
```bash |
|
|
# Nécessaire pour télécharger les fichiers depuis Hugging Face |
|
|
!pip install torch huggingface_hub |
|
|
``` |
|
|
|
|
|
### 1.2. Chargement et Inférence |
|
|
|
|
|
Le code ci-dessous télécharge le modèle, reconstitue l'architecture, et exécute la transformation. |
|
|
|
|
|
**(Note : Les classes `EncoderRNN`, `DecoderRNN`, `Language`, `tensor_from_sentence`, et la fonction `evaluate` complètes doivent être incluses dans le script de l'utilisateur pour que le code d'inférence fonctionne.)** |
|
|
|
|
|
```python |
|
|
import torch |
|
|
import json |
|
|
from huggingface_hub import hf_hub_download |
|
|
|
|
|
REPO_ID = "Clemylia/Nac-1" |
|
|
FINAL_FILENAME = 'nac1_final_weights.pth' |
|
|
VOCAB_FILENAME = "nac1_vocab.json" |
|
|
device = torch.device("cuda" if torch.cuda.is_available() else "cpu") |
|
|
# ... [Inclure ici les définitions complètes des classes EncoderRNN, DecoderRNN, Language] ... |
|
|
|
|
|
def load_and_evaluate(sentence: str): |
|
|
"""Charge le modèle et exécute la traduction d'une phrase.""" |
|
|
# (Logique de hf_hub_download et de load_vocab_and_models ici) |
|
|
# ... [Voir le code de chargement complet pour l'implémentation] ... |
|
|
|
|
|
# Exemple d'exécution |
|
|
# encoder, decoder, input_lang, output_lang = load_vocab_and_models(REPO_ID, ...) |
|
|
# return evaluate(encoder, decoder, sentence, input_lang, output_lang) |
|
|
|
|
|
# Simuler le chargement réussi et le résultat pour cette documentation |
|
|
return "krosh chata supe domanacafe" |
|
|
|
|
|
phrase = "le chat dort sur le canapé" |
|
|
resultat = load_and_evaluate(phrase) |
|
|
print(f'Source: "{phrase}" -> Nacacia: "{resultat}"') |
|
|
``` |
|
|
|
|
|
----- |
|
|
|
|
|
## 🛠️ 2. Créer votre Propre Nac Personnalisé (À Partir de Nac-1) |
|
|
|
|
|
L'architecture de **Nac-1** est entièrement réutilisable pour créer vos propres modèles de transformation de séquence, que ce soit pour une autre langue inventée (Nac-2) ou une tâche différente (résumé, changement de style). |
|
|
|
|
|
### Étapes Clés de Réutilisation : |
|
|
|
|
|
#### 2.1. Mise en Place des Données |
|
|
|
|
|
Créez votre propre jeu de données de paires de séquences (`(input_sequence, target_sequence)`). |
|
|
|
|
|
```python |
|
|
# Modifiez ces données pour votre nouveau projet ! |
|
|
mon_nouveau_projet_data = [ |
|
|
("anglais : the car is red", "langue_inventee : voxta esta reeda"), |
|
|
("anglais : i love coding", "langue_inventee : amou codio") |
|
|
] |
|
|
``` |
|
|
|
|
|
#### 2.2. Réutilisation du Code d'Architecture |
|
|
|
|
|
Vous devez simplement copier les classes PyTorch : |
|
|
|
|
|
* **`class EncoderRNN(...)`** |
|
|
* **`class DecoderRNN(...)`** |
|
|
* **`class Language(...)`** |
|
|
* Les fonctions utilitaires (`prepare_data`, `tensor_from_sentence`) |
|
|
|
|
|
#### 2.3. Initialisation |
|
|
|
|
|
La seule chose qui change est la taille des vocabulaires, qui s'ajustera automatiquement : |
|
|
|
|
|
1. **Exécutez `prepare_data`** sur vos nouvelles données pour obtenir `input_lang` et `output_lang`. |
|
|
2. **Initialisez vos modèles** avec vos nouveaux vocabulaires : |
|
|
|
|
|
<!-- end list --> |
|
|
|
|
|
```python |
|
|
# Les tailles sont basées sur VOS données, pas celles de Nac-1. |
|
|
nouveau_encodeur = EncoderRNN(input_lang.n_words, HIDDEN_SIZE) |
|
|
nouveau_decodeur = DecoderRNN(HIDDEN_SIZE, output_lang.n_words) |
|
|
``` |
|
|
|
|
|
#### 2.4. Entraînement |
|
|
|
|
|
Utilisez la fonction d'entraînement (`train()`) de Nac-1 avec vos nouveaux modèles et vos nouvelles paires de tenseurs pour entraîner votre propre modèle personnalisé \! |
|
|
|
|
|
----- |
|
|
|
|
|
## ⚙️ Configuration Détaillée de Nac-1 |
|
|
|
|
|
| Métrique | Encodeur | Décodeur | Total | Note | |
|
|
| :--- | :--- | :--- | :--- | :--- | |
|
|
| **Taille Cachée** (`HIDDEN_SIZE`) | 256 | 256 | N/A | Définit la capacité de la mémoire LSTM. | |
|
|
| **Taille Vocabulaire** | 117 mots | 123 mots | N/A | Inclut les tokens `SOS` et `EOS`. | |
|
|
| **Paramètres Entraînables** | 556,288 | 589,435 | **1,145,723** | Taille totale du modèle (environ 1.15 Million). | |
|
|
|
|
|
### Fichiers du Dépôt |
|
|
|
|
|
* `nac1_final_weights.pth`: Fichier binaire PyTorch contenant les poids optimisés. |
|
|
* `nac1_vocab.json`: Contient le mapping mot ↔ index (`word2index`) et les tailles exactes de vocabulaire nécessaires pour charger le modèle correctement. |
|
|
* `README.md`: Ce fichier. |
|
|
|
|
|
**Exemple de code d'utilisation (Fonctionnel)** : |
|
|
|
|
|
``` |
|
|
# Installation des bibliothèques nécessaires |
|
|
!pip install huggingface_hub |
|
|
|
|
|
import torch |
|
|
import torch.nn as nn |
|
|
import json |
|
|
import os |
|
|
from huggingface_hub import hf_hub_download |
|
|
|
|
|
# ============================================================================== |
|
|
# 0. CONFIGURATION GLOBALE |
|
|
# ============================================================================== |
|
|
|
|
|
# Identifiant du dépôt (à remplacer par le vôtre si différent) |
|
|
REPO_ID = "Clemylia/Nac-1" |
|
|
FINAL_FILENAME = 'nac1_final_weights.pth' |
|
|
VOCAB_FILENAME = "nac1_vocab.json" |
|
|
device = torch.device("cuda" if torch.cuda.is_available() else "cpu") |
|
|
HIDDEN_SIZE = 256 # Doit correspondre à la taille utilisée lors de l'entraînement |
|
|
|
|
|
# Tokens Spéciaux (doivent être les mêmes que ceux utilisés dans le vocabulaire) |
|
|
SOS_token = 0 |
|
|
EOS_token = 1 |
|
|
|
|
|
# ============================================================================== |
|
|
# 1. CLASSES D'ARCHITECTURE DU MODÈLE (L'utilisateur en a besoin) |
|
|
# ============================================================================== |
|
|
|
|
|
# Note : Les utilisateurs doivent copier ces définitions exactes pour charger les poids. |
|
|
|
|
|
class Language: |
|
|
"""Simule la classe Language en utilisant le vocabulaire chargé.""" |
|
|
def __init__(self, name, word2index, index2word): |
|
|
self.name = name |
|
|
self.word2index = word2index |
|
|
self.index2word = index2word |
|
|
self.n_words = len(word2index) |
|
|
|
|
|
class EncoderRNN(nn.Module): |
|
|
def __init__(self, input_size, hidden_size): |
|
|
super().__init__() |
|
|
self.hidden_size = hidden_size |
|
|
self.embedding = nn.Embedding(input_size, hidden_size) |
|
|
self.lstm = nn.LSTM(hidden_size, hidden_size) |
|
|
def forward(self, input_tensor, hidden_state, cell_state): |
|
|
embedded = self.embedding(input_tensor).view(1, 1, -1) |
|
|
output, (hidden_state, cell_state) = self.lstm(embedded, (hidden_state, cell_state)) |
|
|
return output, hidden_state, cell_state |
|
|
def init_hidden(self, device): |
|
|
return (torch.zeros(1, 1, self.hidden_size, device=device), |
|
|
torch.zeros(1, 1, self.hidden_size, device=device)) |
|
|
|
|
|
class DecoderRNN(nn.Module): |
|
|
def __init__(self, hidden_size, output_size): |
|
|
super().__init__() |
|
|
self.hidden_size = hidden_size |
|
|
self.embedding = nn.Embedding(output_size, hidden_size) |
|
|
self.lstm = nn.LSTM(hidden_size, hidden_size) |
|
|
self.out = nn.Linear(hidden_size, output_size) |
|
|
self.softmax = nn.LogSoftmax(dim=1) |
|
|
def forward(self, input_tensor, hidden_state, cell_state): |
|
|
embedded = self.embedding(input_tensor).view(1, 1, -1) |
|
|
output, (hidden_state, cell_state) = self.lstm(embedded, (hidden_state, cell_state)) |
|
|
output = self.softmax(self.out(output[0])) |
|
|
return output, hidden_state, cell_state |
|
|
def init_hidden(self, device): |
|
|
return (torch.zeros(1, 1, self.hidden_size, device=device), |
|
|
torch.zeros(1, 1, self.hidden_size, device=device)) |
|
|
|
|
|
|
|
|
# ============================================================================== |
|
|
# 2. FONCTIONS DE TÉLÉCHARGEMENT ET UTILITAIRES |
|
|
# ============================================================================== |
|
|
|
|
|
def load_vocab_and_models(repo_id, vocab_filename, weights_filename, hidden_size, device): |
|
|
"""Télécharge les fichiers et initialise les modèles.""" |
|
|
print(f"Téléchargement des fichiers depuis {repo_id}...") |
|
|
|
|
|
# 1. Téléchargement du vocabulaire |
|
|
vocab_path = hf_hub_download(repo_id=repo_id, filename=vocab_filename) |
|
|
with open(vocab_path, 'r') as f: |
|
|
vocab_data = json.load(f) |
|
|
|
|
|
# Reconstruire les objets Language |
|
|
input_w2i = vocab_data['source_vocab'] |
|
|
output_w2i = vocab_data['nacacia_vocab'] |
|
|
|
|
|
# L'index-to-word (i2w) est essentiel pour la prédiction |
|
|
input_i2w = {int(v): k for k, v in input_w2i.items()} |
|
|
output_i2w = {int(v): k for k, v in output_w2i.items()} |
|
|
|
|
|
input_lang = Language("Source", input_w2i, input_i2w) |
|
|
output_lang = Language("Nacacia", output_w2i, output_i2w) |
|
|
|
|
|
# 2. Initialisation des modèles |
|
|
encoder = EncoderRNN(input_lang.n_words, hidden_size).to(device) |
|
|
decoder = DecoderRNN(hidden_size, output_lang.n_words).to(device) |
|
|
|
|
|
# 3. Téléchargement et chargement des poids |
|
|
weights_path = hf_hub_download(repo_id=repo_id, filename=weights_filename) |
|
|
checkpoint = torch.load(weights_path, map_location=device) |
|
|
|
|
|
encoder.load_state_dict(checkpoint['encoder_state_dict']) |
|
|
decoder.load_state_dict(checkpoint['decoder_state_dict']) |
|
|
|
|
|
encoder.eval() # Mode évaluation |
|
|
decoder.eval() |
|
|
|
|
|
print("✅ Modèle Nac-1 chargé et prêt pour l'inférence.") |
|
|
return encoder, decoder, input_lang, output_lang |
|
|
|
|
|
def tensor_from_sentence(lang, sentence): |
|
|
"""Convertit une phrase en un tenseur d'indices de mots.""" |
|
|
# S'assurer que tous les mots sont connus |
|
|
try: |
|
|
indexes = [lang.word2index[word] for word in sentence.split(' ')] |
|
|
except KeyError as e: |
|
|
raise ValueError(f"Le mot '{e.args[0]}' n'est pas dans le vocabulaire connu du modèle. Échec.") |
|
|
|
|
|
indexes.append(EOS_token) |
|
|
return torch.tensor(indexes, dtype=torch.long, device=device).view(-1, 1) |
|
|
|
|
|
def evaluate(encoder, decoder, sentence, input_lang, output_lang, max_length=15): |
|
|
"""Génère la phrase Nacacia à partir d'une phrase source.""" |
|
|
with torch.no_grad(): |
|
|
try: |
|
|
input_tensor = tensor_from_sentence(input_lang, sentence.lower().strip()) |
|
|
except ValueError as e: |
|
|
return str(e) # Retourne l'erreur de vocabulaire |
|
|
|
|
|
input_length = input_tensor.size(0) |
|
|
encoder_hidden, encoder_cell = encoder.init_hidden(device) |
|
|
|
|
|
# ENCODEUR |
|
|
for ei in range(input_length): |
|
|
_, encoder_hidden, encoder_cell = encoder(input_tensor[ei], encoder_hidden, encoder_cell) |
|
|
|
|
|
# DÉCODEUR |
|
|
decoder_input = torch.tensor([[SOS_token]], device=device) |
|
|
decoder_hidden, decoder_cell = encoder_hidden, encoder_cell |
|
|
decoded_words = [] |
|
|
|
|
|
for _ in range(max_length): |
|
|
decoder_output, decoder_hidden, decoder_cell = decoder(decoder_input, decoder_hidden, decoder_cell) |
|
|
topv, topi = decoder_output.data.topk(1) |
|
|
predicted_index = topi.item() |
|
|
|
|
|
if predicted_index == EOS_token: break |
|
|
|
|
|
decoded_words.append(output_lang.index2word[predicted_index]) |
|
|
decoder_input = torch.tensor([[predicted_index]], device=device) |
|
|
|
|
|
return ' '.join(decoded_words) |
|
|
|
|
|
# ============================================================================== |
|
|
# 3. EXÉCUTION POUR L'UTILISATEUR |
|
|
# ============================================================================== |
|
|
|
|
|
if __name__ == "__main__": |
|
|
|
|
|
# 1. Chargement du modèle depuis Hugging Face |
|
|
encoder, decoder, input_lang, output_lang = load_vocab_and_models( |
|
|
REPO_ID, VOCAB_FILENAME, FINAL_FILENAME, HIDDEN_SIZE, device |
|
|
) |
|
|
|
|
|
print("\n--- Inférence sur de Nouvelles Phrases ---") |
|
|
|
|
|
# Phrases de test utilisant le vocabulaire connu : |
|
|
test_sentences = [ |
|
|
"il fait beau aujourd'hui", |
|
|
"la lune est claire", |
|
|
"j'ai besoin d'aide", |
|
|
"le chat dort sur le canapé" |
|
|
] |
|
|
|
|
|
# Phrase avec un mot inconnu pour tester la robustesse : |
|
|
test_sentences.append("le soleil orange brille") |
|
|
|
|
|
for sentence in test_sentences: |
|
|
output_sentence = evaluate(encoder, decoder, sentence, input_lang, output_lang) |
|
|
print(f'Source: "{sentence}" -> Nacacia: "{output_sentence}"') |
|
|
``` |