¿Cómo normalizar los datos al rango 0-1?

267

Estoy perdido en la normalización, ¿podría alguien guiarme por favor?

Tengo valores mínimos y máximos, digamos -23.89 y 7.54990767, respectivamente.

Si obtengo un valor de 5.6878, ¿cómo puedo escalar este valor en una escala de 0 a 1?

Angelo
fuente
8
¿Es este el camino = (valor-min) / (max-min)
Angelo
3
Puede ayudarlo a leer este hilo: cómo-verificar-una-distribución-está-normalizada . Si eso responde a su pregunta, puede eliminar esta Q; si no, edite su Q para especificar lo que aún no comprende.
gung
1
Explicación de la protección: esta pregunta está atrayendo respuestas adicionales que contienen solo soluciones de código. Si bien estos pueden ser interesantes o útiles para algunos lectores, no es un objetivo de CV proporcionar repositorios de soluciones de código.
Nick Cox
1
las soluciones proporcionadas consideran un valor de contraste lineal : ¿le gustaría una normalización diferente, por ejemplo, una que logre una probabilidad uniforme para la salida?
meduz

Respuestas:

300

Si desea normalizar sus datos, puede hacerlo como sugiere y simplemente calcular lo siguiente:

zi=ximin(x)max(x)min(x)

donde y son ahora sus datos normalizados . Como prueba de concepto (aunque no lo solicitó) aquí hay un código y un gráfico adjunto para ilustrar este punto:x=(x1,...,xn)ziithR

ingrese la descripción de la imagen aquí

# Example Data
x = sample(-100:100, 50)

#Normalized Data
normalized = (x-min(x))/(max(x)-min(x))

# Histogram of example data and normalized data
par(mfrow=c(1,2))
hist(x,          breaks=10, xlab="Data",            col="lightblue", main="")
hist(normalized, breaks=10, xlab="Normalized Data", col="lightblue", main="")
kmario23
fuente
11
Solo me pregunto cómo hacen los dos histogramas de aspecto bastante diferente illustrate the pointde su respuesta (correcta).
ttnphns
12
@ttnphns Se ven solo diferentes debido a la agrupación de los histogramas. Sin embargo, mi punto era mostrar que los valores originales vivían entre -100 y 100 y ahora, después de la normalización, viven entre 0 y 1. Podría haber usado un gráfico diferente para mostrar esto, supongo, o simplemente estadísticas resumidas.
20
El suave empujón de @ttnphns tenía la intención de alentarlo no solo a usar un medio menos complicado para ilustrar una idea (simple), sino también (sospecho) como una pista de que una ilustración más directamente relevante podría ser beneficiosa aquí. Puede hacer ambas cosas al encontrar una forma más directa de graficar la transformación cuando se aplica a los
valores mínimos
1
¿Hay alguna forma de "normalizar" al rango personalizado en lugar de 0-1?
John Demetriou
1
@JohnDemetriou Puede que no sea la solución más limpia, pero puede escalar los valores normalizados para hacerlo. Si desea, por ejemplo, un rango de 0-100, simplemente multiplique cada número por 100. Si desea un rango que no comienza con 0, como 10-100, lo haría escalando el MAX-MIN y luego al valores que obtienes de eso simplemente agregando el MIN. Así que escale 90, luego agregue 10. Eso debería ser suficiente para la mayoría de los rangos personalizados que desee.
Alexander Rossa
47

La fórmula general de una línea para reescalar linealmente los valores de datos que han observado min y max en un nuevo rango arbitrario min ' a max' es

  newvalue= (max'-min')/(max-min)*(value-max)+max'
  or
  newvalue= (max'-min')/(max-min)*(value-min)+min'.
ttnphns
fuente
99
Esto es correcto, pero no eficiente. Es una transformación lineal, por lo que debe calcular previamente ay bconstantes, y luego simplemente aplicar newvalue = a * value + b. a = (max'-min')/(max-min)yb = max - a * max
Mark Lakata el
1
¿Sabes cómo citar esto? Quiero decir, ¿hay alguna referencia "original" en alguna parte?
Trefex
3
@MarkLakata Corrección leve (¿error tipográfico?): b = max' - a * maxOb = min' - (a * min)
Nick
@ Nick - sí. Me falta un '
Mark Lakata
¿Puede comparar su normalización aquí se.mathworks.com/matlabcentral/answers/… es decir, la ecuación u = -1 + 2.*(u - min(u))./(max(u) - min(u));.
Léo Léopold Hertz 준영
13

Aquí está mi implementación de PHP para la normalización:

function normalize($value, $min, $max) {
	$normalized = ($value - $min) / ($max - $min);
	return $normalized;
}

Pero mientras construía mis propias redes neuronales artificiales, necesitaba transformar la salida normalizada de nuevo a los datos originales para obtener una buena salida legible para el gráfico.

function denormalize($normalized, $min, $max) {
	$denormalized = ($normalized * ($max - $min) + $min);
	return $denormalized;
}

$int = 12;
$max = 20;
$min = 10;

$normalized = normalize($int, $min, $max); // 0.2
$denormalized = denormalize($normalized, $min, $max); //12

La desnormalización utiliza la siguiente fórmula:

x(maxmin)+min

jankal
fuente
2
Hay una diferencia importante entre esta respuesta y la respuesta ya aceptada. Eso explicaba la idea principal de forma clara y directa, y luego mostraba de forma secundaria cómo hacerlo en un programa de uso común. Por el contrario, publica aquí solo el código. Si bien me complace creer que este es un buen código (no escribo PHP) en este foro, normalmente no tenemos un paquete de respuestas a cada pregunta que explique cómo hacerlo en todos los idiomas imaginables. De lo contrario, tendríamos respuestas aquí en SAS, SPSS, Stata, MATLAB, C, C ++, C #, Java. Python, etc., etc.
Nick Cox
2
No creo que esta sea la única diferencia. En mi código, también mostré cómo devolver un valor normalizado al valor que tenía antes de la normalización. Creo que eso hace que valga la pena esta respuesta.
enero
1
Todavía es cierto que publicas solo código: creo que debes enfatizar cualquier virtud supuestamente especial del código en los comentarios, ya que de lo contrario los lectores tienen que leer el código para ver cuáles son. Presumiblemente, la inversión de la escala solo se usa cuando (a) se han sobrescrito los valores originales, pero (b) el usuario ha recordado con prudencia guardar el mínimo y el máximo. Mi punto más amplio, como se comentó anteriormente, es que CV no pretende ser un repositorio de ejemplos de código.
Nick Cox
Hay algunos problemas, donde necesita restaurar el valor: Nueral Networks, por ejemplo ... Pero tiene razón, en términos de análisis de datos, esta respuesta es muy mala.
enero
3
@ NickCox Me pareció que su respuesta era más satisfactoria que la aceptada.
Karl Morrison
4

División por cero

Una cosa a tener en cuenta es que max - minpodría ser igual a cero. En este caso, no querrás realizar esa división.

El caso en el que esto sucedería es cuando todos los valores de la lista que intenta normalizar sean iguales. Para normalizar dicha lista, cada elemento sería 1 / length.

// JavaScript
function normalize(list) {
   var minMax = list.reduce((acc, value) => {
      if (value < acc.min) {
         acc.min = value;
      }

      if (value > acc.max) {
         acc.max = value;
      }

      return acc;
   }, {min: Number.POSITIVE_INFINITY, max: Number.NEGATIVE_INFINITY});

   return list.map(value => {
      // Verify that you're not about to divide by zero
      if (minMax.max === minMax.min) {
         return 1 / list.length
      }

      var diff = minMax.max - minMax.min;
      return (value - minMax.min) / diff;
   });
}

Ejemplo:

normalize([3, 3, 3, 3]); // output => [0.25, 0.25, 0.25, 0.25]
rodrigo-silveira
fuente
Este es un cambio de escala a una suma 1, no a un rango de 0-1. Simplemente creo que la respuesta está fuera de tema, por lo tanto.
ttnphns
No tan. normalize([12, 20, 10])salidas [0.2, 1.0, 0.0], que es lo mismo que obtendría con (val - min) / (max - min).
rodrigo-silveira
@ rodrigo-silveira No veo por qué la salida de 0.25. ¿No es mejor todo 0.5? Todos los elementos son iguales, por lo que deben mantenerse centrados en el intervalo.
javierdvalle
0

la respuesta es correcta pero tengo una sugerencia, ¿qué pasa si sus datos de entrenamiento se enfrentan a algún número fuera de rango? podrías usar la técnica de aplastar. se garantizará que nunca saldrá del alcance. En vez de esto

ingrese la descripción de la imagen aquí

recomiendo usar esto

ingrese la descripción de la imagen aquí

con aplastamiento como este en min y max de rango

ingrese la descripción de la imagen aquí

y el tamaño de la brecha esperada fuera del rango es directamente proporcional al grado de confianza de que habrá valores fuera del rango.

para obtener más información, puede buscar en google: aplastar los números fuera de rango y consultar el libro de preparación de datos de "dorian pyle"

parvij
fuente
55
Edite su respuesta para usar la capitalización como convencional. Las minúsculas consistentes pueden parecer divertidas o eficientes, pero es más difícil de leer para casi todos.
Nick Cox
3
Las ilustraciones no transmiten adecuadamente su respuesta. ¿Qué es exactamente una "técnica de aplastamiento"?
whuber
0

Prueba esto. Es consistente con la escala de funciones

normalize <- function(x) { 
  x <- as.matrix(x)
  minAttr=apply(x, 2, min)
  maxAttr=apply(x, 2, max)
  x <- sweep(x, 2, minAttr, FUN="-") 
  x=sweep(x, 2,  maxAttr-minAttr, "/") 
  attr(x, 'normalized:min') = minAttr
  attr(x, 'normalized:max') = maxAttr
  return (x)
} 
Lui Kimman
fuente
77
Hay una diferencia importante entre esta respuesta y la respuesta ya aceptada. Eso explicaba la idea principal de forma clara y directa, y luego mostraba de forma secundaria cómo hacerlo en un programa de uso común. Por el contrario, publica aquí solo el código. Si bien estoy feliz de creer que este es un buen código (en un lenguaje inexplicable) en este foro, normalmente no tenemos un paquete de respuestas a cada pregunta que explique cómo hacerlo en cada idioma concebible. De lo contrario, tendríamos respuestas aquí en SAS, SPSS, Stata, MATLAB, C, C ++, C #, Java. Python, etc., etc.
Nick Cox