【问题标题】:Normalizing an iterable type such that the output is an iterable of floats whose sum is 1规范化可迭代类型,使得输出是总和为 1 的浮点数的可迭代
【发布时间】:2012-07-15 22:37:31
【问题描述】:

好的,

我遇到了一个舍入错误问题。我有一个 java 程序,它逐行读取一些数字列表。该程序要求此列表为浮点数(什么类型的浮点数?我怀疑是单精度)数字,其总和 S 在 0.999 和 1.001 之间(即 .999

from numpy import array, linalg

def Normalize(X):
    NumpyX = array(X)
    Norm = linalg.norm(NumpyX)
    Normalize = NumpyX/Norm
    return Normalize

def FileMaker(FilePointer,Vector)
    for i in Vector:
        FilePointer.write('%f\n'%i)
    return


#sum(SubstitutionPoints) does not add to 1
SubstitutionPoints =[0.00606508512067950,0.00675296642376962,0.00688999694872917,0.00580692396866418,0.00680583604896024,0.00609061670962565,0.00585881991631447,0.00577148570812953,0.00600882981888663,0.00618499536435559,0.00650767341787896,0.00670521809234427,0.00699374780209504,0.00841141135948587,0.00830145870238677,0.00879477131238090,0.00918627324146331,0.00958946761973615,0.01032404247887830,0.01093417870737930,0.01188202458790520,0.01261860720648550,0.01355451051017660,0.01473818756656830,0.01623978223562570,0.01811682034513980,0.01990010225231130,0.02154250858435480,0.02418185925226890,0.02583490296173980,0.02844212438633430,0.03194935989118780,0.03534228607419560,0.03971366519834600,0.04548573525944540,0.05190994307855660,0.05190994307855660,0.05190994307855660,0.05190994307855660,0.05190994307855660,0.05190994307855660,0.05190994307855660,0.05190994307855660,0.05190994307855660,0.05190994307855660,0.05190994307855660,0.05190994307855660,0.05190994307855660,0.05190994307855660,0.05190994307855660,0.05190994307855660,0.05190994307855660,0.05190994307855660,0.05190994307855660,0.05190994307855660,0.05190994307855660,0.05190994307855660,0.05190994307855660,0.05190994307855660,0.05190994307855660,0.05190994307855660,0.05190994307855660,0.05190994307855660,0.05190994307855660,0.05190994307855660,0.05190994307855660,0.05190994307855660,0.05190994307855660,0.05190994307855660,0.05190994307855660,0.05190994307855660,0.05190994307855660,0.05190994307855660,0.05190994307855660,0.05190994307855660,0.05190994307855660,0.05190994307855660,0.05190994307855660,0.05190994307855660,0.05190994307855660,0.05190994307855660,0.05190994307855660,0.05190994307855660,0.05190994307855660,0.05190994307855660,0.05190994307855660,0.05190994307855660,0.05190994307855660,0.05190994307855660,0.05190994307855660,0.05190994307855660,0.05190994307855660,0.05190994307855660,0.05190994307855660,0.05190994307855660,0.05190994307855660,0.05190994307855660,0.05190994307855660,0.05190994307855660,0.05190994307855660,0.05190994307855660]
NormedSP = Normalize(SubstitutionPoints)
SubFile = open('Sub.txt','w')
FileMaker(SubFile,NormedSP)
SubFile.close()

由于python不使用单精度浮点数,我担心创建的文件会导致我的java程序出现问题,因为我的java程序(metasim)返回错误:

Simulating files:
[BorreliaBurgdorferiB31_CP32-3.fasta]
java.lang.Exception: Substitution rates don't sum to 1.0.
!!! FAILED !!!

不幸的是,我无法调试 java 程序,因为它是“java 可执行文件”。我唯一的选择是提供正确的输入。

感谢任何建议/帮助。

编辑

从尝试 float32() 的一些建议中,我修改了我的 normalize 方法:

def Normalize(self,X):
    Total = sum(X)
    NumpyX = array([float32(i) for i in X])
    Norm = linalg.norm(NumpyX,ord=1)
    Normalize = NumpyX/Norm
    return Normalize

我开始怀疑这是单精度浮点问题。

我的输出是否被截断并导致错误?

【问题讨论】:

  • 我不知道是谁一直在删除答案,但这真的很烦人!我非常感谢所有建议。把它们都作为参考就好了。
  • 我要感谢 serndele(我认为那是他的名字)的建议、Daniel Pryden 和其他人(Ivan??)的 cmets

标签: java python floating-point


【解决方案1】:

numpy.linalg.norm 需要 ord=1 关键字 arg 来执行您期望的操作。使用您当前的数据和定义...

>>> Normalize(substitution_points).sum()
9.0451896403987444

您可以改为这样做 - 这也可以正确缩放负值(linalg.norm 将值的 abs 相加):

>>> def normalize(x):
...     a = numpy.array(x)
...     return a / a.sum()
... 
>>> normalize(substitution_points).sum()
0.99999999999999789

0.9999999... > 0.999,所以它应该工作,根据你提供的规范。

但是......它似乎仍然无法正常工作。尝试使用numpy.float16 -- 并注意创建浮点数组的更惯用方法如下:

array([ 0.,  1.,  2.,  3.,  4.], dtype=float32)

【讨论】:

  • 哎呀我的意思是 Norm = linalg.norm(NumpyX,ord=1)
  • @torrho,哦。那么这是否意味着简单的除法对你不起作用?或者这只是您的示例代码中的一个错字? (我没想到你可能会使用linalg.norm 来计算曼哈顿距离。)
  • 错字不是问题。我也尝试使用 float32。我想知道这不是问题吗?也许别的什么?任何想法
  • 或者,如果这不起作用,那么正如@Ignacio Vazquez-Abrams 在他已删除的帖子中所说,“你唯一真正的解决方法是将归一化值相加,将差异添加到最后一个元素,并交叉你的手指。”伊格纳西奥,你应该取消删除!
  • 好的,我会试试 float16。如果失败了,我会尝试将差异添加到向量的第一个元素(这对我的模型来说更好)
【解决方案2】:

您的 Normalize 方法不会强制列表的总和为 1:除以范数会将 norm 设置为 1。要将总数设置为 1,您需要除以当前总计:

def normalize(X):
   total = sum(X)
   return [x/total for x in X]

【讨论】:

    【解决方案3】:

    如果您只需要精确到小数点后三位,为什么不将这些值乘以 1000,用整数进行所有数学运算,然后只在输出中添加小数点?这样应该很容易确保总和是准确的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-09-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-13
      • 2023-02-20
      • 2021-07-14
      相关资源
      最近更新 更多