Como normalizar os dados no intervalo 0-1?


266

Estou perdido na normalização, alguém poderia me guiar por favor.

Eu tenho um valor mínimo e máximo, digamos -23.89 e 7.54990767, respectivamente.

Se eu receber um valor de 5,6878, como posso escalar esse valor em uma escala de 0 a 1.


8
é esta a forma = (valor-min) / (max-min)
Angelo

3
Pode ajudá-lo a ler este tópico: como verificar uma distribuição está normalizada . Se isso responder à sua pergunta, você pode excluir este Q; caso contrário, edite seu Q para especificar o que você ainda não entende.
gung

1
Explicação da proteção: Esta pergunta está atraindo respostas extras que contêm apenas soluções de código. Embora isso possa ser interessante ou útil para alguns leitores, o CV não tem como objetivo fornecer repositórios de soluções de código.
Nick Cox

1
as soluções fornecidas consideram um valor de contraste linear - você gostaria de uma normalização diferente, por exemplo, uma que atinja uma probabilidade uniforme para a saída?
meduz 21/05/19

Respostas:


299

Se você deseja normalizar seus dados, faça o que sugere e simplesmente calcule o seguinte:

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

onde e agora são seus dados normalizados. Como prova de conceito (embora você não tenha solicitado), aqui estão alguns códigos e um gráfico anexo para ilustrar este ponto:x=(x1,...,xn)ziithR

insira a descrição da imagem aqui

# 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="")

11
Só me pergunto como os dois histogramas de aparência bastante diferente illustrate the pointda sua resposta (correta).
ttnphns

12
@ttnphns Eles parecem apenas diferentes devido ao binning dos histogramas. Meu objetivo, no entanto, era mostrar que os valores originais viviam entre -100 e 100 e agora após a normalização eles vivem entre 0 e 1. Eu poderia ter usado um gráfico diferente para mostrar isso, suponho ou apenas estatísticas resumidas.

20
A gentil cutucada de @ttnphns foi criada para encorajá-lo não apenas a usar um meio menos complicado de ilustrar uma idéia (simples), mas também (suspeito) como uma dica de que uma ilustração mais diretamente relevante pode ser benéfica aqui. Você poderia fazer tanto por encontrar uma maneira mais simples para representar graficamente a transformação quando é aplicado ao mínimo e máximo realmente fornecido pelo OP
whuber

1
Existe uma maneira de "normalizar" para o intervalo personalizado em vez de 0-1?
John Demetriou

1
@JohnDemetriou Pode não ser a solução mais limpa, mas você pode dimensionar os valores normalizados para fazer isso. Se você quiser, por exemplo, um intervalo de 0 a 100, multiplique cada número por 100. Se desejar um intervalo que não comece com 0, como 10 a 100, faça isso escalando pelo MAX-MIN e depois para o valores que você obtém apenas adicionando o MIN. Portanto, aumente a escala em 90 e adicione 10. Isso deve ser suficiente para a maioria dos intervalos personalizados que você deseja.
Alexander Rossa

47

A fórmula geral de uma linha para redimensionar linearmente os valores dos dados que observaram min e max em um novo intervalo arbitrário min ' a max' é

  newvalue= (max'-min')/(max-min)*(value-max)+max'
  or
  newvalue= (max'-min')/(max-min)*(value-min)+min'.

9
Isso está correto, mas não é eficiente. Como é uma transformação linear, você deve pré a- calcular e bconstantes e depois aplicar newvalue = a * value + b. a = (max'-min')/(max-min)eb = max - a * max
Mark Lakata 23/09

1
Você sabe citar isso? Quero dizer, existe uma referência "original" em algum lugar?
Trefex

3
@MarkLakata Correção ligeira (erro de digitação?): b = max' - a * maxOub = min' - (a * min)
Nick

@ Nick - sim. Estou faltando um '
Mark Lakata 30/12/2014

Você pode comparar sua normalização aqui se.mathworks.com/matlabcentral/answers/… ou seja, a equação u = -1 + 2.*(u - min(u))./(max(u) - min(u));.
Léo Léopold Hertz # 24/16

13

Aqui está minha implementação do PHP para normalização:

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

Mas enquanto eu estava construindo minhas próprias redes neurais artificiais, precisei transformar a saída normalizada de volta nos dados originais para obter uma boa saída legível para o 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

A desnormalização usa a seguinte fórmula:

x(maxmin)+min


2
Há uma diferença importante entre esta resposta e a resposta já aceita. Isso explicou a idéia principal de maneira clara e direta e, em seguida, mostrou como fazê-lo em um programa comumente usado. Por outro lado, você publica aqui apenas o código. Embora eu esteja feliz em acreditar que este é um bom código (não escrevo PHP) neste fórum, normalmente não temos um pacote de respostas para todas as perguntas que explicam como fazê-lo em todas as linguagens concebíveis. Caso contrário, teríamos respostas aqui em SAS, SPSS, Stata, MATLAB, C, C ++, C #, Java. Python, etc, etc #
Nick Cox

2
Eu não acho que essa seja a única diferença. No meu código, também mostrei como retornar um valor normalizado ao valor que era antes da normalização. Eu acho que vale a pena essa resposta.
27415 jankal

1
Ainda é verdade que você publica apenas código: acho que você precisa enfatizar virtudes supostamente especiais do código nos comentários, caso contrário os leitores precisam ler o código para ver o que são. Presumivelmente, inverter a escala é útil apenas quando (a) os valores originais foram substituídos, mas (b) o usuário se lembrou prudentemente de salvar o mínimo e o máximo. Meu argumento mais amplo, como comentado acima, é que o CV não pretende ser um repositório de exemplos de código.
Nick Cox

Existem alguns problemas nos quais você precisa restaurar o valor: Nueral Networks, por exemplo ... Mas você está certo, em termos de análise de dados, essa resposta é muito ruim.
jankal

3
@NickCox, achei sua resposta mais satisfatória do que a aceita.
Karl Morrison

4

Divisão por zero

Uma coisa a ter em mente é que isso max - minpode ser igual a zero. Nesse caso, você não gostaria de executar essa divisão.

O caso em que isso aconteceria é quando todos os valores da lista que você está tentando normalizar são iguais. Para normalizar essa lista, cada item seria 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;
   });
}

Exemplo:

normalize([3, 3, 3, 3]); // output => [0.25, 0.25, 0.25, 0.25]

Isso é um redimensionamento para a soma 1, e não para o intervalo 0-1. Eu só acho que a resposta está fora de tópico, portanto.
ttnphns

Não tão. normalize([12, 20, 10])saídas [0.2, 1.0, 0.0], que é a mesma que você obteria (val - min) / (max - min).
rodrigo-silveira

@ rodrigo-silveira Não vejo por que toda a saída de 0,25. Não é melhor todos os 0,5? Todos os itens são iguais, portanto, devem ser mantidos centralizados no intervalo.
javierdvalle 02/04

0

a resposta está certa, mas tenho uma sugestão, e se seus dados de treinamento enfrentarem algum número fora do intervalo? você pode usar a técnica de esmagamento. será garantido que nunca fique fora de alcance. ao invés disso

insira a descrição da imagem aqui

eu recomendo usar isso

insira a descrição da imagem aqui

com esmagamento como este em min e max de alcance

insira a descrição da imagem aqui

e o tamanho da lacuna esperada fora da faixa é diretamente proporcional ao grau de confiança de que haverá valores fora da faixa.

para obter mais informações, você pode pesquisar no Google: esmagar os números fora da faixa e consultar o livro de preparação de dados de "dorian pyle"


5
Edite sua resposta para usar letras maiúsculas como convencional. Letras minúsculas consistentes podem parecer divertidas ou eficientes, mas é mais difícil para quase todo mundo ler.
Nick Cox

3
As ilustrações não transmitem adequadamente sua resposta. O que exatamente é uma "técnica de esmagamento"?
whuber

0

Tente isso. É consistente com a escala da função

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)
} 

7
Há uma diferença importante entre esta resposta e a resposta já aceita. Isso explicou a idéia principal de maneira clara e direta e, em seguida, mostrou como fazê-lo em um programa comumente usado. Por outro lado, você publica aqui apenas o código. Embora eu esteja feliz em acreditar que este é um bom código (em algum idioma inexplicável) deste fórum, normalmente não temos um conjunto de respostas para todas as perguntas que explicam como fazê-lo em todos os idiomas imagináveis. Caso contrário, teríamos respostas aqui em SAS, SPSS, Stata, MATLAB, C, C ++, C #, Java. Python, etc, etc #
Nick Cox
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.