Jak znormalizować dane do zakresu 0-1?


265

Jestem zagubiony w normalizacji, czy ktoś mógłby mnie poprowadzić, proszę.

Mam wartości minimalne i maksymalne, powiedzmy odpowiednio -23,89 i 7,54990767.

Jeśli otrzymam wartość 5,6878, jak mogę skalować tę wartość w skali od 0 do 1.


8
jest w ten sposób = (wartość-min) / (maks-min)
Angelo

3
Może ci pomóc przeczytać ten wątek: jak-zweryfikować-a-dystrybucja-jest znormalizowana . Jeśli to odpowiada na twoje pytanie, możesz usunąć to Q; jeśli nie, edytuj swoje Q, aby określić, czego nadal nie rozumiesz.
gung

1
Wyjaśnienie ochrony: To pytanie przyciąga dodatkowe odpowiedzi zawierające wyłącznie rozwiązania kodowe. Chociaż mogą być interesujące lub przydatne dla niektórych czytelników, CV nie zapewnia repozytoriów rozwiązań kodowych.
Nick Cox

1
dostarczone rozwiązania uwzględniają wartość kontrastu liniowego - czy chcesz inną normalizację, na przykład taką, która osiąga jednolite prawdopodobieństwo dla wyniku?
meduz

Odpowiedzi:


299

Jeśli chcesz znormalizować swoje dane, możesz to zrobić, sugerując i po prostu obliczyć:

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

gdzie i to teraz twoje znormalizowane dane. Jako dowód koncepcji (choć o to nie prosiłeś), oto kod i towarzyszący mu wykres ilustrujący ten punkt:x=(x1,...,xn)ziithR

wprowadź opis zdjęcia tutaj

# 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
Zastanawiam się tylko, jak wypadają dwa zupełnie odmienne histogramy illustrate the point(poprawnej) odpowiedzi?
ttnphns

12
@ttnphns Wyglądają inaczej tylko z powodu grupowania histogramów. Moim celem było jednak wykazanie, że oryginalne wartości żyły od -100 do 100, a teraz po normalizacji żyją od 0 do 1. Mógłbym użyć innego wykresu, aby to pokazać, lub tylko statystyki podsumowujące.

20
Delikatny szturm @ttnphns miał zachęcić cię nie tylko do użycia mniej skomplikowanych sposobów zilustrowania (prostego) pomysłu, ale także (podejrzewam) jako wskazówkę, że korzystniejsza może być bardziej odpowiednia ilustracja. Możesz to zrobić, znajdując prostszy sposób na
wykreślenie

1
Czy istnieje sposób na „normalizację” zakresu niestandardowego zamiast 0-1?
John Demetriou,

1
@JohnDemetriou Może nie być najczystszym rozwiązaniem, ale w tym celu można skalować znormalizowane wartości. Jeśli chcesz na przykład zakres 0-100, po prostu pomnóż każdą liczbę przez 100. Jeśli chcesz zakres, który nie zaczyna się od 0, np. 10-100, zrobiłbyś to skalując według MAX-MIN, a następnie do wartości, które otrzymujesz po dodaniu MIN. Skaluj o 90, a następnie dodaj 10. To powinno wystarczyć dla większości niestandardowych zakresów.
Alexander Rossa

47

Ogólny wzór jednej linii liniowo przeskalowania wartości danych Obserwując min i max do nowego dowolnego zakresu min' do max” jest

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

9
Jest to poprawne, ale nieefektywne. Jest to transformacja liniowa, więc dokonałeś wstępnego obliczenia ai bstałych, a następnie po prostu zastosowałeś newvalue = a * value + b. a = (max'-min')/(max-min)ib = max - a * max
Mark Lakata,

1
Czy wiesz jak to cytować? Mam na myśli, czy jest gdzieś „oryginalne” odniesienie?
Trefex

3
@ MarkLakata Niewielka korekta (literówka?): b = max' - a * maxLubb = min' - (a * min)
Nick

@Nick - tak. Brakuje mi '
Mark Lakata,

Czy możesz porównać swoją normalizację tutaj se.mathworks.com/matlabcentral/answers/… tj. Równanie u = -1 + 2.*(u - min(u))./(max(u) - min(u));.
Léo Léopold Hertz

13

Oto moja implementacja PHP do normalizacji:

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

Ale kiedy budowałem własne sztuczne sieci neuronowe, musiałem przekształcić znormalizowane dane wyjściowe z powrotem do oryginalnych danych, aby uzyskać dobry odczyt na wykresie.

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

W normalizacji wykorzystuje się następującą formułę:

x(max-min)+min


2
Istnieje istotna różnica między tą odpowiedzią a odpowiedzią już zaakceptowaną. To wyjaśniło główną ideę jasno i bezpośrednio, a następnie pokazało, jak to zrobić w jednym powszechnie używanym programie. I odwrotnie, zamieszczasz tutaj tylko kod. Chociaż cieszę się, że to dobry kod (nie piszę PHP) na tym forum, zwykle nie mamy pakietu odpowiedzi na każde pytanie wyjaśniające, jak to zrobić w każdym możliwym języku. W przeciwnym razie mielibyśmy odpowiedzi tutaj w SAS, SPSS, Stata, MATLAB, C, C ++, C #, Java. Python itp.
Nick Cox

2
Nie sądzę, że to jedyna różnica. W moim kodzie pokazałem również, jak przywrócić znormalizowaną wartość do wartości sprzed normalizacji. Myślę, że to sprawia, że ​​warto tę odpowiedź.
jankal

1
Nadal jest prawdą, że publikujesz tylko kod: Myślę, że musisz w komentarzu podkreślić wszelkie rzekomo szczególne zalety kodu, ponieważ w przeciwnym razie czytelnicy będą musieli przeczytać kod, aby zobaczyć, co to jest. Przypuszczalnie odwrócenie skalowania jest użyteczne tylko wtedy, gdy (a) pierwotne wartości zostały zastąpione, ale (b) użytkownik ostrożnie zapamiętał, aby zapisać minimum i maksimum. Moja szersza uwaga, jak skomentowano powyżej, jest taka, że ​​CV nie ma być repozytorium przykładów kodu.
Nick Cox

Istnieją pewne problemy, gdzie trzeba przywrócić wartość: na przykład Nueral Networks ... Ale masz rację, jeśli chodzi o analizę danych, ta odpowiedź jest bardzo zła.
jankal

3
@NickCox Uważam, że jego odpowiedź jest bardziej satysfakcjonująca niż zaakceptowana.
Karl Morrison

4

Dzielenie przez zero

Należy pamiętać, że max - minmoże to być zero. W takim przypadku nie chcesz wykonywać tego podziału.

Tak się dzieje, gdy wszystkie wartości na liście, które próbujesz znormalizować, są takie same. Aby znormalizować taką listę, każdy element byłby 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;
   });
}

Przykład:

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

Jest to przeskalowanie do sumy 1, a nie do zakresu 0-1. Myślę, że dlatego odpowiedź jest nie na temat.
ttnphns

Skąd. normalize([12, 20, 10])wyjścia [0.2, 1.0, 0.0], czyli takie same, jakie można uzyskać (val - min) / (max - min).
rodrigo-silveira

@ rodrigo-silveira Nie rozumiem, dlaczego cała produkcja 0,25. Czy to nie wszystko lepiej 0,5? Wszystkie elementy są równe, więc powinny być wyśrodkowane w przedziale.
javierdvalle

0

odpowiedź jest prawidłowa, ale mam sugestię, co jeśli dane treningowe napotkają pewną liczbę poza zakresem? możesz użyć techniki zgniatania. nigdy nie wyjdzie poza zasięg. raczej niż to

wprowadź opis zdjęcia tutaj

polecam użyć tego

wprowadź opis zdjęcia tutaj

z takim zgniataniem w min i maks. zasięgu

wprowadź opis zdjęcia tutaj

a wielkość oczekiwanej luki poza zakresem jest wprost proporcjonalna do stopnia pewności, że wartości będą poza zakresem.

Aby uzyskać więcej informacji, możesz google: wyciskanie numerów spoza zakresu i zajrzyj do książki przygotowywania danych „Dorian Pyle”


5
Edytuj swoją odpowiedź, aby używać wielkich liter jako konwencjonalnych. Spójne małe litery mogą wydawać się zabawne lub wydajne, ale prawie wszystkim trudniej je odczytać.
Nick Cox,

3
Ilustracje nie przedstawiają odpowiednio Twojej odpowiedzi. Czym dokładnie jest „technika zgniatania”?
whuber

0

Spróbuj tego. Jest to zgodne ze skalą funkcji

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
Istnieje istotna różnica między tą odpowiedzią a odpowiedzią już zaakceptowaną. To wyjaśniło główną ideę jasno i bezpośrednio, a następnie pokazało, jak to zrobić w jednym powszechnie używanym programie. I odwrotnie, zamieszczasz tutaj tylko kod. Chociaż cieszę się, że to dobry kod (w jakimś niewyjaśnionym języku) na tym forum, zwykle nie mamy pakietu odpowiedzi na każde pytanie wyjaśniające, jak to zrobić w każdym możliwym języku. W przeciwnym razie mielibyśmy odpowiedzi tutaj w SAS, SPSS, Stata, MATLAB, C, C ++, C #, Java. Python itp.
Nick Cox
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.