2016-11-02 15 views
8

norvig.com/big.txt से को देखते हुए, लक्ष्य बड़े पैमाने पर गिनती को गिनना है (कल्पना कीजिए कि मुझे यह गणना 100,000 बार दोहराना है)।बिग्राम को वास्तविक तेज़ी से (मल्टीप्रोसेसिंग के साथ या बिना) की गणना करना - पायथन

Fast/Optimize N-gram implementations in python के अनुसार

, इस तरह Bigrams निकालने सबसे इष्टतम होगा:

_bigrams = zip(*[text[i:] for i in range(2)]) 

और अगर मैं Python3 उपयोग कर रहा हूँ, जनरेटर का मूल्यांकन नहीं किया जाएगा जब तक मैं list(_bigrams) या कुछ अन्य कार्यों के साथ यह अमल में लाना वह वही करेगा।

import io 
from collections import Counter 

import time 
with io.open('big.txt', 'r', encoding='utf8') as fin: 
    text = fin.read().lower().replace(u' ', u"\uE000") 

while True: 
    _bigrams = zip(*[text[i:] for i in range(2)]) 
    start = time.time() 
    top100 = Counter(_bigrams).most_common(100) 
    # Do some manipulation to text and repeat the counting. 
    text = manipulate(text, top100)  

लेकिन प्रति पुनरावृत्ति के लगभग 1+ सेकंड लगते हैं, और 100,000 पुनरावृत्तियों बहुत लंबे होंगे।

मैंने sklearn काउंटर वेक्टरोरिज़र भी कोशिश की है, लेकिन निकालने का समय, गिनने और शीर्ष 100 bigrams प्राप्त करने के लिए देशी पायथन के बराबर हैं।

तो मैं कुछ multiprocessing के साथ प्रयोग किया गया है, Python multiprocessing and a shared counter और http://eli.thegreenplace.net/2012/01/04/shared-counter-with-pythons-multiprocessing से मामूली संशोधन का उपयोग करते हुए:

from multiprocessing import Process, Manager, Lock 

import time 

class MultiProcCounter(object): 
    def __init__(self): 
     self.dictionary = Manager().dict() 
     self.lock = Lock() 

    def increment(self, item): 
     with self.lock: 
      self.dictionary[item] = self.dictionary.get(item, 0) + 1 

def func(counter, item): 
    counter.increment(item) 

def multiproc_count(inputs): 
    counter = MultiProcCounter() 
    procs = [Process(target=func, args=(counter,_in)) for _in in inputs] 
    for p in procs: p.start() 
    for p in procs: p.join() 
    return counter.dictionary 

inputs = [1,1,1,1,2,2,3,4,4,5,2,2,3,1,2] 

print (multiproc_count(inputs)) 

लेकिन बाइग्राम गिनती में MultiProcCounter का उपयोग कर भी लंबे समय तक यात्रा प्रति 1+ सेकंड से ले जाता है। मुझे नहीं पता कि यह मामला क्यों है, int उदाहरण की डमी सूची का उपयोग करते हुए, multiproc_count पूरी तरह से काम करता है।

मैं कोशिश की है:

import io 
from collections import Counter 

import time 
with io.open('big.txt', 'r', encoding='utf8') as fin: 
    text = fin.read().lower().replace(u' ', u"\uE000") 

while True: 
    _bigrams = zip(*[text[i:] for i in range(2)]) 
    start = time.time() 
    top100 = Counter(multiproc_count(_bigrams)).most_common(100) 

वहाँ पायथन में वास्तव में तेजी से Bigrams गिनती करने के लिए कोई तरीका है?

+0

लगता है जैसे आपको वितरित प्रसंस्करण और मानचित्र/कम करना चाहिए यदि आप वास्तव में 100,000 बार एक ही काम करने से नहीं बच सकते हैं। मुझे लगता है कि आपका मतलब है कि आपके पास डेटा भी बड़ा है, न कि आप सचमुच समान गणना को 100,000 बार दोहराते हैं; यदि यह वास्तव में आपका मतलब है, तो ऐसा लगता है कि आपकी मूल योजना में कोई दोष है। – tripleee

+0

यह 100,000 बार एक ही चीज़ दोहरा रहा है लेकिन हर बार, यह शीर्ष 100 bigrams लेता है और पाठ में हेरफेर करता है, इसलिए प्रत्येक पुनरावृत्ति पर bigrams निकालने के लिए इनपुट पाठ अलग है। – alvas

+0

क्या आप बड़े 20 पहले बड़े मानते हैं।txt होना ['th', 'he', 'e', ​​'p', 'pr', 'ro', 'oj', 'je', 'ec', 'ct', 't', 'g ',' gu ',' ut ',' te ',' en ',' nb ',' be ',' er ',' rg '] जैसे आपका कोड उत्पन्न होता है, या शब्द-उन्मुख सबसेट जैसे [' th ' , 'हे', 'पीआर', 'आरओ', 'ओज', 'जे', 'ईसी', 'सीटी', 'gu', 'ut', 'te', 'en', 'nb', ' हो ',' एर ',' आरजी ',' ईबी ',' बो ',' ओओ ',' ओके ']? बस खेल के नियमों को समझने की कोशिश कर रहा है। – cdlane

उत्तर

0

मेरा प्रस्ताव है कि:

Text= "The Project Gutenberg EBook of The Adventures of Sherlock Holmes" 
"by Sir Arthur Conan Doyle" 

# Counters 
Counts= [[0 for x in range(128)] for y in range(128)] 

# Perform the counting 
R= ord(Text[0]) 
for i in range(1, len(Text)): 
    L= R; R= ord(Text[i]) 
    Counts[L][R]+= 1 

# Output the results 
for i in range(ord('A'), ord('{')): 
    if i < ord('[') or i >= ord('a'): 
     for j in range(ord('A'), ord('{')): 
      if (j < ord('[') or j >= ord('a')) and Counts[i][j] > 0: 
       print chr(i) + chr(j), Counts[i][j] 


Ad 1 
Bo 1 
EB 1 
Gu 1 
Ho 1 
Pr 1 
Sh 1 
Th 2 
be 1 
ck 1 
ct 1 
dv 1 
ec 1 
en 2 
er 2 
es 2 
he 3 
je 1 
lm 1 
lo 1 
me 1 
nb 1 
nt 1 
oc 1 
of 2 
oj 1 
ok 1 
ol 1 
oo 1 
re 1 
rg 1 
rl 1 
ro 1 
te 1 
tu 1 
ur 1 
ut 1 
ve 1 

इस संस्करण केस संवेदी है; पहले पूरे पाठ को कम करने के लिए शायद बेहतर है।

+0

यह मानते हुए कि वर्णों की संख्या तय की गई है, नहीं? – alvas

+0

@alvas: वर्णों की संख्या कितनी है? –

+0

मेरा मतलब है 'गणना = [[0 के लिए निश्चित सरणी सूची एक्स इन रेंज (128)] वाई इन रेंज (128)] ' – alvas

1
import os, thread 

text = 'I really like cheese' #just load whatever you want here, this is just an example 

CORE_NUMBER = os.cpu_count() # may not be available, just replace with how many cores you have if it crashes 

ready = [] 
bigrams = [] 

def extract_bigrams(cores): 
    global ready, bigrams 
    bigrams = [] 
    ready = [] 
    for a in xrange(cores): #xrange is best for performance 
     bigrams.append(0) 
     ready.append(0) 
    cpnt = 0#current point 
    iterator = int(len(text)/cores) 
    for a in xrange(cores-1): 
     thread.start_new(extract_bigrams2, (cpnt, cpnt+iterator+1, a)) #overlap is intentional 
     cpnt += iterator 
    thread.start_new(extract_bigrams2, (cpnt, len(text), a+1)) 
    while 0 in ready: 
     pass 

def extract_bigrams2(startpoint, endpoint, threadnum): 
    global ready, bigrams 
    ready[threadnum] = 0 
    bigrams[threadnum] = zip(*[text[startpoint+i:endpoint] for i in xrange(2)]) 
    ready[threadnum] = 1 

extract_bigrams(CORE_NUMBER) 
thebigrams = [] 
for a in bigrams: 
    thebigrams+=a 

print thebigrams 

वहाँ है जैसे कि यह खाली स्थान या विराम चिह्न को छान नहीं, तो इस कार्यक्रम के साथ कुछ मुद्दों कर रहे हैं, लेकिन मैं दिखाने के लिए आप के लिए क्या शूटिंग की जानी चाहिए इस कार्यक्रम बनाया है। आप अपनी आवश्यकताओं के अनुरूप इसे आसानी से संपादित कर सकते हैं।

यह प्रोग्राम ऑटो-डिटेक्ट करता है कि आपके कंप्यूटर के कितने कोर हैं, और उन धागे की संख्या बनाते हैं, जहां बड़े पैमाने पर उन क्षेत्रों को समान रूप से वितरित करने का प्रयास किया जाता है। मैं केवल स्कूल के स्वामित्व वाले कंप्यूटर पर ऑनलाइन कोड में इस कोड का परीक्षण करने में सक्षम हूं, इसलिए मैं निश्चित नहीं हो सकता कि यह पूरी तरह से काम करता है। अगर कोई समस्या या प्रश्न हैं, तो कृपया उन्हें टिप्पणियों में छोड़ दें।

+0

मैं आपके थ्रेडेड दृष्टिकोण की सराहना करता हूं - थ्रेडिंग से पहले डेटा फ़िल्टरिंग और केस फोल्डिंग जैसी चीजें होती हैं, इसलिए प्रदर्शन लाभ को महत्वपूर्ण रूप से प्रभावित नहीं किया जाएगा। हालांकि, आपका समाधान वास्तव में बड़े पैमाने पर नहीं है - एक बार थ्रेड पूर्ण होने पर, मुख्य कार्यक्रम को सभी गिनतियों को मर्ज करना होगा जो एक जटिलता है कि सिंगल थ्रेडेड समाधान का सामना नहीं करना पड़ता है। एक और पूर्ण उदाहरण के बिना, यह जानना मुश्किल है कि क्या अतिरिक्त ओवरहेड संभावित लाभ को अस्वीकार कर सकता है। – cdlane

+0

क्या आपने इसे 'big.txt' बनाम देशी पायथन गैर-थ्रेडेड/गैर-मल्टीप्रोसेसिंग दृष्टिकोण बनाकर बेंचमार्क करने का प्रयास किया था? – alvas

संबंधित मुद्दे