我正在使用HashTable包在Haskell中编写Bayes naive分类器。然而,当处理更大的语料库时,我有大量的内存泄漏可能是由大量的值更新引起的。当加载已经指定的字数时,它需要大约2GB的RAM,但是当计算来自语料库的单词出现时,8GB的ram是不够的,它只是崩溃。我怎么能阻止它?代码计数字样如下:
chars :: T.Text
chars = "qwertyuiopasdfghjklzxcvbnmęóąśłżźćń\t "
el :: Char -> T.Text -> Bool
el = T.any . (==)
preprocess :: T.Text -> [T.Text]
preprocess !line = T.words . T.map check . T.toLower $ line
where check !x = if x `el` chars then x else ' '
loop :: Handle -> Corpus -> IO ()
loop hdl dic =
hIsEOF hdl >>= \x -> if x
then return ()
else do
cl:dat <- preprocess <$> TIO.hGetLine hdl
let ins !word =
if (T.length word <= 20) && (T.length word >= 4)
then (H.lookup dic word >>=
\mprob -> case mprob of
Just (SexProbs m f) -> do
H.delete dic word
H.insert dic word $ if cl == "m" then SexProbs (m+1) f else SexProbs m (f+1)
Nothing -> H.insert dic word $ if cl == "m" then SexProbs 1 0 else SexProbs 0 1)
else return ()
mapM_ ins dat
loop hdl dic
分析表明最大的分配来源是预处理和循环,但我不知道如何减少内存使用。
答案 0 :(得分:1)
原因似乎是您的SexProbs
数据类型。它可能用惰性字段定义,即(假设计数器为Int
):
data SexProbs = SexProbs Int Int
使用SexProbs (m+1) n
构造新值将不评估添加,但将thunk放入堆内存中。这些累积并导致空间泄漏。
为避免这种情况,请使用seq
let m' = m+1 in m' `seq` SexProbs m' n
或更改您的类型定义以使用严格字段:
data SexProbs = SexProbs !Int !Int