Pytorch: masalah pengoptimal load_state_dict()?

Dibuat pada 22 Sep 2017  ·  23Komentar  ·  Sumber: pytorch/pytorch

Hai, saya menemukan bug ini:

    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)

Kerangka kode seperti:

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 <-

Tampaknya param_groups yang dimuat adalah torch.cuda.FloatTensor , dan saya sudah mencoba solusi untuk
pindahkan optmizer.param_groups ke cpu , tetapi masih memiliki bug yang sama.

awaiting response (this tag is deprecated) needs reproduction

Komentar yang paling membantu

@apaszke Ah,

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()

Semua 23 komentar

Bisakah Anda memberikan skrip lengkap untuk mereproduksi masalah?

mungkin Anda bisa mencoba seperti ini,
pengoptimal.langkah()
exp_avg.mul_(beta1).add_(1 - beta1, grad.cpu())

Maaf, saya melewatkan email balasan.

Saya khawatir saya tidak dapat menyediakan reproduksi sekarang. Ini adalah pekerjaan yang saya lakukan untuk proyek OpenNMT-py : https://github.com/OpenNMT/OpenNMT-py , mencoba menggunakan lr_scheduler untuk melakukan pembaruan lr. Dan saya mengalami masalah ini saat menguji kasus resume a suspended training . Jadi saya memperhitungkan kerangka kode tentang masalah ini di atas.

Saya sudah mencoba beberapa metode, termasuk trik seperti yang disarankan @hefeicyp , tetapi tetap saja terjadi.

Menurut analisis saya, itu karena pelatihan sebelumnya dilakukan pada gpu, jadi ketika menyimpan optimizer.state_dict , status yang disimpan (tensor) adalah versi cuda . Selama melanjutkan, ketika kita memuat pengoptimal yang disimpan, load_state_dict() memuat versi cuda ini ke cpu(model( nn.Module ) dapat dipindahkan ke gpu dengan mudah, tetapi torch.optimizer sepertinya kurang memiliki kemampuan ini?), jadi masalah ini muncul.

Coba pindahkan status pengoptimal ke memori GPU secara manual setelah memuatnya dari pos pemeriksaan.

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()

Saya setuju bahwa memiliki metode optimizer.cuda() untuk operasi ini akan menyenangkan.

@dogancan , terima kasih. Pekerjaan saya ditangguhkan karena masalah lain, ketika dilanjutkan, saya akan mencoba metode Anda.

Saya khawatir solusi @dogancan tidak akan berhasil. Ini akan membuat kesalahan hilang, tetapi pengoptimal Anda tidak akan lagi melatih model. Anda harus membuat ulang pengoptimal setelah mentransmisikan modul ke jenis atau perangkat yang berbeda, dan Anda dapat menggunakan load_state_dict untuk memulihkan status dari salinan sebelumnya. Ini saat ini tidak berfungsi, tetapi kita harus memperbaikinya (dengan menyalin dari data dari dict negara, alih-alih menggunakan tensor secara langsung - ini memungkinkan pembaruan lintas perangkat atau lintas jenis).

@apaszke , ya, metode Anda adalah yang saya gunakan saat ini, berhasil. Tapi saya akan menunggu upstream untuk memperbaiki masalah ini. Terima kasih atas karya-karya hebat Anda!

@apaszke Ah,

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()

benar. Itu harus berhasil

Kecuali bahwa Anda harus menggunakan torch.is_tensor(v) alih-alih isinstance(v, torch.Tensor)

Saya memiliki masalah serupa. Ketika saya menyimpan status pengoptimal dari GPU selain GPU 0 dan kemudian memuat status, status itu masih memuat semuanya ke GPU 0. Menentukan map_location di torch.load() juga tidak berhasil. Solusi @dogancan menyelesaikan ini.

Hai teman-teman, saya memiliki masalah yang sangat mirip dengan yang ada di utas ini, ini kode saya:

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()

Dan setelah saya melanjutkan, saya mendapatkan KeyErrors di pengoptimal saya:

---> 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)]

Apakah kalian tahu cara memperbaiki masalah ini? BTW, saya menggunakan 8 GPU , saya kira apakah masalah ini karena itu?

@CodArs-van apakah Anda dapat menyelesaikan masalah Anda dengan banyak GPU?

@rafaelvalle Terima kasih sudah bertanya. Ya, saya bisa, ternyata masalahnya karena saya menggunakan versi awal PyTorch, setelah saya memperbarui versi, itu berfungsi seperti pesona!

Sekedar komentar, masalah ini disebabkan oleh

    def load_state_dict(self, state_dict):
        ...
        # deepcopy, to be consistent with module API
        state_dict = deepcopy(state_dict)
       ...  

deepcopy membuat semua state tensor dipindahkan ke GPU0
jadi dengan memindahkan status pengoptimal ke GPU tertentu akan memperbaiki masalah ini.

Hai @lzcn , bagaimana Anda mengetahui lokasi GPU spesifik dari berbagai tensor sebelumnya?

Apakah fitur di mana semua panggilan torch.save() selalu menggunakan versi CPU yang dibuat secara otomatis layak dilakukan?
Dan kemudian saat melanjutkan, torch.load() akan menggunakan perangkat "saat ini" yang digunakan (atau strategi apa pun yang lebih baik).
Saat ini sepertinya kami membutuhkan banyak kode boilerplater untuk memastikan penyimpanan dan pemuatan konsisten di seluruh perangkat untuk model/pengoptimal/penjadwal/dll.

Saya telah menemui masalah serupa, saya membuat ulang pengoptimal Adam tanpa optimizer.cuda() setelah memuat ulang model, model.cuda() dan DataParallel(model) sesuai dengan solusi @dogancan .

terima kasih, itu berhasil!

@apaszke Ah,

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()

@paszke
Hai, seperti yang Anda katakan: setiap kali memindahkan model ke perangkat lain, kita harus membangun pengoptimal, tetapi, jika kita memindahkan model ke perangkat lain dan mundur, haruskah kita membangun pengoptimal lagi?
berikut adalah contoh kode:

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

apakah pengoptimal berjalan seperti yang diharapkan?

juga, jika melakukan model.to(model.device) , haruskah kita membangun kembali pengoptimal?

@apaszke Ah,

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 Apakah ada masalah jika Anda mengubah urutan menjadi seperti ini?

```python
model = model()
model.to('cuda')
pengoptimal = optim.Adam(model.parameters())
optimizer.load_state_dict(checkpoint['optimizer'])
untuk status di optimizer.state.values():
untuk k, v di state.items():
if isinstance(v, torch.Tensor):
status[k] = v.cuda()
model.load_state_dict(pos pemeriksaan['model'])

Berarti memindahkan model ke 'cuda' tetapi hanya memuat dict statusnya dari pos pemeriksaan setelah memuat dict status pengoptimal terlebih dahulu?

Masalah tersebut dapat disimpulkan bahwa keadaan pengoptimal akan dimuat ke perangkat sama seperti model. Anda harus memuat model ke GPU terlebih dahulu, lalu memuat status pengoptimal. Sehingga model dan status pengoptimal dimuat di GPU.

Alih-alih memindahkan pengoptimal ke cuda setelah memuatnya di cpu, Anda dapat memuat pos pemeriksaan langsung di 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
Apakah halaman ini membantu?
0 / 5 - 0 peringkat