Bien sûr ! Si vous me montrez le code, je serais ravi de vous l’expliquer en détail. N’hésitez pas à partager le code ou une partie du code que vous souhaitez comprendre. 😊
Le code reste en anglais, car il s’agit d’un bloc de code Python. La traduction des noms de variables ou de fonctions pourrait entraîner des erreurs de syntaxe ou de logique.
ChatGPT :
Bien sûr ! Le code que vous avez fourni semble faire partie d’un algorithme d’apprentissage automatique, plus précisément une implémentation de la descente de gradient stochastique (SGD) pour mettre à jour les poids et les biais dans un réseau de neurones pendant le processus d’entraînement. Décomposons-le étape par étape :
self.weights et self.biases :
Ces variables font probablement partie d’une classe de réseau de neurones, représentant les poids et les biais du réseau. Dans un réseau de neurones, les poids sont des paramètres qui ajustent la force des connexions entre les neurones de différentes couches, tandis que les biais sont des paramètres qui contrôlent le seuil d’activation des neurones.
nabla_w et nabla_b :
Ces variables stockent probablement les gradients de la fonction de coût par rapport aux poids et aux biais, respectivement. Pendant le processus d’entraînement, les gradients sont calculés pour déterminer comment la fonction de coût change en fonction des poids et des biais. Ces informations sont ensuite utilisées pour mettre à jour les paramètres afin de minimiser le coût.
eta :
Il s’agit du taux d’apprentissage, qui contrôle la taille des pas effectués dans la direction des gradients lors de la mise à jour des paramètres. Un taux d’apprentissage plus élevé peut accélérer la convergence pendant l’entraînement, mais il peut également provoquer une instabilité. Un taux d’apprentissage plus faible peut améliorer la stabilité, mais augmenter le temps d’entraînement.
mini_batch :
Il s’agit d’un sous-ensemble des données d’entraînement utilisé pour chaque itération de la descente de gradient stochastique. La descente de gradient par mini-lots est une variante de la SGD où l’ensemble des données d’entraînement est divisé en lots plus petits, et les mises à jour des paramètres sont effectuées en utilisant chaque mini-lot.
Cette ligne met à jour les poids du réseau de neurones. Elle utilise une compréhension de liste pour parcourir chaque poids w et son gradient correspondant nw. Pour chaque poids, elle soustrait une partie du gradient (pondérée par le taux d’apprentissage eta et la taille du mini-lot) du poids initial. C’est ainsi que les poids sont mis à jour pour minimiser la fonction de coût.
Le code reste en anglais, car il s’agit d’un extrait de code Python. La traduction n’est pas nécessaire pour les blocs de code.
Cette ligne met à jour les biais du réseau de neurones de manière similaire. Elle utilise une compréhension de liste pour parcourir chaque biais b et son gradient correspondant nb. Pour chaque biais, elle soustrait une portion du gradient (pondérée par le taux d’apprentissage eta et la taille du mini-lot) du biais d’origine.
En résumé, ces lignes de code effectuent la mise à jour des poids et des biais du réseau de neurones en utilisant la descente de gradient stochastique. Ce processus est répété pour chaque mini-lot pendant la phase d’entraînement afin d’optimiser les paramètres du réseau et d’améliorer ses performances sur la tâche donnée.
Zhiwei : Qu’est-ce qu’un modèle de langage SpaCy ?
ChatGPT : SpaCy est une bibliothèque open-source de traitement du langage naturel (NLP) développée par Explosion AI. Elle est conçue pour être efficace, rapide et prête pour la production, ce qui en fait un choix populaire pour diverses tâches de NLP. SpaCy propose des modèles linguistiques pré-entraînés capables de traiter et de comprendre du texte, permettant aux développeurs d’effectuer diverses tâches de NLP telles que l’étiquetage morphosyntaxique, la reconnaissance d’entités nommées, l’analyse syntaxique de phrases, et bien plus encore.
Les principales caractéristiques du modèle de langage SpaCy incluent :
Tokenisation : SpaCy peut diviser un texte en mots ou jetons individuels, en tenant compte de diverses règles et complexités linguistiques.
Étiquetage morphosyntaxique : La bibliothèque peut attribuer des étiquettes morphosyntaxiques à chaque token, indiquant s’il s’agit d’un nom, d’un verbe, d’un adjectif, etc.
Reconnaissance d’entités nommées (NER) : SpaCy peut identifier et catégoriser des entités telles que les noms de personnes, d’organisations, de lieux, de dates, etc.
Analyse des dépendances : Il peut analyser la structure grammaticale d’une phrase et déterminer les relations entre les mots.
Lemmatisation : SpaCy peut convertir les mots en leur forme de base ou racine (lemmes).
Vecteurs de mots : La bibliothèque fournit des vecteurs de mots, également appelés embeddings de mots, qui sont des représentations numériques denses des mots capturant leur signification sémantique.
SpaCy prend en charge plusieurs langues et est livré avec des modèles pré-entraînés pour différentes langues, ce qui le rend largement utilisé dans diverses applications de traitement du langage naturel (NLP), telles que l’extraction d’informations, l’analyse de sentiments, les chatbots, la traduction automatique, et bien plus encore. De plus, il permet aux développeurs d’entraîner des modèles personnalisés sur leurs propres ensembles de données si nécessaire.
Zhiwei : Qu’est-ce qu’un modèle de langage SpaCy ?
ChatGPT : SpaCy est une bibliothèque open-source de traitement du langage naturel (NLP) développée par Explosion AI. Elle est conçue pour être efficace, rapide et facile à utiliser, ce qui en fait un choix populaire pour diverses tâches de NLP. SpaCy propose des modèles de langage pré-entraînés pour plusieurs langues, permettant aux utilisateurs d’effectuer des tâches telles que la tokenisation, l’étiquetage morphosyntaxique, la reconnaissance d’entités nommées, l’analyse de dépendances, et bien plus encore.
Le cœur de la rapidité et de l’efficacité de SpaCy réside dans ses implémentations et structures de données optimisées en Cython, ce qui le rend particulièrement adapté aux environnements de production et aux applications réelles. La bibliothèque est écrite en Python et est livrée avec des modèles pré-entraînés pour diverses langues, notamment l’anglais, l’allemand, le français, l’espagnol, et bien d’autres.
Les modèles linguistiques de SpaCy utilisent des techniques d’apprentissage profond pour apprendre les motifs sous-jacents dans les données de langage naturel. Ces modèles sont entraînés sur de grands corpus de texte, et les représentations apprises peuvent ensuite être utilisées pour diverses tâches de traitement du langage naturel (NLP). Les modèles pré-entraînés peuvent être affinés sur des données spécifiques pour obtenir de meilleures performances sur des tâches propres à un domaine.
L’architecture et la facilité d’utilisation ont fait de SpaCy un choix populaire parmi les développeurs et les chercheurs de la communauté NLP. Il est souvent utilisé pour des tâches telles que l’extraction d’informations, la classification de texte, la reconnaissance d’entités nommées, l’étiquetage morphosyntaxique et l’analyse syntaxique. De plus, la conception modulaire de SpaCy permet aux utilisateurs de l’intégrer facilement dans leurs flux de travail et pipelines NLP existants.
# La graine doit être la même dans tous les processus
torch.manual_seed(1)
iflocal_rank>0:sys.stdout=open(os.devnull,"w")
start_time=time.time()checkpoints=sorted(Path(ckpt_dir).glob("*.pth"))assertlen(checkpoints)>0,f"aucun fichier de point de contrôle trouvé dans {ckpt_dir}"assertmodel_parallel_size==len(checkpoints),f"Chargement d'un point de contrôle pour MP={len(checkpoints)} mais la taille du monde est {model_parallel_size}"ckpt_path=checkpoints[get_model_parallel_rank()]checkpoint=torch.load(ckpt_path,map_location="cpu")withopen(Path(ckpt_dir)/"params.json","r")asf:params=json.loads(f.read())
Exécutez la commande, puis récupérez le journal des erreurs.
% torchrun --nproc_per_node 1 example_text_completion.py \--ckpt_dir llama-2-7b/ \--tokenizer_path tokenizer.model \--max_seq_len 128 --max_batch_size 4
NOTE: Les redirections ne sont actuellement pas prises en charge sous Windows ou MacOs.
Traceback (dernier appel le plus récent) :
File "/Users/lzwjava/projects/llama/example_text_completion.py", line 55, in <module>
fire.Fire(main)
File "/Users/lzwjava/anaconda3/lib/python3.10/site-packages/fire/core.py", line 141, in Fire
component_trace = _Fire(component, args, parsed_flag_args, context, name)
File "/Users/lzwjava/anaconda3/lib/python3.10/site-packages/fire/core.py", line 475, in _Fire
component, remaining_args = _CallAndUpdateTrace(
File "/Users/lzwjava/anaconda3/lib/python3.10/site-packages/fire/core.py", line 691, in _CallAndUpdateTrace
component = fn(*varargs, **kwargs)
File "/Users/lzwjava/projects/llama/example_text_completion.py", line 18, in main
generator = Llama.build(
File "/Users/lzwjava/projects/llama/llama/generation.py", line 62, in build
torch.distributed.init_process_group("nccl")
File "/Users/lzwjava/anaconda3/lib/python3.10/site-packages/torch/distributed/distributed_c10d.py", line 907, in init_process_group
default_pg = _new_process_group_helper(
File "/Users/lzwjava/anaconda3/lib/python3.10/site-packages/torch/distributed/distributed_c10d.py", line 1013, in _new_process_group_helper
raise RuntimeError("Distributed package doesn't have NCCL ""built in")
RuntimeError: Le package distribué ne contient pas NCCL intégré
ERROR:torch.distributed.elastic.multiprocessing.api:échec (code de sortie : 1) local_rank: 0 (pid: 23273)du binaire : /Users/lzwjava/anaconda3/bin/python
Traceback (dernier appel le plus récent) :
Fichier “/Users/lzwjava/anaconda3/bin/torchrun”, ligne 33, dans
sys.exit(load_entry_point('torch==2.0.1', 'console_scripts', 'torchrun')())
Fichier "/Users/lzwjava/anaconda3/lib/python3.10/site-packages/torch/distributed/elastic/multiprocessing/errors/__init__.py", ligne 346, dans wrapper
return f(*args, **kwargs)
Fichier "/Users/lzwjava/anaconda3/lib/python3.10/site-packages/torch/distributed/run.py", ligne 794, dans main
run(args)
Fichier "/Users/lzwjava/anaconda3/lib/python3.10/site-packages/torch/distributed/run.py", ligne 785, dans run
elastic_launch(
Fichier "/Users/lzwjava/anaconda3/lib/python3.10/site-packages/torch/distributed/launcher/api.py", ligne 134, dans __call__
return launch_agent(self._config, self._entrypoint, list(args))
Fichier "/Users/lzwjava/anaconda3/lib/python3.10/site-packages/torch/distributed/launcher/api.py", ligne 250, dans launch_agent
raise ChildFailedError(
torch.distributed.elastic.multiprocessing.errors.ChildFailedError:
============================================================
example_text_completion.py ÉCHEC
------------------------------------------------------------
Échecs :
------------------------------------------------------------
Cause racine (premier échec observé) :
[0] :
temps : 2023-08-03_15:35:37
hôte : 1.0.0.127.in-addr.arpa
rang : 0 (rang_local : 0)
code sortie : 1 (pid : 23273)
fichier d'erreur : <N/A>
traceback : Pour activer la traceback, voir : https://pytorch.org/docs/stable/elastic/errors.html
============================================================
```
Apprenez à interpréter la trace de la pile d'erreurs.
Demandez à ChatGPT ce que signifie Backend.NCCL dans PyTorch ?
---
Zhiwei :
code :
```python
import torch
from transformers import LlamaTokenizer, LlamaForCausalLM
```
```python
model_path = '.'
# model_path = 'openlm-research/open_llama_7b'
```
```python
tokenizer = LlamaTokenizer.from_pretrained(model_path)
model = LlamaForCausalLM.from_pretrained(
model_path, torch_dtype=torch.float16, device_map='auto',
)
```
```python
prompt = 'Q: Quel est le plus grand animal ?\nA:'
input_ids = tokenizer(prompt, return_tensors="pt").input_ids
generation_output = model.generate(
input_ids=input_ids, max_new_tokens=32
)
print(tokenizer.decode(generation_output[0]))
```
erreur :
```shell
/home/lzw/anaconda3/envs/llama/lib/python3.11/site-packages/transformers/generation/utils.py:1445: UserWarning: Vous appelez .generate() avec `input_ids` sur un type de périphérique différent de celui de votre modèle. `input_ids` est sur le CPU, alors que le modèle est sur le CUDA. Vous pourriez rencontrer des comportements inattendus ou une génération plus lente. Assurez-vous que vous avez placé `input_ids` sur le bon périphérique en appelant par exemple input_ids = input_ids.to('cuda') avant d'exécuter `.generate()`.
warnings.warn(
Traceback (most recent call last):
File "/home/lzw/Projects/open_llama_3b/run.py", line 17, in
generation_output = model.generate(
^^^^^^^^^^^^^^^
File "/home/lzw/anaconda3/envs/llama/lib/python3.11/site-packages/torch/utils/_contextlib.py", line 115, in decorate_context
return func(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^
File "/home/lzw/anaconda3/envs/llama/lib/python3.11/site-packages/transformers/generation/utils.py", line 1515, in generate
return self.greedy_search(
^^^^^^^^^^^^^^^^^^^
File "/home/lzw/anaconda3/envs/llama/lib/python3.11/site-packages/transformers/generation/utils.py", line 2332, in greedy_search
outputs = self(
^^^^^
File "/home/lzw/anaconda3/envs/llama/lib/python3.11/site-packages/torch/nn/modules/module.py", line 1501, in _call_impl
return forward_call(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/lzw/anaconda3/envs/llama/lib/python3.11/site-packages/transformers/models/llama/modeling_llama.py", line 688, in forward
outputs = self.model(
^^^^^^^^^^^
File "/home/lzw/anaconda3/envs/llama/lib/python3.11/site-packages/torch/nn/modules/module.py", line 1501, in _call_impl
return forward_call(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/lzw/anaconda3/envs/llama/lib/python3.11/site-packages/transformers/models/llama/modeling_llama.py", line 531, in forward
inputs_embeds = self.embed_tokens(input_ids)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/lzw/anaconda3/envs/llama/lib/python3.11/site-packages/torch/nn/modules/module.py", line 1501, in _call_impl
return forward_call(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/lzw/anaconda3/envs/llama/lib/python3.11/site-packages/torch/nn/modules/sparse.py", line 162, in forward
return F.embedding(
^^^^^^^^^^^^
File "/home/lzw/anaconda3/envs/llama/lib/python3.11/site-packages/torch/nn/functional.py", line 2210, in embedding
return torch.embedding(weight, input, padding_idx, scale_grad_by_freq, sparse)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
RuntimeError: Tous les tenseurs doivent être sur le même périphérique, mais au moins deux périphériques ont été trouvés, cuda:0 et cpu! (lors de la vérification de l'argument pour l'argument index dans la méthode wrapper_CUDA__index_select)
```
comment résoudre ?
ChatGPT :
Le message d'erreur que vous rencontrez indique qu'il y a une incompatibilité entre les types de périphériques de votre tenseur d'entrée (`input_ids`) et votre modèle (`LlamaForCausalLM`). Le tenseur d'entrée se trouve sur le CPU (`cpu`), tandis que le modèle est sur le GPU (`cuda`). Pour résoudre ce problème, vous devez vous assurer que le tenseur d'entrée se trouve sur le même périphérique que le modèle avant de générer du texte à l'aide du modèle.
Voici le code modifié pour résoudre le problème :
```python
import torch
from transformers import LlamaTokenizer, LlamaForCausalLM
```
```python
model_path = '.'
# model_path = 'openlm-research/open_llama_7b'
```
```python
tokenizer = LlamaTokenizer.from_pretrained(model_path)
model = LlamaForCausalLM.from_pretrained(
model_path, torch_dtype=torch.float16, device_map='auto',
)
```
prompt = 'Q: Quel est le plus grand animal ?\nA:'
input_ids = tokenizer(prompt, return_tensors="pt").input_ids
# Déplacer le tenseur input_ids sur le même appareil que le modèle
input_ids = input_ids.to(model.device)
```python
generation_output = model.generate(
input_ids=input_ids, max_new_tokens=32
)
print(tokenizer.decode(generation_output[0]))
```
Dans ce code, j'ai ajouté la ligne `input_ids = input_ids.to(model.device)` après avoir obtenu le tenseur `input_ids` à partir du tokenizer. Cette ligne déplace le tenseur `input_ids` sur le même appareil que le modèle (soit le CPU, soit le GPU) avant de générer du texte. Cela devrait résoudre l'erreur "Expected all tensors to be on the same device".
N'oubliez pas que si vous exécutez ce code sur une machine équipée d'un GPU et que votre modèle est sur un GPU, il est généralement plus efficace de garder à la fois le modèle et les données d'entrée sur le GPU pour profiter des capacités de traitement parallèle.
---
Zhiwei : Pourrais-tu expliquer les codes ci-dessous ?
```python
def generate(
self,
prompt_tokens: List[List[int]],
max_gen_len: int,
temperature: float = 0.6,
top_p: float = 0.9,
logprobs: bool = False,
echo: bool = False,
) -> Tuple[List[List[int]], Optional[List[List[float]]]]:
params = self.model.params
bsz = len(prompt_tokens)
assert bsz <= params.max_batch_size, (bsz, params.max_batch_size)
```
```python
min_prompt_len = min(len(t) for t in prompt_tokens)
max_prompt_len = max(len(t) for t in prompt_tokens)
assert max_prompt_len <= params.max_seq_len
total_len = min(params.max_seq_len, max_gen_len + max_prompt_len)
```
```python
pad_id = self.tokenizer.pad_id
tokens = torch.full((bsz, total_len), pad_id, dtype=torch.long, device="cuda")
for k, t in enumerate(prompt_tokens):
tokens[k, : len(t)] = torch.tensor(t, dtype=torch.long, device="cuda")
if logprobs:
token_logprobs = torch.zeros_like(tokens, dtype=torch.float)
```
```python
prev_pos = 0
eos_reached = torch.tensor([False] * bsz, device="cuda")
input_text_mask = tokens != pad_id
for cur_pos in range(min_prompt_len, total_len):
logits = self.model.forward(tokens[:, prev_pos:cur_pos], prev_pos)
if logprobs:
token_logprobs[:, prev_pos + 1 : cur_pos + 1] = -F.cross_entropy(
input=logits.transpose(1, 2),
target=tokens[:, prev_pos + 1 : cur_pos + 1],
reduction="none",
ignore_index=pad_id,
)
if temperature > 0:
probs = torch.softmax(logits[:, -1] / temperature, dim=-1)
next_token = sample_top_p(probs, top_p)
else:
next_token = torch.argmax(logits[:, -1], dim=-1)
```
```python
next_token = next_token.reshape(-1)
# ne remplacer le token que si le prompt a déjà été généré
next_token = torch.where(
input_text_mask[:, cur_pos], tokens[:, cur_pos], next_token
)
tokens[:, cur_pos] = next_token
eos_reached |= (~input_text_mask[:, cur_pos]) & (
next_token == self.tokenizer.eos_id
)
prev_pos = cur_pos
if all(eos_reached):
break
```
```python
if logprobs:
token_logprobs = token_logprobs.tolist()
out_tokens, out_logprobs = [], []
for i, toks in enumerate(tokens.tolist()):
# couper à la longueur maximale de génération
start = 0 if echo else len(prompt_tokens[i])
toks = toks[start : len(prompt_tokens[i]) + max_gen_len]
probs = None
if logprobs:
probs = token_logprobs[i][start : len(prompt_tokens[i]) + max_gen_len]
# couper au token eos si présent
if self.tokenizer.eos_id in toks:
eos_idx = toks.index(self.tokenizer.eos_id)
toks = toks[:eos_idx]
probs = probs[:eos_idx] if logprobs else None
out_tokens.append(toks)
out_logprobs.append(probs)
return (out_tokens, out_logprobs if logprobs else None)
```
ChatGPT : Bien sûr ! Le code fourni est une méthode appelée `generate` qui prend un prompt (texte d'entrée) et génère du texte en utilisant un modèle de langage. Cette méthode est conçue pour fonctionner avec un modèle et un tokenizer spécifiques, et effectue la génération de texte en utilisant soit un échantillonnage glouton (greedy sampling), soit un échantillonnage top-p. Voici une explication détaillée du fonctionnement de cette méthode :
1. **Paramètres de la méthode :**
- `prompt_tokens` : Une liste de prompts tokenisés, où chaque prompt est représenté par une liste d'entiers (identifiants de tokens).
- `max_gen_len` : La longueur maximale de la sortie générée (en tokens).
- `temperature` : Un paramètre contrôlant le caractère aléatoire de la génération. Des valeurs plus élevées (par exemple, 1.0) rendent la sortie plus aléatoire, tandis que des valeurs plus basses (par exemple, 0.6) la rendent plus déterministe.
- `top_p` : Un paramètre contrôlant la diversité du texte généré. Des valeurs plus élevées (par exemple, 0.9) permettent un échantillonnage plus diversifié.
- `logprobs` : Si `True`, la méthode retourne également les log-probabilités des tokens générés.
- `echo` : Si `True`, la sortie générée inclura le prompt lui-même.
2. **Initialisation :**
La méthode initialise des variables telles que `params`, `bsz` (taille du lot), `min_prompt_len`, et `max_prompt_len`. Elle calcule également `total_len`, qui représente la longueur totale de la sortie générée, incluant l'invite.
3. **Génération de Tokens :**
La méthode génère des tokens pour le texte de sortie. Elle utilise une boucle pour itérer sur les positions dans la séquence générée, en commençant à la fin de l'invite et en avançant.
- Les logits pour chaque position sont obtenus en passant la séquence partielle à la fonction de propagation avant du modèle.
- Si la `température` est supérieure à 0, les logits sont transformés en probabilités en utilisant la fonction softmax avec la valeur de température donnée. Si la `température` est égale à 0, le token avec le logit le plus élevé est sélectionné en utilisant `torch.argmax`.
- Le token suivant est déterminé en fonction des probabilités générées ou de l'argmax, et il est placé dans la position correspondante du tenseur `tokens`.
- Les tokens EOS (fin de séquence) sont détectés, et si toutes les séquences ont atteint un token EOS, le processus de génération est arrêté.
- Les tokens générés sont conservés dans le tenseur `tokens`.
4. **Traitement de la sortie générée :**
- Les tokens générés sont traités pour ajuster la sortie à la longueur maximale souhaitée (`max_gen_len`).
- Si `echo` est `True`, l'invite est incluse dans la sortie générée.
- Si le token `eos` est rencontré, le texte généré est coupé à ce point.
5. **Retour :**
La méthode retourne un tuple contenant les tokens générés et, si `logprobs` est `True`, les log-probabilités des tokens générés.
Cette méthode génère du texte en prédisant itérativement des tokens en fonction du contexte fourni par l'invite (prompt) et des tokens précédemment générés. Elle utilise les paramètres de génération spécifiés pour contrôler le caractère aléatoire et la diversité du texte généré. La méthode est conçue pour être utilisée avec une architecture de modèle et un tokenizer spécifiques, car elle s'appuie sur leurs propriétés et méthodes pour la génération de texte.
---