我想将变量表示为0到1之间的数字。该变量是一个非负整数,没有固有界限。我将0映射到0,但是我可以映射到1或0到1之间的数字呢?
我可以使用该变量的历史记录来提供限制。这意味着如果最大值增加,我必须重述旧的统计信息。我需要这样做还是应该知道其他技巧?
我想将变量表示为0到1之间的数字。该变量是一个非负整数,没有固有界限。我将0映射到0,但是我可以映射到1或0到1之间的数字呢?
我可以使用该变量的历史记录来提供限制。这意味着如果最大值增加,我必须重述旧的统计信息。我需要这样做还是应该知道其他技巧?
Answers:
这样做的一个很常见的技巧(例如,在连接主义建模中)是使用双曲正切tanh作为“挤压函数”,它会自动将所有数字拟合为-1和1之间的间隔。 0到1。在中r
,matlab
您可以通过获得它tanh()
。
另一个压扁函数是逻辑函数(感谢Simon的名字),由,该函数将范围限制为0到1(0映射为.5)。因此,您必须将结果乘以2并减去1才能使数据适合0到1之间的区间。
这是一些简单的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")
通常,我的第一个问题是“ 您为什么要这样做”,然后我看到您已经在对该问题的评论中回答了这一问题:“ 我正在跨多个维度测量内容,并且我希望能够根据给定内容的相关性进行比较。此外,我希望在这些维度上显示清晰易懂的值。 ”
没有理由将数据标准化以使max为1且min为零以实现此目的,而我认为这通常是个坏主意。最大值或最小值很容易成为无法代表总体分布的异常值。@osknows关于使用 -scores的分词是一个更好的主意。分数(也称为标准分数)使用其标准偏差而不是其范围对每个变量进行归一化。标准偏差受异常值的影响较小。为了使用z-scores,每个变量最好具有大致正态分布,或者至少具有大致对称分布(即不严重偏斜),但是如有必要,您可以首先应用一些适当的数据转换以实现此目的;可以通过找到最合适的Box-Cox转换来确定要使用的转换。
mad()
功能。而且,如果担心偏斜,可以使用数据的等级代替原始观察值。在R中,这将是rank()
,但是如果要在新数据上使用它,ecdf()
则将是一个更好的选择(ecdf(x)
返回一个新函数,该函数基本上将值赋予x的p分位数,例如0(真的1 / n)到x的最小值,1到最大值,0.5到中位数等)
除了Henrik和Simon Byrne的好建议之外,您还可以使用f(x)= x /(x + 1)。通过比较,随着x的增大,逻辑函数会夸大差异。也就是说,使用逻辑函数时,f(x)和f(x + 1)之间的差异将大于使用f(x)= x /(x + 1)时的差异。您可能想要也可能不想要这种效果。
我之前的帖子提供了一种在0到1之间进行排名的方法。有关分类器输入相关性的建议
但是,我使用的排名Tmin / Tmax使用样本min / max,但您可能会发现总体min / max更合适。还查找z分数
要添加其他建议建议的答案...
对于选择参数的潜在最佳方法,我建议对Pnorm采用这种近似方法。
1.0/(1.0+exp(-1.69897*(x-mean(x))/sd(x)))
这本质上是Softmax规范化。
参考 Pnorm在紧要关头
我通常使用两种方法来实现此目的。我一直在处理实时数据,因此这里假定连续输入。这是一些伪代码:
使用可训练的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