好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

协同过滤算法之组合加权评分

协同过滤算法之组合加权评分

http://blog.sina.com.cn/s/blog_406d9bb00100r7ix.html

协同过滤算法之组合加权评分   (2011-05-21 11:56:04)

转载 ▼

标签:  

杂谈 分类:   数据库

我们在网上购物的时候总是会花大量时间去搜索自己需要的信息,即使找到了一些类似的商品也可能不是特别满意的,搭上了大把的时间不说可能还选不到合适的商品那就太悲催咯,鉴于这个情况,个性化推荐就应运而生了,如果你去过亚马逊或卓越亚马逊应该就会知道这个东西。

当我们登陆进去后,网站首页会自动列出一些我们喜欢的商品,这样我们就不用到处去找我们想买的商品了。

网站是怎么知道我们喜欢什么商品的呢? 下面是我对这个原理比较肤浅的理解,现帖出来分享一下,废话不多说,切入正题。

 基本概念:

协同过滤算法:协同过滤分析用户兴趣,在用户群中找到指定用户的相似(兴趣)用户,综合这些相似用户对某一信息的评价,形成系统对该指定用户对此信息的喜好程度预测。

目前还存在的缺点:

·         稀疏性问题:用户和商品的总数都非常大,蛋是用户对商品的评分却很少

·         性能问题: 用户数和商品数越来越多,数据量日益增大导致处理效率降低

·         最初评价问题:如果没人给这个商品评分,那么这个商品因为没基数就无法被推荐

为了弥补这三个很要命的缺点,所以又提出了基于组合加权评分的方法,这样基本可以缓解以上缺点,具体如何解决且听慢慢道来。

 

为什么要用组合加权评分?他的主要作用是通过对评分矩阵行和列的平均加权评分进行综合处理并计算得出预测评分,这样就可以使每个用户对每个商品都有评分值,从而缓解了稀疏性问题。

为什么要Base on item?  如果按会员和商品搞个笛卡尔积形成矩阵再进行计算会是一件很悲催的事情,假设目前会员10万人,商品10万件, 10w*10w 后面会有10个零。那会是多少? 天文数字吧,不现实的,放弃吧。

建立矩阵R(m,n)  他是一个m*n阶矩阵,其中m行表示m个用户,n列表示n个商品, R i,j  表示用户i对商品j的评分值。(至于怎么降维可以参考奇异值分解法SVD,HSPA算法,单调递减指数函数时间权重分析法,基于时间权重还可以及时反映用户的兴趣变化)

 

组合加权评分由用户平均加权评分和项目平均加权评分两部分组成。

用户平均加权评分的公式是:

 

其中i表示商品,u表示用户,r u 为此用户平均评分与用户各项评分相对于未评分项平均评分的平均偏差之和。

其中Q为用户u对商品空间的评分总数,r i 为此商品平均评分与用户集合中各用户对未评分项i评分与用户平均评分的平均偏差之和。

组合加权评分r u,I  即是求前两个积的平方根。

 

用这个公式把相应项填充后就造成了所有用户对所有商品均有评分的结果,这样矩阵就圆满了。

具体实现方法:

建环境:

 

会员表 :

create   table   tmp_yofee_member ( id   number ,login_id   varchar2 ( 100 ),status   varchar2 ( 30 ));

商品表 :

create   table   tmp_yofee_product( id   number ,subject   varchar2 ( 100 ),status   varchar2 ( 30 ));

   

插入测试数据 :

--会员表

   declare   i   number ;

     begin

    i:= 2 ;

     while   i< 200   loop

       insert   into   tmp_yofee_member ( id ,login_id)

       values (i, 'yuki' ||i);

      i:=i+ 2 ;

       end   loop ;

       end ;

       --商品表

     declare   i   number ;

     begin

    i:= 2 ;

     while   i< 1000   loop

       insert   into   tmp_yofee_product ( id ,subject)

       values (i, 'item_' ||i);

      i:=i+ 2 ;

       end   loop ;

       end ;    

评分表 ( 将会员表和商品表笛卡尔积 ):

       create   table   TMP_YOFEE_VOTE

       as

       select   b.id pid,b.subject,a.id mid,a.login_id

       from   tmp_yofee_member a ,tmp_yofee_product b;

加入评分列 :

alter   table   tmp_yofee_vote   add   score   number ( 6 , 0 );

修改随机评分值 :

update TMP_YOFEE_VOTE

set   score =   trunc (dbms_random.value( 40 , 100 ))

where   pid   not   like   '%5' ;

commit ;

下面就可以按照刚才的公式通过游标逐个计算还没有评分项的 预测评分值 .  

DECLARE

   AVG_P   NUMBER ( 6 ,   2 );

   AVG_M   NUMBER ( 6 ,   2 );

   WE_M     NUMBER ( 6 ,   2 );

   WE_P     NUMBER ( 6 ,   2 );

    CURSOR   CUR   IS

      SELECT   PID, MID

        FROM   ( SELECT   DISTINCT   PID, MID   FROM   TMP_YOFEE_VOTE   WHERE   SCORE   IS   NULL );

   CUR_PID   NUMBER ;

   CUR_MID   NUMBER ;

BEGIN

    OPEN   CUR;

    FETCH   CUR

      INTO   CUR_PID, CUR_MID;

    WHILE   CUR% FOUND   LOOP

       SELECT   AVG (SCORE)

        INTO   AVG_P   -- 商品平均

        FROM   TMP_YOFEE_VOTE

       WHERE   PID = CUR_PID

         AND   SCORE   IS   NOT   NULL ;

      SELECT   AVG (SCORE)

        INTO   AVG_M   -- 用户平均

        FROM   TMP_YOFEE_VOTE

       WHERE   MID = CUR_MID

         AND   SCORE   IS   NOT   NULL ;

      SELECT   SUM (SCORE - AVG_P) /   COUNT (PID) + AVG_M

        INTO   WE_M   -- 用户加权

        FROM   TMP_YOFEE_VOTE

       WHERE   MID = CUR_MID

         AND   SCORE   IS   NOT   NULL ;

      SELECT   SUM (SCORE - AVG_M) /   COUNT (PID) + AVG_P

        INTO   WE_P   -- 商品加权

        FROM   TMP_YOFEE_VOTE

       WHERE   PID = CUR_PID

         AND   SCORE   IS   NOT   NULL ;

      -- DBMS_OUTPUT.PUT_LINE(SQRT(WE_M * WE_P)); --67.15

      UPDATE   TMP_YOFEE_VOTE

         SET   SCORE = SQRT(WE_M * WE_P)

       WHERE   PID = CUR_PID

         AND   MID = CUR_MID;

      FETCH   CUR

        INTO   CUR_PID, CUR_MID;

    END   LOOP ;

    CLOSE   CUR;

    COMMIT ;

END ;

 

这样我们就可以通过这种方法把矩阵里面未评分项预测并填满以便即将进行的协同过滤.

查看更多关于协同过滤算法之组合加权评分的详细内容...

  阅读:41次