mahout in action推荐系统阅读笔记(3)

第三章:数据表示

推荐质量和数据的数量和质量关系很大,通常来说,数据越多越好,数据质量越高越好

推荐算法的性能和可扩展性与数据的表示关系很大,因为推荐都是数据密集的(data-intensive)

preference data 表示

单独的一个preference包括user id,item id,preference value的元组,有时候preference value可以没有

preference data是这些元组的一个集合。

在mahout中,Preference是一个接口,需要有一个实现,通常使用GenericPreference

先看Preference代码:

public interface Preference {

  /** @return ID of user who prefers the item */
  long getUserID();

  /** @return item ID that is preferred */
  long getItemID();

  /**
   * @return strength of the preference for that item. Zero should indicate "no preference either way";
   *         positive values indicate preference and negative values indicate dislike
   */
  float getValue();

  /**
   * Sets the strength of the preference for this item
   * 
   * @param value
   *          new preference
   */
  void setValue(float value);

}

再看GenericPreference代码:

public class GenericPreference implements Preference, Serializable {

  private final long userID;
  private final long itemID;
  private float value;

  public GenericPreference(long userID, long itemID, float value) {
    Preconditions.checkArgument(!Float.isNaN(value), "NaN value");
    this.userID = userID;
    this.itemID = itemID;
    this.value = value;
  }

  @Override
  public long getUserID() {
    return userID;
  }

  @Override
  public long getItemID() {
    return itemID;
  }

  @Override
  public float getValue() {
    return value;
  }

  @Override
  public void setValue(float value) {
    Preconditions.checkArgument(!Float.isNaN(value), "NaN value");
    this.value = value;
  }

  @Override
  public String toString() {
    return "GenericPreference[userID: " + userID + ", itemID:" + itemID + ", value:" + value + ']';
  }

}

看起来没什么特别的,Preconditions是google guava的一个实现,输入不符合类型时会抛出一个异常

使用也很简单了,例如:new GenericPreference(123, 456, 3.0f)

这里存在的一个问题是有效数据20字节,而其overhead却占据了28字节,浪费严重,需要找方法解决,试看mahout是怎么做的

PreferenceArray

public interface PreferenceArray extends Cloneable, Serializable, Iterable<Preference> {

  /**
   * @return size of length of the "array"
   */
  int length();

  /**
   * @param i
   *          index
   * @return a materialized {@link Preference} representation of the preference at i
   */
  Preference get(int i);

  /**
   * Sets preference at i from information in the given {@link Preference}
   * 
   * @param i
   * @param pref
   */
  void set(int i, Preference pref);

  /**
   * @param i
   *          index
   * @return user ID from preference at i
   */
  long getUserID(int i);

  /**
   * Sets user ID for preference at i.
   * 
   * @param i
   *          index
   * @param userID
   *          new user ID
   */
  void setUserID(int i, long userID);
  /**
   * @param i
   *          index
   * @return item ID from preference at i
   */
  long getItemID(int i);

  /**
   * Sets item ID for preference at i.
   * 
   * @param i
   *          index
   * @param itemID
   *          new item ID
   */
  void setItemID(int i, long itemID);

  /**
   * @return all user or item IDs
   */
  long[] getIDs();

  /**
   * @param i
   *          index
   * @return preference value from preference at i
   */
  float getValue(int i);

  /**
   * Sets preference value for preference at i.
   * 
   * @param i
   *          index
   * @param value
   *          new preference value
   */
  void setValue(int i, float value);
  /**
   * @return independent copy of this object
   */
  PreferenceArray clone();

  /**
   * Sorts underlying array by user ID, ascending.
   */
  void sortByUser();

  /**
   * Sorts underlying array by item ID, ascending.
   */
  void sortByItem();

  /**
   * Sorts underlying array by preference value, ascending.
   */
  void sortByValue();

  /**
   * Sorts underlying array by preference value, descending.
   */
  void sortByValueReversed();

  /**
   * @param userID
   *          user ID
   * @return true if array contains a preference with given user ID
   */
  boolean hasPrefWithUserID(long userID);

  /**
   * @param itemID
   *          item ID
   * @return true if array contains a preference with given item ID
   */
  boolean hasPrefWithItemID(long itemID);
这个接口的一个实现类是GenericUserPreferenceArray,是针对单个user的所有preference,其内部包含单个userid,一个item id集合和评分集合,这样一个preference所占用的空间减小到12字节稍多,和前面的48字节相比下降了大约四分之三

其属性定义为:

  private final long[] ids;
  private long id;
  private final float[] values;

相应的,针对item的有GenericItemPreferenceArray类


FastByIDMap and FastIDSet

为了节省内存,mahout还使用了FastByIDMap和FastIDSet

你可能感兴趣的:(mahout in action推荐系统阅读笔记(3))