6

Sadece Batch data processing with App Engine session of Google I/O 2010'u izledim, MapReduce article from Google Research'un bazı bölümlerini okuyun ve şimdi Python'da bir öneri sistemini uygulamak için MapReduce on Google App Engine'u kullanmayı düşünüyorum.MapReduce, Google App Engine'de birden fazla veri deposuyla ilgili

Task Queue API yerine appengine mapreduce'u kullanmayı tercih ediyorum çünkü birincisi, bir türdeki tüm örneklerde, otomatik yığınlamada, otomatik görev zincirlemesinde, vb. Kolay yinelemeyi sunuyor. Sorun şudur: benim öneri sistemim örnekler arasındaki ilişkiyi hesaplamalıdır İki farklı Modelin, yani, iki ayrı türün örnekleri.

Örnek: Şu iki Modelim var: Kullanıcı ve Öğe. Her birinin özellik olarak etiket listesi vardır. Aşağıda kullanıcılar ve öğeler arasındaki ilişkiyi hesaplama işlevleri bulunmaktadır. calculateCorrelation kullanıcı ve öğelerin her kombinasyonu için çağrılmalıdır unutmayın:

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    

Ama bu calculateCorrelation appengine-MapReduce geçerli Mapper değildir ve belki de bu fonksiyon MapReduce hesaplama konsepti ile bile uyumlu değildir. Yine de, emin olmalıyım ki ... otomatik yığınlama ve görev zincirleme gibi bu appengine-mapreduce avantajlarına sahip olmak benim için gerçekten harika olurdu.

Bunun için herhangi bir çözüm var mı?

Kendi InputReader'ımı tanımlamalı mıyım? İki farklı türdeki tüm örnekleri okuyan yeni bir InputReader, mevcut appengine-mapreduce uygulamasına uyumlu mu?

Veya aşağıdakileri denemeli miyim?

  • yeni Modelinin örnekleri (muhtemelen kullanarak MapReduce) içine, iki tarafından, bu iki çeşit Tüzel kişilerden ikisini bütün anahtarları birleştirin her biri için bu yeni model
  • örnekleri üzerinde Haritacıların kullanılarak
  • Bıkmadan Örneğin, farklı türlerdeki iki varlığı elde etmek için anahtarlar kullanın ve bunlar arasındaki ilişkiyi hesaplayın.
+0

? Kullanıcı ve öğenin her kombinasyonu var mı? Sadece bir şekilde ilgili olanları mı? Ayrıca, hangi dil bu? Python değil! Kullanıcı ve öğenin her birleşimi için –

+0

'hesaplaCorrelation 'çağrılmalıdır. Ve şimdi karışıklığı önlemek için değişken türlerini kaldırdım. – fjsj

cevap

3

Nick Johnson önerisini takip ederek, kendi InputReader'mı yazdım. Bu okuyucu varlıkları iki farklı türden getiriyor. Bu varlıkların tüm kombinasyonları ile tuples verir. İşte burada: İki çeşit tarafın bütün kombinasyonları işlemek için gerektiğinde

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 

Bu kod kullanılmalıdır. Ayrıca ikiden fazla tür için de genelleştirebilirsiniz.İşte

geçerli bir TwoKindsInputReader için mapreduce.yaml geçerli: Kullanıcılar ve Öğeler geçti için kriterler nelerdir

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

Gerçekten neyi hesapladığınızı daha fazla ayrıntı almadan öneride bulunmak zor. Basit bir seçenek, haritadaki ilgili öğeyi kolayca almaktır - orada veri deposu işlemleri yapmanıza engel olacak hiçbir şey yoktur. Bununla birlikte, bu çok sayıda küçük aramaya neden olacaktır. Özel bir InputReader yazmanızın önerdiğine göre, her iki öğe kümesini de paralel olarak almanızı sağlar; bu da performansı önemli ölçüde artıracaktır.

Bu varlıklara nasıl katılmanız gerektiğine dair daha ayrıntılı bilgi verirseniz, daha somut öneriler sunabiliriz.

+0

Sadece daha fazla bilgi eklendi! – fjsj

İlgili konular