Nac-1 / README.md
Clemylia's picture
Update README.md
ae17d5e verified
---
tags:
- pytorch
- seq2seq
- custom-language
- nac-1
license: other
language:
- fr
pipeline_tag: translation
---
-----
## 🩷 Modèle Nac-1 (Langue Créative) 🩷
![Nac](http://www.image-heberg.fr/files/17597665132703744276.png)
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}"')
```