如何将无界变量表示为0到1之间的数字


28

我想将变量表示为0到1之间的数字。该变量是一个非负整数,没有固有界限。我将0映射到0,但是我可以映射到1或0到1之间的数字呢?

我可以使用该变量的历史记录来提供限制。这意味着如果最大值增加,我必须重述旧的统计信息。我需要这样做还是应该知道其他技巧?


6
因为从任何非递减函数就可以了,你有很大的灵活性。但是取决于应用程序,某些方法会比其他方法更好。您寻求这种重新表达的目的是什么?[0,)[0,1]
ub

1
我正在衡量许多不同维度的内容,并且希望能够就给定内容的相关性进行比较。另外,我想显示这些维度上可解释且易于理解的值。
Spencer

1
@Spencer准确地说,您如何衡量内容和“相关性”?例如,在任意尺度上,例如计数,比例,视图频率,与其他内容的相关性等。不同类型的度量受益于不同种类的重新表达。
ub

1
我正在以任意尺度对其进行测量。内容的年龄。一条内容被接收多少“点”。在内容域中自我报告的“兴趣”。
斯宾塞

2
您可以使用的最简单的转换之一就是将数据转换为分位数。
charles.y.zheng 2011年

Answers:


34

这样做的一个很常见的技巧(例如,在连接主义建模中)是使用双曲正切tanh作为“挤压函数”,它会自动将所有数字拟合为-1和1之间的间隔。 0到1。在中rmatlab您可以通过获得它tanh()

另一个压扁函数是逻辑函数(感谢Simon的名字),由,该函数将范围限制为0到1(0映射为.5)。因此,您必须将结果乘以2并减去1才能使数据适合0到1之间的区间。f(x)=1/(1+ex)

这是一些简单的R代码,绘制了两个函数(红色为深褐色,蓝色为后勤形状),因此您可以看到两个壁球的情况:

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

感谢您的回答。这就解决了边界问题。对于我的数据,它的数据很快就变成1,所以我想我下一步要做的就是缩放此信息,以专注于有趣的范围,根据它的历史我可以做到这一点,而不必担心越界,刚刚达到极限。
罗素·盖洛普

25

通常,我的第一个问题是“ 您为什么要这样做”,然后我看到您已经在对该问题的评论中回答了这一问题:“ 我正在跨多个维度测量内容,并且我希望能够根据给定内容的相关性进行比较。此外,我希望在这些维度上显示清晰易懂的值。

没有理由将数据标准化以使max为1且min为零以实现此目的,而我认为这通常是个坏主意。最大值或最小值很容易成为无法代表总体分布的异常值。@osknows关于使用z -scores的分是一个更好的主意分数(也称为标准分数)使用其标准偏差而不是其范围对每个变量进行归一化。标准偏差受异常值的影响较小。为了使用zzz-scores,每个变量最好具有大致正态分布,或者至少具有大致对称分布(即不严重偏斜),但是如有必要,您可以首先应用一些适当的数据转换以实现此目的;可以通过找到最合适的Box-Cox转换来确定要使用的转换


所以没有什么做的数据迫使到,一般我用标准化同意,如果作者确实看起来它:)我回答的讨论之前出现,因此,如果这一个可能删除我的答案是正确的:)[0,1]
Dmitrij Celov 2011年

1
如果有人担心离群值,可以考虑使用中位数绝对偏差(相对于中位数)而不是标准偏差。在R中,使用mad()功能。而且,如果担心偏斜,可以使用数据的等级代替原始观察值。在R中,这将是rank(),但是如果要在新数据上使用它,ecdf()则将是一个更好的选择(ecdf(x)返回一个新函数,该函数基本上将值赋予xp分位数,例如0(真的1 / n)到x的最小值,1到最大值,0.5到中位数等)ppx1/nx1
Karl Ove Hufthammer 2015年

10

任何S型函数都可以工作:


erf不是一个非常方便的函数,只要您不希望将其用于其派生。

我最终使用了一个简单的逻辑函数,并进行了一些小调整:(1 /(1 + java.lang.Math.exp(-1 *(factor * i)))-0.5)*2。我选择了0.05作为似乎对于0到几百之间的我来说效果很好。
吉尔·范古普(Jilles van Gurp)

1.0 /(1.0 + exp(-1.69897 *(x-mean(x))/ sd(x)))非常接近于pnorm
Chris

3

除了Henrik和Simon Byrne的好建议之外,您还可以使用f(x)= x /(x + 1)。通过比较,随着x的增大,逻辑函数会夸大差异。也就是说,使用逻辑函数时,f(x)和f(x + 1)之间的差异将大于使用f(x)= x /(x + 1)时的差异。您可能想要也可能不想要这种效果。



1

要添加其他建议建议的答案...

对于选择参数的潜在最佳方法,我建议对Pnorm采用这种近似方法。

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

讨厌的

这本质上是Softmax规范化。

参考 Pnorm在紧要关头


1

我通常使用两种方法来实现此目的。我一直在处理实时数据,因此这里假定连续输入。这是一些伪代码:

使用可训练的minmax:

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]

此功能要求您要么执行初始训练阶段(使用calibrate()),要么以一定间隔或根据特定条件进行重新训练。例如,想象一个像这样的函数:

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

峰值和谷值通常不接收值,但是如果outBounds()接收到的值大于当前峰值的1.5倍或小于当前谷值除以1.5,则将calibrate()被调用,这将允许该函数自动重新校准。

使用历史最小值:

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

对于第一个示例,这可以全部在Max / MSP / Jitter中实现,使用[peak]和[trough]对象;对于第二个示例,可以使用[jit.3m]来实现。
露台

0

一个非常简单的选项是将数据中的每个数字除以数据中的最大数字。如果您有很多小数字,有几个非常大的数字,则可能无法很好地传达信息。但这比较容易。如果您认为在以这种方式绘制数据时丢失了有意义的信息,则可以尝试其他人建议的一种更复杂的技术。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.