Bonjour, j'ai rencontré ce bug :
optimizer.step()
exp_avg.mul_(beta1).add_(1 - beta1, grad)
TypeError: add_ received an invalid combination of arguments - got (float, torch.cuda.FloatTensor), but expected one of:
* (float value)
* (torch.FloatTensor other)
* (torch.SparseFloatTensor other)
* (float value, torch.FloatTensor other)
didn't match because some of the arguments have invalid types: (float, torch.cuda.FloatTensor)
* (float value, torch.SparseFloatTensor other)
didn't match because some of the arguments have invalid types: (float, torch.cuda.FloatTensor)
Le squelette de code est comme :
model = Model()
model.load_state_dict(checkpoint['model'])
model.cuda()
optimizer = optim.Adam()
optimizer.load_state_dict(checkpoint['optimizer'])
...
# In train loop
for epoch in range(...):
...
optimizer.step()
-> BUG <-
Il semble que les param_groups
chargés soient torch.cuda.FloatTensor
, et j'ai essayé une solution de contournement pour
déplacez optmizer.param_groups
vers cpu
, mais il a toujours le même bogue.
Pourriez-vous fournir un script complet pour reproduire le problème ?
peut-être que tu peux essayer comme ça,
optimiseur.step()
exp_avg.mul_(beta1).add_(1 - beta1, grad.cpu())
Désolé, j'ai raté l'e-mail de réponse.
Je crains de ne pas être en mesure de fournir un reproducteur maintenant. C'est un travail que je fais pour le projet OpenNMT-py : https://github.com/OpenNMT/OpenNMT-py, en essayant d'utiliser lr_scheduler
pour faire la mise à jour lr. Et j'ai rencontré ce problème lors du test du cas resume a suspended training
. J'ai donc factorisé le squelette de code concernant ce problème ci-dessus.
J'ai essayé plusieurs méthodes, y compris des astuces comme celle suggérée par @hefeicyp , mais cela arrive toujours.
D'après mon analyse, c'est parce que la formation précédente a été effectuée sur GPU, donc lors de l'enregistrement du optimizer.state_dict
, les états (tenseurs) stockés sont de la version cuda
. Lors de la reprise, lorsque nous chargeons l'optimiseur enregistré, load_state_dict()
charge cette version cuda
sur cpu(le modèle( nn.Module
) peut être déplacé facilement vers gpu, mais torch.optimizer
semble manquer de cette capacité ?) , donc ce problème émerge.
Essayez de déplacer manuellement l'état de l'optimiseur vers la mémoire GPU après l'avoir chargé à partir du point de contrôle.
optimizer = optim.Adam()
optimizer.load_state_dict(checkpoint['optimizer'])
for state in optimizer.state.values():
for k, v in state.items():
if isinstance(v, torch.Tensor):
state[k] = v.cuda()
Je suis d'accord qu'avoir une méthode optimizer.cuda()
pour cette opération serait bien.
@dogancan , merci. Mon travail a été suspendu en raison d'autres problèmes, une fois repris, j'essayerai votre méthode.
J'ai peur que la solution de load_state_dict
pour restaurer l'état d'une copie précédente. Cela ne fonctionne pas actuellement, mais nous devrions le corriger (en copiant les données du dict d'état, au lieu d'utiliser les tenseurs directement - cela permet des mises à jour inter-appareils ou inter-types).
@apaszke ,
@apaszke Ah, mon mauvais. J'ai oublié de mettre à jour la ligne où l'optimiseur est recréé. Mais sinon, ce qui suit devrait faire l'affaire, n'est-ce pas ?
model = Model()
model.load_state_dict(checkpoint['model'])
model.cuda()
optimizer = optim.Adam(model.parameters())
optimizer.load_state_dict(checkpoint['optimizer'])
for state in optimizer.state.values():
for k, v in state.items():
if isinstance(v, torch.Tensor):
state[k] = v.cuda()
euh, d'accord. ça devrait marcher
Sauf que vous devriez utiliser torch.is_tensor(v)
au lieu de isinstance(v, torch.Tensor)
J'avais un problème similaire. Lorsque j'enregistre l'état de l'optimiseur à partir d'un GPU autre que le GPU 0, puis que je charge l'état, il charge toujours tout sur le GPU 0. La spécification de map_location
dans torch.load()
n'a pas fonctionné non plus. La solution de @dogancan résout ce problème.
Salut les gars, j'ai un problème très similaire à celui de ce fil, voici mon code:
model = inceptionresnetv2(num_classes=config['tr_classes'])
model = torch.nn.DataParallel(model).cuda()
model.load_state_dict(checkpoint['md_state_dict'])
optimizer = torch.optim.Adam(model.parameters(), lr=config['tr_lr'], weight_decay=config['tr_weightdecay'])
optimizer.load_state_dict(checkpoint['md_optimizer'])
for state in optimizer.state.values():
for k, v in state.items():
if torch.is_tensor(v):
state[k] = v.cuda()
Et puis une fois que je reprends, j'ai des KeyErrors sur mon optimiseur :
---> 40 optimizer.step()
41
42 config['am_batch_time'].update(time.time() - end)
~/.conda/envs/env_pytorch/lib/python3.5/site-packages/torch/optim/adam.py in step(self, closure)
44 continue
45 grad = p.grad.data
---> 46 state = self.state[p]
47
48 # State initialization
KeyError: Parameter containing:
(0 ,0 ,.,.) =
-1.6336e-01 -5.6482e-01 -4.2228e-02
...
[torch.cuda.FloatTensor of size 32x3x3x3 (GPU 0)]
Savez-vous les gars comment résoudre ce problème? BTW, j'ai utilisé 8 GPU , je suppose que ce problème est dû à cela?
@CodArs-van avez-vous pu résoudre votre problème avec plusieurs GPU ?
@rafaelvalle Merci d'avoir demandé. Oui, je suis capable de le faire, il s'avère que le problème est dû au fait que j'ai utilisé une première version de PyTorch, après avoir mis à jour la version, cela fonctionne à merveille !
Juste un commentaire, ce problème est causé par
def load_state_dict(self, state_dict):
...
# deepcopy, to be consistent with module API
state_dict = deepcopy(state_dict)
...
deepcopy
fait que tous les tenseurs d'état sont déplacés dans GPU0 ,
ainsi, en déplaçant l'état d'un optimiseur vers un GPU spécifique, cela résoudra ce problème.
Salut @lzcn , comment connaître à l'avance l'emplacement spécifique du GPU des différents tenseurs ?
Une fonctionnalité où tous les appels torch.save() utilisent toujours une version CPU générée automatiquement serait-elle faisable ?
Et puis, à la reprise, torch.load() utiliserait le périphérique "actuel" utilisé (ou toute meilleure stratégie).
Pour le moment, il semble que nous ayons besoin de beaucoup de code passe-partout pour garantir que la sauvegarde et le chargement sont cohérents sur tous les appareils pour les modèles/optimiseur/planificateur/etc.
J'ai rencontré un problème similaire, j'ai recréé l'optimiseur Adam sans Optimizer.cuda() après avoir rechargé model, model.cuda() et DataParallel(model) selon la solution de @dogancan .
merci, ça marche !
@apaszke Ah, mon mauvais. J'ai oublié de mettre à jour la ligne où l'optimiseur est recréé. Mais sinon, ce qui suit devrait faire l'affaire, n'est-ce pas ?
model = Model() model.load_state_dict(checkpoint['model']) model.cuda() optimizer = optim.Adam(model.parameters()) optimizer.load_state_dict(checkpoint['optimizer']) for state in optimizer.state.values(): for k, v in state.items(): if isinstance(v, torch.Tensor): state[k] = v.cuda()
@apaszke
Bonjour, comme vous le dites : à chaque déplacement du modèle vers un autre appareil, nous devons construire l'optimiseur, mais, si nous déplaçons le modèle vers un autre appareil et reculons, devrions-nous reconstruire l'optimiseur ?
voici un exemple de code :
model = Model()
model.cuda()
optimizer = optim.Adam(model.parameters())
for d, gt in trn_dataloader:
# train
...
optimizer.step()
model.cpu() # move to cpu
# eval or do other things
...
model.cuda() # but finnally, move back
l'optimiseur s'exécute-t-il comme prévu ?
aussi, si nous faisons model.to(model.device)
, devrions-nous reconstruire l'optimiseur ?
@apaszke Ah, mon mauvais. J'ai oublié de mettre à jour la ligne où l'optimiseur est recréé. Mais sinon, ce qui suit devrait faire l'affaire, n'est-ce pas ?
model = Model() model.load_state_dict(checkpoint['model']) model.cuda() optimizer = optim.Adam(model.parameters()) optimizer.load_state_dict(checkpoint['optimizer']) for state in optimizer.state.values(): for k, v in state.items(): if isinstance(v, torch.Tensor): state[k] = v.cuda()
@apaszke Y a-t-il un problème si vous passez la commande à quelque chose comme ça ?
```python
modèle = Modèle()
model.to('cuda')
optimiseur = optim.Adam(model.parameters())
optimiseur.load_state_dict(checkpoint['optimizer'])
pour l'état dans Optimizer.state.values() :
pour k, v dans state.items() :
if isinstance(v, torch.Tensor):
état[k] = v.cuda()
model.load_state_dict(checkpoint['model'])
Cela signifie déplacer le modèle vers « cuda » mais ne charger son dict d'état qu'à partir du point de contrôle après avoir d'abord chargé le dict d'état de l'optimiseur ?
Le problème peut être conclu que l'état de l'optimiseur sera chargé sur l'appareil de la même manière que le modèle. Vous devez d'abord charger le modèle sur le GPU, puis charger l'état de l'optimiseur. Pour que le modèle et l'état de l'optimiseur soient chargés dans le GPU.
Au lieu de déplacer l'optimiseur vers cuda après l'avoir chargé dans le processeur, vous pouvez charger le point de contrôle directement dans cuda :
model.to(device)
ckpt = torch.load(<model_path>, map_location=device)
model.load_state_dict(ckpt['state_dict'])
optimizer.load_state_dict(ckpt['optimizer'])
scheduler.load_state_dict(ckpt['scheduler'])
del ckpt
Commentaire le plus utile
@apaszke Ah, mon mauvais. J'ai oublié de mettre à jour la ligne où l'optimiseur est recréé. Mais sinon, ce qui suit devrait faire l'affaire, n'est-ce pas ?