0

我正在研究 mahout 推荐引擎用例。我预先计算了推荐并存储在数据库中。现在我计划向 .net 提供味觉休息服务。我的客户和产品有限。这是分销商级别的推荐用例。我的问题是,如果有新的分销商进来,我将如何向他提出建议。以及如何我向每个经销商建议推荐产品的数量。你们能给我一些指导吗。我会面临性能问题吗..?

4

2 回答 2

0

一种方法是,当新用户到来时,从头开始为所有用户或仅为该用户预先计算推荐。您应该知道该用户也可能会更改其他人的推荐。您是否经常需要进行预计算,这取决于您的需求。

但是,如果您的用户和项目数量有限,另一种方法是让在线推荐器实时计算推荐。如果您使用FileDataModel,有一种方法可以定期从新用户那里获取数据(请参阅Mahout in Action一书)。如果您在内存数据模型中使用更快,您可以覆盖方法:setPreference(long userID, long itemID, float value)removePreference(long userID, long itemID),并且每当新用户出现并喜欢或删除某些项目时,您应该在数据模型上调用这些方法。

编辑:基本上你可以得到GenericDataModel, 并将其添加到方法setPreferenceremovePreference. 这将是您的较低级别的数据模型。您可以通过在如下方法 ReloadFromJDBCDataModel中设置数据模型来包装它:reload()

数据模型 newDelegateInMemory = delegate.hasPreferenceValues() ?新的 MutableDataModel(delegate.exportWithPrefs()) : 新的 MutableBooleanPrefDataModel(delegate.exportWithIDsOnly());

被覆盖的方法:

@Override
public void setPreference(long userID, long itemID, float value) {

    userIDs.add(userID);
    itemIDs.add(itemID);

    setMinPreference(Math.min(getMinPreference(), value));
    setMaxPreference(Math.max(getMaxPreference(), value));

    Preference p = new GenericPreference(userID, itemID, value);

    // User preferences
    GenericUserPreferenceArray newUPref;
    int existingPosition = -1;
    if (preferenceFromUsers.containsKey(userID)) {
        PreferenceArray oldPref = preferenceFromUsers.get(userID);
        newUPref = new GenericUserPreferenceArray(oldPref.length() + 1);
        for (int i = 0; i < oldPref.length(); i++) {
            //If the item does not exist in the liked user items, add it!
            if(oldPref.get(i).getItemID()!=itemID){
                newUPref.set(i, oldPref.get(i));
            }else{
                //Otherwise remember the position
                existingPosition = i;
            }
        }
        if(existingPosition>-1){
            //And change the preference value
            oldPref.set(existingPosition, p);
        }else{
            newUPref.set(oldPref.length(), p);
        }
    } else {
        newUPref = new GenericUserPreferenceArray(1);
        newUPref.set(0, p);
    }
    if(existingPosition == -1){
        preferenceFromUsers.put(userID, newUPref);
    }

    // Item preferences
    GenericItemPreferenceArray newIPref;
    existingPosition = -1;
    if (preferenceForItems.containsKey(itemID)) {
        PreferenceArray oldPref = preferenceForItems.get(itemID);
        newIPref = new GenericItemPreferenceArray(oldPref.length() + 1);
        for (int i = 0; i < oldPref.length(); i++) {
            if(oldPref.get(i).getUserID()!=userID){
                newIPref.set(i, oldPref.get(i));
            }else{
                existingPosition = i;
            }
        }
        if(existingPosition>-1){
            oldPref.set(existingPosition, p);
        }else{
            newIPref.set(oldPref.length(), p);
        }
    } else {
        newIPref = new GenericItemPreferenceArray(1);
        newIPref.set(0, p);
    }
    if(existingPosition == -1){
        preferenceForItems.put(itemID, newIPref);
    }   
}

@Override
public void removePreference(long userID, long itemID) {
    // User preferences
    if (preferenceFromUsers.containsKey(userID)) {
        List<Preference> newPu = new ArrayList<Preference>();
        for (Preference p : preferenceFromUsers.get(userID)) {
            if(p.getItemID()!=itemID){
                newPu.add(p);
            }       
        }
        preferenceFromUsers.remove(userID);
        preferenceFromUsers.put(userID, new GenericUserPreferenceArray(newPu)); 
    }
    if(preferenceFromUsers.get(userID).length()==0){
        preferenceFromUsers.remove(userID);
        userIDs.remove(userID); 
    }
    if (preferenceForItems.containsKey(itemID)) {
        List<Preference> newPi = new ArrayList<Preference>();
        for (Preference p : preferenceForItems.get(itemID)) {
            if(p.getUserID() != userID){
                newPi.add(p);
            }   
        }
        preferenceForItems.remove(itemID);
        preferenceForItems.put(itemID, new GenericItemPreferenceArray(newPi));
    }   
    if(preferenceForItems.get(itemID).length()==0){
        //Not sure if this is needed, but it works without removing the item
        //preferenceForItems.remove(itemID);
        //itemIDs.remove(itemID);
    }
}
于 2014-09-01T13:16:53.757 回答
0

如果“新经销商”是指您没有他们的数据,也没有历史数据。那么您就无法使用 Mahout 的推荐器进行推荐。

一旦他们选择了一个项目,您就可以建议其他项目。使用 Mahout 的“itemsimilarity”驱动程序计算目录中所有物品的相似项。然后,如果他们选择一些东西,您可以建议类似的物品。

来自 itemsimilarity 驱动程序的项目可以作为列值存储在您的数据库中,其中包含每个项目的相似项目的 id。然后,您可以使用搜索引擎对该列进行索引,并使用用户的第一顺序作为查询。这将返回实时个性化推荐,是 Mahout 人建议的最新方法。

请参阅领先的 Mahout 数据科学家之一 Ted Dunning 在这本书中对如何执行此操作的描述。http://www.mapr.com/practical-machine-learning

于 2014-09-02T14:38:59.170 回答