luping-liu/PNDM

Is the implementation for FON really 4-th order?

qsh-zh opened this issue · 5 comments

Thanks for your inspiring work.

I found the implementation of FON is confusing, which may not what claimed in the paper.

Paper claims
image

However,

def gen_fon(img, t, t_next, model, alphas_cump, ets):
    t_list = [t, (t + t_next) / 2.0, t_next]
    if len(ets) > 2:
        noise = model(img, t)
        img_next = transfer(img, t, t-1, noise, alphas_cump)
        delta = img_next - img
        ets.append(delta)
    else:
        noise = model(img, t_list[0])
        img_ = transfer(img, t, t - 1, noise, alphas_cump)
        delta_1 = img_ - img
        ets.append(delta_1)

        img_2 = img + delta_1 * (t - t_next).view(-1, 1, 1, 1) / 2.0
        noise = model(img_2, t_list[1])
        img_ = transfer(img, t, t - 1, noise, alphas_cump)
        delta_2 = img_ - img

        img_3 = img + delta_2 * (t - t_next).view(-1, 1, 1, 1) / 2.0
        noise = model(img_3, t_list[1])
        img_ = transfer(img, t, t - 1, noise, alphas_cump)
        delta_3 = img_ - img

        img_4 = img + delta_3 * (t - t_next).view(-1, 1, 1, 1)
        noise = model(img_4, t_list[2])
        img_ = transfer(img, t, t - 1, noise, alphas_cump)
        delta_4 = img_ - img
        delta = (1 / 6.0) * (delta_1 + 2*delta_2 + 2*delta_3 + delta_4)

    img_next = img + delta * (t - t_next).view(-1, 1, 1, 1)
    return img_next

After len(ets) > 2, delta seems only use first order info?

Yes, you are right. I have fixed this bug. Replace this first-order method with the linear multistep method.

PNDM/runner/method.py

Lines 55 to 60 in f285e8e

if len(ets) > 2:
noise = model(img, t)
img_next = transfer(img, t, t-1, noise, alphas_cump)
delta1 = img_next - img
ets.append(delta1)
delta = (1 / 24) * (55 * ets[-1] - 59 * ets[-2] + 37 * ets[-3] - 9 * ets[-4])

This bug was introduced when refactoring the code, so it does not affect our experimental results.

Thanks for your quick response!!!

I want to point out another related issue, still for this function

    img_next = img + delta * (t - t_next).view(-1, 1, 1, 1)

But actually, the used delta is already relative change (img_next - img) instead of gradient or speed. Does it need to multiply delta t again considering you are using unifomal delta_t?

Well, please notice the difference between

PNDM/runner/method.py

Lines 57 to 58 in f285e8e

img_next = transfer(img, t, t-1, noise, alphas_cump)
delta1 = img_next - img

and
img_next = transfer(img, t, t_next, noise, alphas_cump)

In fact, we use the delta from t to t-1 to approximate the gradient in FON.

I see, thanks for your response!!!