How should I normalize a vector in Matlab where the sum is 1?
Asked Answered
E

4

10

I need to normalize a vector of N integers so that:

  • Each value is proportional to its original value (the value will be between 0 and 1)
  • The sum of all values is =1

For instance:

If I have a vector

V = [2,2,1,0]

the normalized vector should should be:

V_norm = [0.4,0.4,0.2,0]  % 0.4+0.4+0.2 = 1

I tried with many solutions found in this community and on the web and finally I did it with this code:

part = norm(V);
if part > 0
  V_norm = V/part;
else % part = 0 --> avoid "divide by 0" 
  V_norm = part;
end

The problem this works if:

  • all elements of array are "0" --> resultant array doesn't change
  • only one element of the array is >0 and all other elements are = 0 --> resultant array: the element >0 is 1 and the other 0

but if I have a different case,although the result is proportional,the sum is not 0. For instance:

   V = [1,0,1]
   V_norm = [0.74,0,0.74]

   V = [1,1,1]
   V_norm = [0.54,0.54,0.54]

(I'm not sure if the number are correct because I can't use Matlab right now but I'm sure the sum is > 1 )

Ahy hint?

Thank you in advance

Eleonoraeleonore answered 27/6, 2012 at 10:52 Comment(0)
M
9

... the normalized vector should should be:

v_norm = [0.4, 0.4, 0.2, 0]; % 0.4+0.4+0.2 = 1

That depends. What is your norm function?

norm(x) in MATLAB returns the standard norm, meaning the sum of the squares of the elements of a normalized vector x is 1.

In your example:

v = [1, 1, 1];         %# norm(v) = sqrt(1^2+1^2+1^2) = ~1.7321
v_norm = v / norm(v);  %# v_norm = [0.5574, 0.5574, 0.5574]

sum(v_norm .^ 2) indeed yields 1, but sum(v_norm) does not, as expected.


I need to normalize a vector of N integers so that each value is proportional to its original value (the value will be between 0 and 1) and the sum of all values is 1.

What do you mean by "normalize"? Does that mean dividing by a value which is a valid mathematical norm function, according to the norm definition?

What do you mean by "proportional"? Does that imply that all elements are multiplied by that same number? If it does, and it's a valid mathematical norm, you cannot guarantee that the sum of the elements will always be 1.
For instance, consider v = [1, -2]. Then sum(v) = -1.

Or maybe sum is the function you're looking for, but it doesn't mathematically qualify as a norm, because a norm is a function that assigns a strictly positive length or size to all vectors in a vector space.
In the example above, sum(v) is negative.


Ahy hint?

You can choose either:

  1. sum(x), which fulfills both requirements but doesn't qualify as a norm function since it can yield negative values.
  2. norm(x, 1), as OleThomsenBuus suggested, which actually calculates sum(abs(x(:))).
    It won't fulfill both your requirements unless you restrict your vector space to non-negative vectors.
Mantelpiece answered 27/6, 2012 at 11:25 Comment(0)
M
10

What you need to do is, I believe, normalize using the 1-norm (taxicab norm):

v = [2, 2, 1, 0];
v_normed = v / norm(v, 1); % using the 1-norm

Variable v_normed should now be [0.4, 0.4, 0.2, 0.0]. The 1-norm of v_normed will equal 1. You can also sum the vector (similar to the 1-norm, but without applying the absolute function to each value), but the range of that sum will be between -1 to 1 in the general case (if any values in v are below 0). You could use abs on the resulting sum, but mathematically it will no longer qualify as a norm.

Michamichael answered 27/6, 2012 at 11:42 Comment(1)
Like I stated in my answer, it still doesn't fulfill the OP's two requirements for all vectors, but at least it mathematically qualifies as a norm.Mantelpiece
M
9

... the normalized vector should should be:

v_norm = [0.4, 0.4, 0.2, 0]; % 0.4+0.4+0.2 = 1

That depends. What is your norm function?

norm(x) in MATLAB returns the standard norm, meaning the sum of the squares of the elements of a normalized vector x is 1.

In your example:

v = [1, 1, 1];         %# norm(v) = sqrt(1^2+1^2+1^2) = ~1.7321
v_norm = v / norm(v);  %# v_norm = [0.5574, 0.5574, 0.5574]

sum(v_norm .^ 2) indeed yields 1, but sum(v_norm) does not, as expected.


I need to normalize a vector of N integers so that each value is proportional to its original value (the value will be between 0 and 1) and the sum of all values is 1.

What do you mean by "normalize"? Does that mean dividing by a value which is a valid mathematical norm function, according to the norm definition?

What do you mean by "proportional"? Does that imply that all elements are multiplied by that same number? If it does, and it's a valid mathematical norm, you cannot guarantee that the sum of the elements will always be 1.
For instance, consider v = [1, -2]. Then sum(v) = -1.

Or maybe sum is the function you're looking for, but it doesn't mathematically qualify as a norm, because a norm is a function that assigns a strictly positive length or size to all vectors in a vector space.
In the example above, sum(v) is negative.


Ahy hint?

You can choose either:

  1. sum(x), which fulfills both requirements but doesn't qualify as a norm function since it can yield negative values.
  2. norm(x, 1), as OleThomsenBuus suggested, which actually calculates sum(abs(x(:))).
    It won't fulfill both your requirements unless you restrict your vector space to non-negative vectors.
Mantelpiece answered 27/6, 2012 at 11:25 Comment(0)
W
6

If there are no furhter conditions to your normalization than you gave at the beginning of your question, a possible solution would be

V = [3 4 -2];
S = sum(V);
if (S == 0)
    % no solution
else
    V_norm = V ./ S;
end
sum(V_norm)
Wiggle answered 27/6, 2012 at 11:16 Comment(5)
As a sidenote, sum(v) cannot mathematically qualify as a norm because it can yield negative values.Mantelpiece
Doesn't fulfill the requirement of all values being between 0 and 1 (considering negative elements).Putrefaction
I agree. I shouldn't have been using the "normalization" instead of "norm", as did the OP. I'll edit my answer accordingly.Wiggle
there is no need for dot in ./Parabolize
@Parabolize That's correct. Still I consider it good practice to use . whenever applying scalar operators to a vector, because it makes the code unambigous.Wiggle
I
0

I will leave here my solution for "normalizing" the rows of a matrix with positive entries, where normalization means that the row-sums are 1 after the procedure.

Summary

normmat = normr(sqrt(mat)).^2

Minimal Example

mat is your matrix with positive entries

mat = [1 2 3; 2 3 4]
mat =

     1     2     3
     2     3     4

Now we do the one-liner:

normmat = normr(sqrt(mat)).^2
normmat =

    0.1667    0.3333    0.5000
    0.2222    0.3333    0.4444

The sum of each row is 1.

sum(normmat, 2)
ans =

    1.0000
    1.0000

Proportions within one row are constant

normmat ./ mat
ans =

    0.1667    0.1667    0.1667
    0.1111    0.1111    0.1111

Not necessarily the most efficient but it's one line.

Isabel answered 1/4, 2021 at 9:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.