Como representar uma variável ilimitada como número entre 0 e 1


28

Eu quero representar uma variável como um número entre 0 e 1. A variável é um número inteiro não negativo sem limite inerente. Mapeio 0 a 0, mas o que posso mapear para 1 ou números entre 0 e 1?

Eu poderia usar o histórico dessa variável para fornecer os limites. Isso significaria que eu tenho que reafirmar as estatísticas antigas se o máximo aumentar. Preciso fazer isso ou existem outros truques que devo conhecer?


6
Como qualquer função não decrescente de fará o truque, você tem muita flexibilidade. Mas alguns métodos serão melhores que outros, dependendo da aplicação. Qual é o seu propósito em buscar essa re-expressão? [0 0,)[0 0,1]
whuber

1
Estou medindo o conteúdo em várias dimensões diferentes e quero poder fazer comparações em termos de quão relevante é uma determinada parte do conteúdo. Além disso, quero exibir valores nessas dimensões explicáveis ​​e de fácil compreensão.
SpencerMar

1
@ Spencer Exatamente como você está medindo o conteúdo e a "relevância"? Por exemplo, em escalas arbitrárias, como contagens, proporções, frequências de visualizações, correlações com outros conteúdos, etc. etc. Diferentes tipos de medidas se beneficiam de diferentes tipos de re-expressões.
whuber

1
Estou medindo-os em escalas arbitrárias. Qual a idade do conteúdo. Quantos "pontos" um conteúdo é recebido. "Interesse" auto-relatado no domínio do conteúdo.
Spencer #

2
Uma das transformações mais simples que você pode usar é converter seus dados em pontuações quantílicas.
Charles.y.zheng 15/03/11

Respostas:


34

Um truque muito comum para fazer isso (por exemplo, na modelagem conexionista) é usar o tangh hiperbólico da tangente como a 'função de esmagar ". Ele ajusta automaticamente todos os números no intervalo entre -1 e 1. O que, no seu caso, restringe o intervalo de 0 a 1. In re matlabvocê obtém via tanh().

Outra função de esmagamento é a função logística (graças a Simon pelo nome), fornecida por , que restringe o intervalo de 0 a 1 (com 0 mapeado para. 5) Portanto, você teria que multiplicar o resultado por 2 e subtrair 1 para ajustar seus dados no intervalo entre 0 e 1.f(x)=1/(1+e-x)

Aqui está um código R simples que plota as duas funções (tanh em vermelho, logístico em azul) para que você possa ver como os dois squash:

x <- seq(0,20,0.001)
plot(x,tanh(x),pch=".", col="red", ylab="y")
points(x,(1 / (1 + exp(-x)))*2-1, pch=".",col="blue")

Obrigado pela sua resposta. Isso resolve o problema da delimitação. Para meus dados, ele chega a 1 muito rapidamente para meus dados, então acho que a próxima coisa que preciso fazer é dimensionar essas informações para se concentrar no intervalo interessante que eu poderia fazer com base no histórico delas, sem medo de deixar o limite, apenas atingindo o limite.
Russell Gallop

25

Freqüentemente, minha primeira pergunta seria " por que você quer fazer isso", então vi que você já respondeu isso nos comentários da pergunta: " Estou medindo o conteúdo em várias dimensões diferentes e quero ser capaz de fazer comparações em termos de quão relevante é uma determinada parte do conteúdo. Além disso, quero exibir valores nessas dimensões explicáveis ​​e de fácil compreensão " .

zzz-scores, é preferível que cada variável tenha uma distribuição aproximadamente normal, ou pelo menos uma distribuição aproximadamente simétrica (ou seja, não seja severamente inclinada), mas se necessário, você pode aplicar alguma transformação de dados apropriada primeiro para conseguir isso; qual transformação usar poderia ser determinada encontrando a transformação Box-Cox mais adequada .


[0 0,1]

1
mad()rank()ecdf()ecdf(x)ppx1/nx1
Karl Ove Hufthammer

10

Qualquer função sigmóide funcionará:


erf não é uma função muito útil, desde que você não queira usá-la como derivada.

Acabei usando uma função logística simples com alguns pequenos ajustes: (1 / (1 + java.lang.Math.exp (-1 * (fator * i))) - 0,5) * 2. Escolhi um fator de 0,05 que parece funcionar bem para i entre 0 e algumas centenas.
Jilles van Gurp 22/09

1.0 / (1,0 + exp (-1,69897 * (x-média (x)) / SD (x))) é uma boa aproximação para pnorm
Chris

3

Além das boas sugestões de Henrik e Simon Byrne, você pode usar f (x) = x / (x + 1). A título de comparação, a função logística exagerará as diferenças à medida que x aumenta. Ou seja, a diferença entre f (x) ef (x + 1) será maior com a função logística do que com f (x) = x / (x + 1). Você pode ou não querer esse efeito.



1

Para adicionar às outras respostas sugerindo pnorm ...

Para um método potencialmente ideal para selecionar parâmetros, sugiro esta aproximação para pnorm.

1.0/(1.0+exp(-1.69897*(x-mean(x))/sd(x)))

pnormish

Isso é essencialmente a Softmax Normalização.

Referência Pnorm em uma pitada


1

Existem duas maneiras de implementar isso que eu uso normalmente. Estou sempre trabalhando com dados em tempo real, portanto, isso pressupõe entrada contínua. Aqui estão alguns pseudo-códigos:

Usando um minmax treinável:

define function peak:
    // keeps the highest value it has received

define function trough:
    // keeps the lowest value it has received

define function calibrate:
    // toggles whether peak() and trough() are receiving values or not

define function scale:
    // maps input range [trough.value() to peak.value()] to [0.0 to 1.0]

Esta função requer que você execute uma fase inicial de treinamento (usando calibrate()) ou que treine novamente em determinados intervalos ou de acordo com determinadas condições. Por exemplo, imagine uma função como esta:

define function outBounds (val, thresh):
    if val > (thresh*peak.value()) || val < (trough.value() / thresh):
        calibrate()

O pico e a calha normalmente não estão recebendo valores, mas se outBounds()recebe um valor superior a 1,5 vezes o pico atual ou menor que a calha atual dividido por 1,5, calibrate()é chamado o que permite que a função seja recalibrada automaticamente.

Usando um minmax histórico:

var arrayLength = 1000
var histArray[arrayLength]

define historyArray(f):
    histArray.pushFront(f) //adds f to the beginning of the array

define max(array):
    // finds maximum element in histArray[]
    return max

define min(array):
    // finds minimum element in histArray[]
    return min

define function scale:
    // maps input range [min(histArray) to max(histArray)] to [0.0 to 1.0]

main()
historyArray(histArray)
scale(min(histArray), max(histArray), histArray[0])
// histArray[0] is the current element

Tudo isso pode ser implementado no Max / MSP / Jitter com os objetos [peak] e [trough] no primeiro exemplo e com [jit.3m] no segundo exemplo.
terrace

0

Uma opção muito simples é dividir cada número em seus dados pelo maior número em seus dados. Se você tiver muitos números pequenos e alguns muito grandes, isso pode não transmitir bem as informações. Mas é relativamente fácil; se você acha que informações significativas são perdidas ao representar graficamente os dados dessa maneira, tente uma das técnicas mais sofisticadas sugeridas por outras pessoas.

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.