2014-08-27 100 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