IakovlevIA / structural-complexity

8 stars 5 forks source link

Speed up the code by simplifying the expression #3

Open hannnwang opened 3 years ago

hannnwang commented 3 years ago

You may already have noticed it, and I'm just commenting that the code could be sped up substantially if we simplify the expression by applying an inequality and telescoping. You should also check yourself whether or not what I'm saying is correct.

Equation [4] in the paper can be simplified with the following steps: 1) From an inequality, we can get rid of the absolute sign: We denote the image at step k to be A, and the image at step k+1 to be B. Following your explanations in the paper, B would be re-scaled and thus have the same dimension as A. Suppose they are also square images (generalizations to nonsquare images should be straightforward) and denote the image width or height to be L. Then, L^2O_{k+1,k} is the sum of pixelwise product of A and B, and L^2O{k,k} is the pixelwise product of A and A itself etc. One pixel of A or B is denoted as Aij and Bij respectively. Then, the term under the summation on the RHS of equation [4] can be expressed as |\sum{i,j} AijBij-1/2(AijAij+BijBij)|/L^2. At each (i,j), AijBij-1/2(AijAij+BijBij) is less than or equal to 0. This can be seen from the inequality: ab\leq 1/2(a^2+b^2) if a and b are real. (To prove it, simply subtract the RHS with LHS, and you get 1/2(a-b)^2, which is larger than or equal to 0.) Therefore, the term inside the absolute value sign should be always non-positive. We can then delete the absolute value sign, and add a minus sign in front of every term on the RHS of equation [4].

2) Apply the equation [3] you derived, and replace O{k+1,k} with O{k+1,k+1}. Combined with step 1), the term under the summation is turned into:
0.5*(O{k,k}-O{k+1,k+1})

3) Now, this series can be telescoped: if one sums the above expression from k=0 to k=N-1, then a lot of terms will cancel out. After summing over k, we can now convert equation [4] into: C=0.5*(O{0,0}-O{N,N}).

This expression is much quicker to compute than the original expression.

I have verified that this gives me the same results as the original expression when I apply it onto examples shown in Fig.1 and Fig.2 of the paper. (My results are different from what's listed in the paper, though, as explained in Issue #2.)

Caveats: Step 1) holds only if the pixels values are real numbers. Step 1) and 2) holds only if the definition of overlap and the coarse-graining process are done in the same way as in paper (illustrated by Fig.1 of the paper).

IakovlevIA commented 3 years ago

You may already have noticed it, and I'm just commenting that the code could be sped up substantially if we simplify the expression by applying an inequality and telescoping. You should also check yourself whether or not what I'm saying is correct. C=0.5*(O{0,0}-O{N,N}). This expression is much quicker to compute than the original expression.

I fully agree with you that in this particular case presented in the paper you can simplify the equation for C this way. However, to distinguish between pictures with the same total complexity you can analyze the partial contributions C_k from different scales (see Fig.8 and the related discussion). In case of training neural networks, I would use C_k along with/instead of C to keep as much information about the sample as possible.

hannnwang commented 3 years ago

OK good to know!

This brings me to my next question -- why is your C defined like this anyway? As you pointed out too, it would smudge out the individual contributions from Ck. In fact, if one coarse grains the figure all the way down to 1 block, then C would essentially just be the L2 norm of the figure minus the square of the average of the figure.

It appears to me that defining C as sum_k {Ck}^2, for example, could at least let C be impacted by contributions from all the scales. Why you didn't do something like that?

cainiao123s commented 4 months ago

OK good to know!

This brings me to my next question -- why is your C defined like this anyway? As you pointed out too, it would smudge out the individual contributions from Ck. In fact, if one coarse grains the figure all the way down to 1 block, then C would essentially just be the L2 norm of the figure minus the square of the average of the figure.

It appears to me that defining C as sum_k {Ck}^2, for example, could at least let C be impacted by contributions from all the scales. Why you didn't do something like that?

Hello, may I ask you some questions? I am currently researching this as well.

hannnwang commented 4 months ago

@cainiao123s Yes, I'd be happy to have a look.

OK good to know! This brings me to my next question -- why is your C defined like this anyway? As you pointed out too, it would smudge out the individual contributions from Ck. In fact, if one coarse grains the figure all the way down to 1 block, then C would essentially just be the L2 norm of the figure minus the square of the average of the figure. It appears to me that defining C as sum_k {Ck}^2, for example, could at least let C be impacted by contributions from all the scales. Why you didn't do something like that?

Hello, may I ask you some questions? I am currently researching this as well.

cainiao123s commented 4 months ago

1.Hello, when calculating the complexity of that zebra image, I obtained a result of 0.12. However, this does not match the answers given by the author and you. Here are the data I obtained: 开始进行粗粒度化 开始第1次粗粒度化 开始第2次粗粒度化 开始第3次粗粒度化 开始第4次粗粒度化 开始第5次粗粒度化 开始第6次粗粒度化 开始第7次粗粒度化 开始第8次粗粒度化 开始第9次粗粒度化 开始第10次粗粒度化 粗粒度化计算完成 尺寸——像素数目: {'L_0': 4096, 'L_1': 2048, 'L_2': 1024, 'L_3': 512, 'L_4': 256, 'L_5': 128, 'L_6': 64, 'L_7': 32, 'L_8': 16, 'L_9': 8, 'L_10': 4}

开始计算o_k,k-1 o_k,k-1计算完成 o_k_add_1_k: {'o_1,0': tensor(0.5607, device='cuda:0', dtype=torch.float64), 'o_2,1': tensor(0.2498, device='cuda:0', dtype=torch.float64), 'o_3,2': tensor(0.2734, device='cuda:0', dtype=torch.float64), 'o_4,3': tensor(0.3460, device='cuda:0', dtype=torch.float64), 'o_5,4': tensor(0.4470, device='cuda:0', dtype=torch.float64), 'o_6,5': tensor(0.5365, device='cuda:0', dtype=torch.float64), 'o_7,6': tensor(0.5616, device='cuda:0', dtype=torch.float64), 'o_8,7': tensor(0.5364, device='cuda:0', dtype=torch.float64), 'o_9,8': tensor(0.4486, device='cuda:0', dtype=torch.float64), 'o_10,9': tensor(0.3459, device='cuda:0', dtype=torch.float64)}

开始计算o_k,k o_k,k计算完成 o_k,k: {'o_0,0': tensor(0.5859, device='cuda:0', dtype=torch.float64), 'o_1,1': tensor(0.5607, device='cuda:0', dtype=torch.float64), 'o_2,2': tensor(0.2498, device='cuda:0', dtype=torch.float64), 'o_3,3': tensor(0.2734, device='cuda:0', dtype=torch.float64), 'o_4,4': tensor(0.3460, device='cuda:0', dtype=torch.float64), 'o_5,5': tensor(0.4470, device='cuda:0', dtype=torch.float64), 'o_6,6': tensor(0.5365, device='cuda:0', dtype=torch.float64), 'o_7,7': tensor(0.5616, device='cuda:0', dtype=torch.float64), 'o_8,8': tensor(0.5364, device='cuda:0', dtype=torch.float64), 'o_9,9': tensor(0.4486, device='cuda:0', dtype=torch.float64), 'o_10,10': tensor(0.3459, device='cuda:0', dtype=torch.float64)}

开始计算复杂度C 复杂度C计算完成 最终复杂度C: tensor(-0.1200, device='cuda:0', dtype=torch.float64)

2.Have you conducted any further experiments and published papers on the method you mentioned regarding the author's erasure of Ck's contributions and proposed corrections?