当前位置:   article > 正文

Certain step counts for DDIM cause out of bounds error_add one to get the final alpha values right

add one to get the final alpha values right

报错记录: 

  1. Traceback (most recent call last):
  2. File "/home/yiming/Projects/EvDiffusion/scripts/frame_voxel/test_sr_ver1.py", line 86, in <module>
  3. samples_ddim, _ = sampler.sample(S=opt.steps,
  4. File "/home/yiming/anaconda3/envs/ldm/lib/python3.8/site-packages/torch/autograd/grad_mode.py", line 27, in decorate_context
  5. return func(*args, **kwargs)
  6. File "/home/yiming/Projects/EvDiffusion/ldm/models/diffusion/ddim.py", line 98, in sample
  7. self.make_schedule(ddim_num_steps=S, ddim_eta=eta, verbose=verbose)
  8. File "/home/yiming/Projects/EvDiffusion/ldm/models/diffusion/ddim.py", line 44, in make_schedule
  9. ddim_sigmas, ddim_alphas, ddim_alphas_prev = make_ddim_sampling_parameters(alphacums=alphas_cumprod.cpu(),
  10. File "/home/yiming/Projects/EvDiffusion/ldm/modules/diffusionmodules/util.py", line 65, in make_ddim_sampling_parameters
  11. alphas = alphacums[ddim_timesteps]
  12. IndexError: index 1000 is out of bounds for dimension 0 with size 1000

查到的解决办法: 

Certain step counts for DDIM cause out of bounds error by MartinCairnsSQL · Pull Request #3917 · AUTOMATIC1111/stable-diffusion-webui · GitHub

When DDIM is set to any of the following step counts 3, 9, 27, 36, 37, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110,111 the last value in the ddim_timesteps array is 1000 which is out of bounds for the 1000 entries in the alphacums array.

The formula 999 / (1000 // num_steps) + 1 will give the next valid DDIM step if it's an integer value.

自行问题分析:

检查源码发现这里的计算逻辑是这样的:

首先计算ddim timesteps的间隔:(1000 // num_ddim_timesteps)

然后在(0,1000, (1000 // num_ddim_timesteps))之间取序列,最后把序列中的每个值+1得到ddim timesteps

  1. def make_ddim_timesteps(ddim_discr_method, num_ddim_timesteps, num_ddpm_timesteps, verbose=True):
  2. if ddim_discr_method == 'uniform':
  3. c = num_ddpm_timesteps // num_ddim_timesteps
  4. ddim_timesteps = np.asarray(list(range(0, num_ddpm_timesteps, c)))
  5. elif ddim_discr_method == 'quad':
  6. ddim_timesteps = ((np.linspace(0, np.sqrt(num_ddpm_timesteps * .8), num_ddim_timesteps)) ** 2).astype(int)
  7. else:
  8. raise NotImplementedError(f'There is no ddim discretization method called "{ddim_discr_method}"')
  9. # assert ddim_timesteps.shape[0] == num_ddim_timesteps
  10. # add one to get the final alpha values right (the ones from first scale to data during sampling)
  11. steps_out = ddim_timesteps + 1
  12. if verbose:
  13. print(f'Selected timesteps for ddim sampler: {steps_out}')
  14. return steps_out

根据刚刚计算出的ddim timesteps得到alphas

alphacums是一个(1000,)的向量,然后刚刚计算得到的ddim_timesteps索引得到alphas

  1. def make_ddim_sampling_parameters(alphacums, ddim_timesteps, eta, verbose=True):
  2. # select alphas for computing the variance schedule
  3. alphas = alphacums[ddim_timesteps]
  4. alphas_prev = np.asarray([alphacums[0]] + alphacums[ddim_timesteps[:-1]].tolist())
  5. # according the the formula provided in https://arxiv.org/abs/2010.02502
  6. sigmas = eta * np.sqrt((1 - alphas_prev) / (1 - alphas) * (1 - alphas / alphas_prev))
  7. if verbose:
  8. print(f'Selected alphas for ddim sampler: a_t: {alphas}; a_(t-1): {alphas_prev}')
  9. print(f'For the chosen value of eta, which is {eta}, '
  10. f'this results in the following sigma_t schedule for ddim sampler {sigmas}')
  11. return sigmas, alphas, alphas_prev

所以如果num_ddim_timesteps设置为3,最后ddim timesteps[-1]是1000,所以取alphas会超出维度

解决方案

PoliticalCostlyAdministrators - Replit

根据给出的num_ddim_timesteps计算最接近的可行num_ddim_timesteps的方法:

  1. def next_valid_ddim_step(ddim_num_steps):
  2. valid_step = 999 / (1000 // ddim_num_steps)
  3. if valid_step == floor(valid_step):
  4. return int(valid_step) + 1
  5. return ddim_num_steps

或者直接把 make_ddim_timesteps中的

c = num_ddpm_timesteps // num_ddim_timesteps

np.asarray(list(range(0, num_ddpm_timesteps, c)))

换成

c = num_ddpm_timesteps // num_ddim_timesteps

(np.arange(0, num_ddim_timesteps) * c).astype(int)

也就是:

  1. def make_ddim_timesteps_hym(ddim_discr_method, num_ddim_timesteps, num_ddpm_timesteps, verbose=True):
  2. if ddim_discr_method == 'uniform':
  3. c = num_ddpm_timesteps // num_ddim_timesteps
  4. # ddim_timesteps = np.asarray(list(range(0, num_ddpm_timesteps, c)))
  5. ddim_timesteps = (np.arange(0, num_ddim_timesteps) * c).astype(int)
  6. elif ddim_discr_method == 'quad':
  7. ddim_timesteps = ((np.linspace(0, np.sqrt(num_ddpm_timesteps * .8), num_ddim_timesteps)) ** 2).astype(int)
  8. else:
  9. raise NotImplementedError(f'There is no ddim discretization method called "{ddim_discr_method}"')
  10. # assert ddim_timesteps.shape[0] == num_ddim_timesteps
  11. # add one to get the final alpha values right (the ones from first scale to data during sampling)
  12. steps_out = ddim_timesteps + 1
  13. if verbose:
  14. print(f'Selected timesteps for ddim sampler: {steps_out}')
  15. return steps_out

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/IT小白/article/detail/524286
推荐阅读
相关标签
  

闽ICP备14008679号