2013-09-03 4 views
1

У меня проблемы с производительностью с заранее подобранными деталями в Mahout.Mahout precomputed Точность позиции товара - медленная рекомендация

У меня 4 миллиона пользователей с примерно одинаковым количеством элементов, с настройками пользовательского элемента размером 100 МБ. Я хочу сделать рекомендацию на основе контента, основанную на сходстве косинусов векторов TF-IDF документов. Поскольку вычисление это на лету идет медленно, я предварительно вычислены попарное сходство 50 наиболее аналогичных документов следующим образом:

  1. Я использовал seq2sparse для получения векторов TF-IDF.
  2. Я использовал mahout rowId производить Mahout матрицу
  3. Я использовал Mahout rowSimilarity -i INPUT/matrix -o OUTPUT -r 4587604 --similarityClassname SIMILARITY_COSINE -m 50 -ess производить верхние 50 самых похожих документов

я использовал Hadoop для предвычисления все это. Для 4 миллионов элементов выход составил всего 2,5 ГБ.

Затем я загрузил содержимое файлов, созданных редукторами, в Collection<GenericItemSimilarity.ItemItemSimilarity> corrMatrix = ..., используя docIndex для декодирования идентификаторов документов. Они уже были целыми числами, но rowId расшифровали их, начиная с 1, поэтому я должен вернуть его.

Для рекомендации я использую следующий код:

ItemSimilarity similarity = new GenericItemSimilarity(correlationMatrix); 

CandidateItemsStrategy candidateItemsStrategy = new SamplingCandidateItemsStrategy(1, 1, 1, model.getNumUsers(), model.getNumItems()); 
MostSimilarItemsCandidateItemsStrategy mostSimilarItemsCandidateItemsStrategy = new SamplingCandidateItemsStrategy(1, 1, 1, model.getNumUsers(), model.getNumItems()); 

Recommender recommender = new GenericItemBasedRecommender(model, similarity, candidateItemsStrategy, mostSimilarItemsCandidateItemsStrategy); 

Я пытаюсь его с ограниченной моделью данных (1.6е элементов), но я загрузила все детали-запись попарных сходств в памяти. Мне удается загрузить все в основной памяти с использованием 40 ГБ.

Когда я хочу сделать рекомендацию для одного пользователя

Recommender cachingRecommender = new CachingRecommender(recommender); 
List<RecommendedItem> recommendations = cachingRecommender.recommend(userID, howMany); 

истекшее время для процесса рекомендации является 554.938583083 секунд, и к тому же она не дала никаких рекомендаций. Сейчас я действительно беспокоюсь о выполнении рекомендации. Я играл с номерами CandidateItemsStrategy и MostSimilarItemsCandidateItemsStrategy, но у меня не было никаких улучшений в производительности.

Разве идея прекомпьютера не предполагает ускорения процесса рекомендации? Не мог бы кто-нибудь помочь мне и рассказать мне, где я поступаю неправильно, и что я делаю неправильно. Кроме того, почему загрузка поровну сходства в основной памяти взрывается экспоненциально? 2,5 ГБ файлов было загружено в 40 ГБ основной памяти в Collection<GenericItemSimilarity.ItemItemSimilarity> mahout matrix ?. Я знаю, что файлы сериализуются с использованием , VectorWritable значений ключа hashMap, и ключ должен повторяться для каждого векторного значения в матрице ItemItemSimilarity, но это немного слишком много, вам не кажется?

Заранее спасибо.

ответ

1

Я стою скорректировано относительно времени, необходимого для вычисления рекомендации с использованием Collection для предварительно вычисленных значений. По-видимому, я поставил long startTime = System.nanoTime(); в верхней части моего кода, а не до List<RecommendedItem> recommendations = cachingRecommender.recommend(userID, howMany);. Это подсчитало время, необходимое для загрузки набора данных и сопоставленных элементов в общую память.

Однако я стою за памятью. Я улучшил его, используя пользовательский ItemSimilarity и загрузив HashMap<Long, HashMap<Long, Double> из предварительно вычисленного сходства.Я использовал библиотеку трофеев, чтобы уменьшить требования к пространству.

Подробный код. Обычай ItemSimilarity:

public class TextItemSimilarity implements ItemSimilarity{ 

    private TLongObjectHashMap<TLongDoubleHashMap> correlationMatrix; 

    public WikiTextItemSimilarity(TLongObjectHashMap<TLongDoubleHashMap> correlationMatrix){ 
     this.correlationMatrix = correlationMatrix; 
    } 

    @Override 
    public void refresh(Collection<Refreshable> alreadyRefreshed) { 
    } 

    @Override 
    public double itemSimilarity(long itemID1, long itemID2) throws TasteException { 
     TLongDoubleHashMap similarToItemId1 = correlationMatrix.get(itemID1); 
     if(similarToItemId1 != null && !similarToItemId1.isEmpty() && similarToItemId1.contains(itemID2)){ 
      return similarToItemId1.get(itemID2); 
     } 
     return 0; 
    } 
    @Override 
    public double[] itemSimilarities(long itemID1, long[] itemID2s) throws TasteException { 
     double[] result = new double[itemID2s.length]; 
     for (int i = 0; i < itemID2s.length; i++) { 
      result[i] = itemSimilarity(itemID1, itemID2s[i]); 
     } 
     return result; 
    } 
    @Override 
    public long[] allSimilarItemIDs(long itemID) throws TasteException { 
     return correlationMatrix.get(itemID).keys(); 
    } 
} 

общее потребление памяти вместе с моими данными, используя набор Collection<GenericItemSimilarity.ItemItemSimilarity> является 30GB, а также при использовании TLongObjectHashMap<TLongDoubleHashMap> и пользовательских TextItemSimilarity требование пространства 17GB. Производительность времени составляет 0,05 с с использованием Collection<GenericItemSimilarity.ItemItemSimilarity> и 0,07 с с использованием TLongObjectHashMap<TLongDoubleHashMap>. Кроме того, я считаю, что большая роль в исполнении играет с использованием CandidateItemsStrategy и MostSimilarItemsCandidateItemsStrategy

Я думаю, если вы хотите сохранить некоторые использует пространство находки HashMap, и если вы хотите просто немного более высокую производительность, вы можете использовать Collection<GenericItemSimilarity.ItemItemSimilarity>.