yuanzhi-zhu / DiffPIR

"Denoising Diffusion Models for Plug-and-Play Image Restoration", Yuanzhi Zhu, Kai Zhang, Jingyun Liang, Jiezhang Cao, Bihan Wen, Radu Timofte, Luc Van Gool.
https://yuanzhi-zhu.github.io/DiffPIR/
MIT License
337 stars 25 forks source link

Comparisons with DDRM - Operators #5

Closed SavvasMel closed 12 months ago

SavvasMel commented 1 year ago

Hello,

That is a very interesting work, and a very tidy code, well done!

I would like to ask what changes needed to be made in the DDRM code so that DiffPIR's operators and DDRM's operators can match properly. What I find is that if I create a noisy image with the DiffPIR code (let's say by creating a Gaussian blur of size 9x9 and st. deviation 3) and a noisy image with the DDRM code (again the same operator but with their zero-padded strategy code), the DDRM's noisy image is a more challenging one.

I am trying to compare the two algorithms in the most fair way, so I am not sure if the operators are the same. Could you help me on that please? How did you make the comparisons in the paper towards this?

yuanzhi-zhu commented 1 year ago

Hi @SavvasMel , Thank you for your interest!

The bluring operator in our work is inherent from DPS.

Unfortunately, we tuned the hyper-parameters of the degradation operator by hand to match the performance of the operators in different methods :( Additionally, I am unaware of the theoretical connection between the two settings of operators.

Let me know if this answers your question.

SavvasMel commented 1 year ago

I am sorry for the late response. Yes, this answers my question, thank you very much for your prompt response! Just another quick question:

I see that your code is adapted also to run DPS but there is one step that produces an error for me and specifically this part

if generate_mode == 'DPS_y0': norm_grad, norm = utils_model.grad_and_value(operator=Tx,x=x, x_hat=x0, measurement=y)

norm_grad, norm = utils_model.grad_and_value(operator=Tx,x=xt, x_hat=x0, measurement=y)

      x = xt - norm_grad * 1. #norm / (2*rhos[t_i]) 
      x = x.detach_()

This part requires x0 to have a gradient requirement because the norm_grad is calculated w.r.t to x0 and not x (which has a gradient requirement). I am not sure what would be the best to change here. I would much appreciate if you could help towards this.

yuanzhi-zhu commented 1 year ago

@SavvasMel thanks for your feedback,

According to the paper of DPS, the gradient is taken with respect to $x_t$ indeed.

And the error in the code is caused by setting the model's parameter with v.requires_grad = False.

A quick fix is made and the repo has been updated accordingly.

Actually, all you have to do is to replace: https://github.com/yuanzhi-zhu/DiffPIR/blob/7d6aa59971e0c6035f3475bd1ddc0f0da7927f5f/main_ddpir_sisr.py#L133-L134 with:

    if generate_mode != 'DPS_y0':
        # for DPS_yt, we can avoid backward through the model
        for k, v in model.named_parameters():
            v.requires_grad = False

please donot forget to set iter_num = 1000 and skip_type = 'uniform' when use DPS_y0