Stavo andando a testare la classificazione bayes naive. Una parte di questo stava per costruire un istogramma dei dati di allenamento. Il problema è che sto usando una grande quantità di dati di addestramento, la mailing list haskell-cafe da un paio di anni fa, e ci sono oltre 20k file nella cartella.Costruire un istogramma con haskell, molte volte più lento che con python
Ci vuole un po 'più di due minuti per creare l'istogramma con python e poco più di 8 minuti con haskell. Sto usando Data.Map (insertWith '), enumeratori e testo. Cos'altro posso fare per accelerare il programma?
Haskell:
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
Edit: importazioni aggiunti
Che tipo di contenitore è 'istogramma' in Python? Potrebbe certamente essere ragionevole usare una mappa hash piuttosto che una basata sull'albero. – leftaroundabout
Solo il dettato di base. Ho anche provato HashMap da contenitori non ordinati, ma la velocità è diminuita e il tempo gc è aumentato. – Masse
Hai compilato con -O2? Fa un mondo di differenza. –