我正要測試樸素貝葉斯分類。其中一部分將構建訓練數據的直方圖。問題在於,我使用了大量的訓練數據,幾年前的haskell-cafe郵件列表,並且該文件夾中有超過20k個文件。用haskell建立直方圖,比python慢了許多倍
用python創建直方圖需要花費兩分多鐘的時間,而使用haskell需要8分多鐘。我正在使用Data.Map(insertWith'),枚舉器和文本。我還能做些什麼來加速該計劃?
哈斯克爾:
import qualified Data.Text as T
import qualified Data.Text.IO as TI
import System.Directory
import Control.Applicative
import Control.Monad (filterM, foldM)
import System.FilePath.Posix ((</>))
import qualified Data.Map as M
import Data.Map (Map)
import Data.List (foldl')
import Control.Exception.Base (bracket)
import System.IO (Handle, openFile, hClose, hSetEncoding, IOMode(ReadMode), latin1)
import qualified Data.Enumerator as E
import Data.Enumerator (($$), (>==>), (<==<), (==<<), (>>==), ($=), (=$))
import qualified Data.Enumerator.List as EL
import qualified Data.Enumerator.Text as ET
withFile' :: (Handle -> IO c) -> FilePath -> IO c
withFile' f fp = do
bracket
(do
h ← openFile fp ReadMode
hSetEncoding h latin1
return h)
hClose
(f)
buildClassHistogram c = do
files ← filterM doesFileExist =<< map (c </>) <$> getDirectoryContents c
foldM fileHistogram M.empty files
fileHistogram m file = withFile' (λh → E.run_ $ enumHist h) file
where
enumHist h = ET.enumHandle h $$ EL.fold (λm' l → foldl' (λm'' w → M.insertWith' (const (+1)) w 1 m'') m' $ T.words l) m
的Python:
for filename in listdir(root):
filepath = root + "/" + filename
# print(filepath)
fp = open(filepath, "r", encoding="latin-1")
for word in fp.read().split():
if word in histogram:
histogram[word] = histogram[word]+1
else:
histogram[word] = 1
編輯:增加進口
什麼樣的容器是Python中的「直方圖」?使用哈希映射而不是基於樹的哈希映射肯定是合理的。 – leftaroundabout 2012-03-19 15:18:31
只是基本的字典。我也嘗試了無序容器的HashMap,但速度減慢了,gc時間增加了。 – Masse 2012-03-19 15:20:04
你用-O2編譯過嗎?它造就了一個不同的世界。 – 2012-03-19 15:30:37