Closed RafaelMostert closed 5 years ago
Thank you very much for the awesome testing. Let me simplify your first example to be sure, that I understand it correctly. If we have a neuron with only 1.0 entries and a image with only 0.0 entries, then the euclidean distance should be 0.0 and not 4.0 as you expected.
In your second example with random numbers, I would suppose, that the high number results from the the special behavior using unit8 to speed-up the euclidean norm calculation, where I have to normalize the float into uint8. I would expect, that the numbers are correct, but not scaled back. I will add the back scaling from uint into float in the next days. You can simply check the scaled numbers by using --euclidean-distance-type float
.
Thanks for looking into it!
And good to know about the --euclidean-distance-type float
flag.
But I already differ from your result in the first basic example. What goes wrong in the following argument?
Using the PINK paper:
Given neuron with weights A and the image vector B.
The similarity measure Δ(A,B)=min{d(A,φ(B))|φ∈Φ} with Φ ={φ1,...,φN} a set of image rotations and d(A,B) the Euclidean distance between A and B.
Since A is all 1.0s and B all 0s, the rotations have no effect and Δ(A,B)=d(A,B).
Now for every weight within the euclidean distance dimension, d(1,0)=(1-0)^2=1 is added to the summed euclidean distance. In my example above, the image was 3x3 so the Euclidean distance dimension = 2x2
so I expect the summed euclidean distance to each neuron to be 4.
I added --euclidean-distance-type
to the usage print, but it will appears only in version 2.3.
Of course, you are right for the first example. The result must be 4. I will check it.
I just tested the --euclidean-distance-type float
flag and it works :)
The first example now gives 4,4,4,4 and the second example (with np.random.seed=42
) gives a bunch of floats between 0 and 4: 0.43070784 0.09937809 0.10547281 0.39434844
Disabling rotations with the -n 1
flag in the second example should lead to higher values and indeed the results are higher:
1.05128109 0.96608406 0.91012907 0.58507311
Oops, I forgot the square root over the sum for the Euclidean distance.
d(1,0)=sqrt((1-0)^2)=1
In my first example the effective area is A = [1,1,1,1] and B=[0,0,0,0]
so for d(A,B)=sqrt((1-0)^2+(1-0)^2+(1-0)^2+(1-0)^2)=2 not 4. So Pink seems wrong in the first example, even with --euclidean-distance-type float
.
And testing the example in which the neurons are all zeros and the image all 0.5, the result should be d(A,B)=sqrt((0.5-0)^2+(0.5-0)^2+(0.5-0)^2+(0.5-0)^2)=1. But Pink reports 0.74999994 0.74999994 0.74999994 0.74999994
So there might be something wrong still.
More weird things:
I did some more testing.
It seems as if problems from my last comment get introduced only with the -n 1
flag for images of all sizes, big or small. (For -n 1, the euclidean distance dimension and the neuron dimension are automatically set to the image dimension.)
With -n 4
or -n 360
d(A,B) is equal to d(B,A).
The --flip-off
flag does not affect the results.
Catching -n <4
would be good.
If -n >= 4
and --euclidean-distance-type float
the reported results are the squares of the euclidean dimension.
In those cases, the only bug to fix there is inserting a square root in PINK.
In the meanwhile I have fixed the scaling issue for euclidean-distance-type unit8/16.
I have also added some checks for d(A,B) == d(B,A). Please find them here:
I see only d(A,B) != d(B,A) if the euclidean-distance-dim is too large (should be not the cause with default settings) and -n > 4
is used.
The sqrt for the euclidean distance was consciously omitted, as it has no direct effect. Therefore, d(0,1) = 4 is correct (without sqrt).
For -n 1
(no rotations) the setting euclidean_distance_dim = neuron_dim = image_dim
makes sence, because there are no rotational effects as discussed in #15.
You are right, the behaviour of -n < 4
is according to pull request 15.
Might be nice to indicate that the sqrt is missing somewhere in the documentation at some point.
Great! All mapping issues are fixed or sorted out then, thanks a lot :)
You are welcome.
The sqrt was omitted for performance reasons, which is in the training phase no problem, as the euclidean distance is not used directly. I think it is better to add the sqrt in the mapping phase to be consistent with the paper. Should be the better way to prevent future confusion :)
It is harder for me to get the SOMs to converge during training. Especially since my diagnostics don't work as the mapping procedure leads to unexpected high numbers. Did something change in the calculation of the summed euclidean distance between image and neuron? (apart from pull request 15) To see where I go wrong in the mapping process, I made a small test case below:
This results in the following output:
Executing the last line gives the following output, which seem fine (dimensions seem right):
Now loading the som using
load_som_mapping(map_path, verbose=True)
results in the following (wrong) result:So the euclidean distance reported is 0,0,0,0 while it should be 4,4,4,4.
Repeating this proces for neurons and a single image all randomly sampled between 0 and 1 gives rise to the way to high numbers:
Produces:
Mapping result is:
While it should be four times a value between 0 and 4.
It would be great if you could spot what I do wrong (in creating the binaries, at runtime or while loading the mapping).