32

I am not really sure what this operation might be called, but I have some numbers, for example:

  • 40
  • 10

I need to format these numbers so that they form the sum 1, but they should keep their "weight".

In this specific case:

  • 40 would become 0.80
  • 10 would become 0.2

But if I have more values (like 40, 10, 25, 5 for example), I am really lost because I don't know the formula.

If anybody can help, could they please reply in words (for example: "Sum up all values then divide through...", and not in a formula? I am really not good at reading formulas at all.

Seanny123
  • 169
tmighty
  • 393

7 Answers7

52

Why not just divide each number in your sample by the sum of all the numbers in your sample?

Rustyn
  • 8,407
15

The answers provided here won't work in cases where the set contains negative numbers.

The function you're looking for is called the softmax function. The softmax function is often used in the final layer of a neural network-based classifier. Softmax is defined as:

$$f_i(x) = \frac{e^{x_i}}{\sum_j e^{x_j}}$$

Chris
  • 103
  • 8
    This does not maintain the relative spacing of the values. Small values become less import -> larger values are relatively larger after the softmax. OP wanted their "weights" to remain unchanged. – n1k31t4 Apr 16 '20 at 20:22
  • Yup, this is a wrong answer! Softmax is a non-linear transform, which means exactly what the comment above says: it does not maintain the relative spacing of the values. – Ondrej Sotolar Jan 03 '23 at 12:55
14

I'm currently learning probability from an online course.

It's teaching me to use this amazingly simple method, and so far it has worked flawlessly!

Where e is an element in the list of numbers to be normalized:

Calculate a normalizer (multiplier) like so:

normalizer = 1 / (e1 + e2 + e3)

Next, multiply the normalizer to every element in the list:

((e1 * normalizer) + (e2 * normalizer) + .... + (en * normalizer) ) == 1.0

... and they will add up to 1.0.

So taking your example of numbers 10 and 40:

normalizer = 1 / (10 + 40) = 0.02
(10 * 0.02) = 0.2
(40 * 0.02) = 0.8
(0.2 + 0.8) = 1.0

Hence we get our 1.0.

I've gone ahead and written a simple Python script that you can run on almost any Python interpreter and play around with the parameters and test the results.

# python script
import random as rnd

# number of items in list, change this to as huge a list as you want
itemsInList = 5 

# specify min and max value bounds for randomly generated values
# change these to play around with different value ranges
minVal = 8
maxVal = 20

# creates a list of random values between minVal and maxVal, and sort them
numList = sorted( [rnd.randint(minVal, maxVal) for x in range(itemsInList)] )
print ('initial list is\n{}\n'.format(numList))

# calculate the normalizer, using: (1 / (sum_of_all_items_in_list))
normalizer = 1 / float( sum(numList) )

# multiply each item by the normalizer
numListNormalized = [x * normalizer for x in numList]
print('Normalized list is\n{}\n'.format(numListNormalized))

print('Sum of all items in numListNormalized is {}'.format(sum(numListNormalized)))

Running the code gives this sample output:

initial list is
[9, 12, 15, 16, 19]

Normalized list is
[0.1267605633802817, 0.16901408450704225, 0.2112676056338028, 0.22535211267605634, 0.26760563380281693]

Sum of all items in numListNormalized is 1.0

I hope this helps!

  • 2
    The best answer here, according to my understanding of the question. Works with negative numbers too Also, you can "rescale" you array to maintain any sum, not only 1. Then the normalizer should divide the target sum value instead of 1. – Dmytro Titov May 24 '20 at 13:10
  • Excellent. How would I proceed if I need to split 1 into weighted parts? The reverse of this approach? If I need 2 parts, I would need 0.8 and 0.2. If I need 3 parts, 0.6, 0.3, 0.1. And so on. How would I approach this problem? – iam thadiyan Mar 15 '21 at 05:43
  • 3
    e1 + e2 + e3 can sum to 0, then a division by zero would happen. – fjsj Apr 23 '21 at 15:33
  • Thank you, this is definitely the best answer. Note that if you need to normalise to some other number than 1 (say, you want to balance percentages to add up to 100) you can simply do normalizer = 100 / (e1 + e2 + e3). This scales to any number of es. – theberzi Aug 31 '22 at 19:18
11

From the text description, it seems this is what you want:

  • calculate the sum of all elements
  • divide each element by the sum

Note that, however, then your example $[40, 10]$ normalises as $[0.8, 0.2]$, not $[0.75,0.25]$. The latter doesn't preserve the ratio of both elements.

1

My take on the problem. First, in order to get rid of negative numbers, subtract all values in the original vector $\vec{x}$ by the minimum value in it: $\vec{u}=\vec{x}-\text{min}(\vec{x})$. This will ensure the minimum value in $\vec{u}$ will be 0. Then, the final "normalized" values between 0 and 1 are given by $$z_i = \frac{\vec{u}_i}{\sum_{j \in \vec{u}} \vec{u}_{j}}.$$

Edit: as pointed out in the comments, subtracting the minimum value of $\vec{x}$ from all values in $\vec{x}$ should only be done if at least one of the values in $\vec{x}$ is negative. After this step, the sum of the values in the final vector $\vec{z}$ will be 1.

What it means to calculate ratios involving negative values is open to interpretation. Maybe it's a closer behavior to that of the softmax function in machine learning, as it makes all values positive and sum to 1.

  • 1
    Why are you subtracting the minimal value? In the example provided, it would turn the 10 to 0 but the example says that it should turn to 0.2. – Hume2 May 15 '20 at 11:48
  • You're right. I'll have a go at this again later. – Douglas De Rizzo Meneghetti May 15 '20 at 16:27
  • @Hume2 I just realized that subtracting the minimal value, when there is at least one negative value in the vector, may solve the problem of having negative values in the original vector, as after this, dividing all values by their sum still results in a kind of vector of ratios, in which their sum is 1. I just don't know if there is an interpretation to that, as we're dealing with ratios involving negative numbers.

    It should not be done if values are greater than or equal to 0.

    – Douglas De Rizzo Meneghetti May 17 '20 at 19:32
  • If the sum is zero, the "weight" isn't defined either. And when there are negative numbers but the sum is still nonzero, I don't see why the "weight" should be defined differently. – Hume2 May 18 '20 at 05:12
0

Divide $100$ by the sum which is $80$ to get $1.25$. Then you multiply the the terms and use simple proportion where $80*1.25=100$ is proportional to one. You will get answers like $05,0.125,0.3125$ and $0.0625$.

Sudarsan
  • 876
david
  • 1
-1

Just divide all the numbers through by 50. Should normalise it to the scale you want 0 - 1. For example: 40/50 = 0.8 25/50 = 0.5 5/50 = 0.1

etc.

I think you get the idea!