2014-08-27 73 views
2

我正在研究一个脚本,它是这样的:程序分析一些文本文件在一定的语言,绘制每个k的概率分布,其中k是第一个字符出现在文本的每个字母中的每个给定字母的后面。然后该程序使用这些知识尝试和使用马尔可夫链书写“真实”的单词。概率分布和浮点型变量,概率必须加1 1

我已经写了大部分的脚本,它已经吐出了有趣的单词,关键是生成单词的函数正在尝试和除了机制,以避免卡住。它被卡住了,因为一些概率分布不加到1(我猜是因为float类型不是那么精确或类似的东西),应该与这些分布一起工作的numpy函数引发了一个ValueError,因为概率不等于1

通过触发某些发行版的例外情况,根本不会生成某些单词,最终结果不如它可能的有趣。

现在,我的问题是:有没有办法让这些概率分布在生成时加起来为1? 我试过gmpy2,round()函数,但似乎没有人工作。也许这是一个愚蠢的问题,我只需要得到一些新鲜空气...无论如何,一些帮助将是有用的!

这里是概率分布

def FreqRel(self,listValues): 
    absFreq = self.AbsFreq(listValues) 
    freqRel = [] 
    for i in absFreq: 
     freqRel.append(i/sum(absFreq)) 
    if sum(freqRel) != 1: 
     print("Frequencies do not add up to 1") 
     if sum(freqRel) - 1 < 0: 
      diff = sum(freqRel) - 1 
      #This should be an adjustment which should not interfere 
      #that much on the probability distribution 
      freqRel[1] = freqRel[1] - diff 
      print("missing",diff) 
     elif sum(freqRel) - 1 > 0: 
      diff = sum(freqRel) - 1 
      #This should be an adjustment which should not interfere 
      #that much on the probability distribution 
      freqRel[1] = freqRel[1] - diff 
      print("Too much",diff) 
    return freqRel 

这里产生的代码是运行此功能时,我得到印在控制台上的内容: enter image description here

enter image description here

这里是当总和不是1时崩溃的代码。numpy行是崩溃的thos。 和错误是:ValueError异常:概率加起来还不到1

def spitText(n): 
    i = 0 
    while i < n: 
     try: 
      word = "" 
      #This oldChar setting is arbitrary, later I'm going to fix it 
      oldChar = "b" 
      for k in range(np.random.choice(distributions[0],replace=True,p=distributions[1])): 
       newChar = np.random.choice(alphabet,replace=True,p=distRel[alphabet.index(oldChar)]) 
       word = word + newChar 
       oldChar = newChar 
      print(word) 
      time.sleep(0.2) 
      i+=1 
     except: 
      pass 
+0

你的freqAss是什么?它起源于哪里? – greole 2014-08-27 09:01:54

+0

对不起,它应该是absFreq而不是freqAss。这是一个错字。刚刚编辑,谢谢! – mickkk 2014-08-27 09:03:56

+0

你能向我们展示当总和不是1时崩溃的代码吗? – parchment 2014-08-27 09:08:27

回答

4

你有一些输出,看起来像这样:

1.0 
1.0 
1.0 
0 
1.0 
1.0 

从评论:

that's a simple for loop outside this function that prints out the sum of each distribution stored as a returned value from this function

所以,你的一些频率分布总和为0。那是你的问题。

假设你的代码建立分布有一些边界情况,要么返回一个空的分布,要么全部为零。无论哪种方式,显然不会起作用。


事实上,许多这些1.0值是关闭由多达8E-17的累积舍入误差是一个红色的鲱鱼。你可以看到,numpy的是建立在处理这些:

>>> np.random.choice(2, 3, p=[0.4, 0.6+3e-17]) 
array([1, 0, 0]) 

只有当错误变得足够大(对于大多数numpy的默认相对小量是1E-5),它抱怨:

>>> np.random.choice(2, 3, p=[0.4, 0.6+3e-5]) 
ValueError: probabilities do not sum to 1 

所以你必须有一些概率分布,其总和超过1大于1e-5。当然你也可以;你有一些整个1


这意味着你的主要问题:

is there a way to make these probability distributions add up to 1 when they are generated?

...真是XY problem:这不是你需要在这里解决的事情。

但我会回答它。简短的答案是:否。浮点数是具有固定数字精度的二进制分数。如果您尝试在浮点数中存储任意实数,则会出现舍入错误。你可以很容易地看到这一点:

>>> 1.0 + 1e-17 
1.0 

那里只是没有足够的位来存储1.01.00000000000000001不同的二进制小数。

如果您想进一步了解(而且您应该),请阅读有关该主题的经典介绍性文章What every computer scientist should know about floating point

+0

就是这样!一些字母根本不出现,因此它们的分布总和为0,从而在采样时导致错误。我怀疑这是一件愚蠢的事......谢谢abarnert!我将检查纸张! – mickkk 2014-08-27 09:38:27

+0

@mickkk:我想到了这样的事情。大多数错误都是由你从未想过的简单边缘情况引起的,但是一旦你知道寻找它们,这些情况就很明显。 (呃,那些愚蠢的错别字,我无法看到我自己的代码,不管我盯着它多么努力......)你不高兴计算机科学不是你的主要领域吗? :) – abarnert 2014-08-27 09:46:18

+0

+1很棒! @mickkk:你可以尝试[拉普拉斯平滑](http://en.wikipedia.org/wiki/Laplace_smoothing)来解决这个问题。 – 2014-08-27 10:00:35