6

में एक से अधिक डेटास्टोर प्रकार पर मैपराइडस मैंने Batch data processing with App Engine session of Google I/O 2010 देखा, MapReduce article from Google Research के कुछ हिस्सों को पढ़ें और अब मैं पाइथन में एक अनुशंसा प्रणाली को लागू करने के लिए MapReduce on Google App Engine का उपयोग करने के बारे में सोच रहा हूं।Google App Engine

मैं कार्य कतार एपीआई के बजाय एपेंगिन-मैप्रेडस का उपयोग करना पसंद करता हूं क्योंकि पूर्व किसी प्रकार, स्वचालित बैचिंग, स्वचालित कार्य श्रृंखला आदि के सभी उदाहरणों पर आसान पुनरावृत्ति प्रदान करता है। समस्या यह है कि: मेरे अनुशंसाकर्ता प्रणाली को उदाहरणों के बीच सहसंबंध की गणना करने की आवश्यकता है दो अलग-अलग मॉडल, यानी, दो अलग-अलग प्रकार के उदाहरण।

उदाहरण: मेरे पास इन दो मॉडल हैं: उपयोगकर्ता और आइटम। प्रत्येक में एक विशेषता के रूप में टैग की एक सूची है। उपयोगकर्ताओं और वस्तुओं के बीच सहसंबंध की गणना करने के लिए कार्य नीचे दिए गए हैं। ध्यान दें कि calculateCorrelation उपयोगकर्ताओं और आइटम के प्रत्येक संयोजन के लिए बुलाया जाना चाहिए:

def calculateCorrelation(user, item): 
    return calculateCorrelationAverage(u.tags, i.tags) 

def calculateCorrelationAverage(tags1, tags2): 
    correlationSum = 0.0 
    for (tag1, tag2) in allCombinations(tags1, tags2): 
     correlationSum += correlation(tag1, tag2) 
    return correlationSum/(len(tags1) + len(tags2)) 

def allCombinations(list1, list2): 
    combinations = [] 
    for x in list1: 
     for y in list2: 
      combinations.append((x, y)) 
    return combinations    

लेकिन उस calculateCorrelation appengine-mapreduce में एक वैध मैपर नहीं है और हो सकता है इस समारोह MapReduce गणना अवधारणा के साथ भी संगत नहीं है। फिर भी, मुझे यह सुनिश्चित करने की ज़रूरत है कि मेरे लिए स्वचालित बैचिंग और कार्य श्रृंखला जैसे ऐपेंजिन-मैप्रिडस फायदे होने के लिए यह वास्तव में बहुत अच्छा होगा।

क्या इसके लिए कोई समाधान है?

क्या मुझे अपना खुद का इनपुट रीडर परिभाषित करना चाहिए? एक नया इनपुट रीडर जो दो अलग-अलग प्रकार के सभी उदाहरण पढ़ता है, वर्तमान एपेंगेन-मैप्रिडस कार्यान्वयन के साथ संगत है?

या मुझे निम्नलिखित का प्रयास करना चाहिए?

  • दो द्वारा दो इन दो प्रकार की सभी संस्थाओं के सभी चाबियाँ कम्बाइन, एक नया मॉडल के उदाहरण (संभवतः का उपयोग कर MapReduce) में,
  • दोहराएं इस नए मॉडल
  • के उदाहरण से प्रत्येक के लिए खत्म हो गया मानचित्रकारों का उपयोग कर उदाहरण के लिए, विभिन्न प्रकार की दो इकाइयों को प्राप्त करने और उनके बीच सहसंबंध की गणना करने के लिए इसके अंदर कुंजियों का उपयोग करें।
+0

क्या मानदंड उपयोगकर्ता और आइटम में पारित करने के लिए कर रहे हैं? क्या यह उपयोगकर्ता और वस्तु का हर संयोजन है? बस कुछ जो किसी तरह से संबंधित हैं? इसके अलावा, वह भाषा क्या है? यह (काफी) पायथन नहीं है! –

+0

'गणना गणना' उपयोगकर्ता और आइटम के प्रत्येक संयोजन के लिए बुलाया जाना चाहिए। और अब मैंने भ्रम से बचने के लिए चर के प्रकार हटा दिए हैं। – fjsj

उत्तर

3

निक जॉनसन सुझाव के बाद, मैंने अपना खुद का इनपुट रीडर लिखा। यह पाठक दो अलग-अलग प्रकार से इकाइयों को लाता है। यह इन इकाइयों के सभी संयोजनों के साथ tuples पैदा करता है। संदेश यह है:

class TwoKindsInputReader(InputReader): 
    _APP_PARAM = "_app" 
    _KIND1_PARAM = "kind1" 
    _KIND2_PARAM = "kind2" 
    MAPPER_PARAMS = "mapper_params" 

    def __init__(self, reader1, reader2): 
     self._reader1 = reader1 
     self._reader2 = reader2 

    def __iter__(self): 
     for u in self._reader1: 
      for e in self._reader2: 
       yield (u, e) 

    @classmethod 
    def from_json(cls, input_shard_state): 
     reader1 = DatastoreInputReader.from_json(input_shard_state[cls._KIND1_PARAM]) 
     reader2 = DatastoreInputReader.from_json(input_shard_state[cls._KIND2_PARAM]) 

     return cls(reader1, reader2) 

    def to_json(self): 
     json_dict = {} 
     json_dict[self._KIND1_PARAM] = self._reader1.to_json() 
     json_dict[self._KIND2_PARAM] = self._reader2.to_json() 
     return json_dict 

    @classmethod 
    def split_input(cls, mapper_spec): 
     params = mapper_spec.params 
     app = params.get(cls._APP_PARAM) 
     kind1 = params.get(cls._KIND1_PARAM) 
     kind2 = params.get(cls._KIND2_PARAM) 
     shard_count = mapper_spec.shard_count 
     shard_count_sqrt = int(math.sqrt(shard_count)) 

     splitted1 = DatastoreInputReader._split_input_from_params(app, kind1, params, shard_count_sqrt) 
     splitted2 = DatastoreInputReader._split_input_from_params(app, kind2, params, shard_count_sqrt) 
     inputs = [] 

     for u in splitted1: 
      for e in splitted2: 
       inputs.append(TwoKindsInputReader(u, e)) 

     #mapper_spec.shard_count = len(inputs) #uncomment this in case of "Incorrect number of shard states" (at line 408 in handlers.py) 
     return inputs 

    @classmethod 
    def validate(cls, mapper_spec): 
     return True #TODO 

इस कोड को इस्तेमाल किया जाना चाहिए जब आप दो प्रकार की संस्थाओं के सभी संयोजनों की प्रक्रिया पूरी की। आप इसे दो से अधिक प्रकार के लिए सामान्यीकृत भी कर सकते हैं।

यहाँ यह एक वैध TwoKindsInputReader के लिए mapreduce.yaml है:

mapreduce: 
- name: recommendationMapReduce 
    mapper: 
    input_reader: customInputReaders.TwoKindsInputReader 
    handler: recommendation.calculateCorrelationHandler 
    params: 
    - name: kind1 
     default: kinds.User 
    - name: kind2 
     default: kinds.Item 
    - name: shard_count 
     default: 16 
2

यह जानना मुश्किल है कि आप वास्तव में क्या गणना कर रहे हैं इसके बारे में अधिक जानकारी के बिना क्या सिफारिश करनी है। एक साधारण विकल्प है कि बस संबंधित कॉल को मानचित्र कॉल के अंदर लाएं - वहां आपको डेटास्टोर ऑपरेशन करने से रोकने में कुछ भी नहीं है।

इसके परिणामस्वरूप बहुत सी छोटी कॉलें होंगी। जैसा कि आप सुझाव देते हैं, एक कस्टम इनपुट रीडर लिखना, आपको समानांतर में इकाइयों के दोनों सेट लाने की अनुमति देगा, जो प्रदर्शन में काफी सुधार करेगा।

यदि आप इन संस्थाओं में शामिल होने की आवश्यकता के बारे में अधिक जानकारी देते हैं, तो हम अधिक ठोस सुझाव प्रदान करने में सक्षम हो सकते हैं।

+0

बस अधिक जानकारी जोड़ा गया! – fjsj