QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 5353|回复: 3
打印 上一主题 下一主题

求协同过滤算法程序

[复制链接]
字体大小: 正常 放大
harveymao        

1

主题

10

听众

312

积分

升级  4%

  • TA的每日心情

    2014-12-6 00:46
  • 签到天数: 86 天

    [LV.6]常住居民II

    自我介绍
    数学建模的爱好者

    社区QQ达人

    群组第三届数模基础实训

    群组2014年地区赛数学建模

    群组数学建模培训课堂1

    跳转到指定楼层
    1#
    发表于 2014-7-18 23:21 |只看该作者 |倒序浏览
    |招呼Ta 关注Ta
    本人在学校参加暑假培训,需要这个算法做题!求大神赐教,感激不尽  `! p, V$ R  G& P2 h0 a' t0 P
    zan
    转播转播0 分享淘帖0 分享分享0 收藏收藏0 支持支持0 反对反对0 微信微信

    3503

    主题

    538

    听众

    5990

    积分

  • TA的每日心情
    开心
    2017-2-7 15:12
  • 签到天数: 691 天

    [LV.9]以坛为家II

    社区QQ达人 元老勋章 发帖功臣 新人进步奖 优秀斑竹奖 金点子奖 原创写作奖 最具活力勋章 助人为乐奖 风雨历程奖

    群组2013年国赛赛前培训

    群组2014年地区赛数学建模

    群组数学中国第二期SAS培训

    群组物联网工程师考试

    群组2013年美赛优秀论文解

    # -*- coding=utf-8 -*-4 \/ b/ f: b0 X% J3 e* M
    1 i1 i3 [0 O& @* I* e
    import math
    ' p9 X- J/ x( V5 R7 n8 zimport sys
    + ~4 G  v8 D- R+ w: Q9 G+ T6 Zfrom texttable import Texttable% Z% S! Z% }7 Y6 ?! ?8 j4 P8 g, \, R

    ; D* c5 D5 x: T' c. V
    / |+ i3 b6 x" }#) m# x! \% `& p
    #   使用 |A&B|/sqrt(|A || B |)计算余弦距离
    7 C& a$ |! F( R- p% t' R" P#- c- Z. g% s) K) i( l/ D- x# a
    #: l% e2 J! v# B  u4 |# m( F
    #/ w0 J% f/ J$ S8 Q) `# |
    def calcCosDistSpe(user1,user2):
    - a8 S0 D5 G' u& M: I: d    avg_x=0.0& r3 d5 l0 J9 e9 \
        avg_y=0.0
    * ]" ~- `: |: M2 ~    for key in user1:
    ; B1 w% R) r8 r$ f: Z        avg_x+=key[1]& R+ r* w  u( X% h$ `( [
        avg_x=avg_x/len(user1)
    , `' F: Q5 e- `' Y' \# M: O5 B    9 I( _8 t/ B; G* I( O' Z
        for key in user2:
    , l2 y( H" s& _! S7 E" H- F        avg_y+=key[1]9 m5 U$ T( K4 `4 s0 d" A
        avg_y=avg_y/len(user2)+ e: _, r( F. d% r
        3 F  ~1 }5 c% n! J3 O
        u1_u2=0.0
    5 m8 v* m7 x$ }0 e" z& M& n9 j    for key1 in user1:
    # |# y* m/ D+ x. w        for key2 in user2:
    2 R  B. Y5 r; d, r) }7 i: X            if key1[1] > avg_x and key2[1]>avg_y and key1[0]==key2[0]:
    5 b# X+ ~9 o2 U; a" T5 I                u1_u2+=19 D) @9 d3 ]5 _2 Y
        u1u2=len(user1)*len(user2)*1.0  m) d0 a& I$ i
        sx_sy=u1_u2/math.sqrt(u1u2)5 h3 G9 z$ [& m9 o9 b7 H+ h
        return sx_sy
    - f3 ^7 l8 u" r3 P
    / Y( ]: S. c4 v. B
    0 M& s0 d4 P% u( F7 y& o# h#
    + P( _+ H3 z0 w. Z" w#   计算余弦距离
    . S; v4 _2 |8 d) O#
    , u* v( V& f3 G! u0 l0 S7 A## z3 l- s! k) c9 ^* x- f" q- L
    def calcCosDist(user1,user2):
    5 f# C& }4 [$ L' X2 w    sum_x=0.0; a4 ~9 x& P$ Z+ N6 {: n7 m: R
        sum_y=0.09 c; k' @% A2 M, C: u. M1 j+ l
        sum_xy=0.0- R" A2 ]; M# C9 J, U
        for key1 in user1:
    " C5 I6 Z- m# S  d+ ^, O3 h* i        for key2 in user2:( k; `* Z, O% I! |: n' T
                if key1[0]==key2[0] :
    ' ^. Y5 U, q! n4 R' Y- ]                sum_xy+=key1[1]*key2[1]
    2 T8 |: m( T; m$ e  G% I/ d* N. \                sum_y+=key2[1]*key2[1]
    4 _6 @9 w2 p6 X2 A2 U5 U. F                sum_x+=key1[1]*key1[1]% a7 g+ M2 E2 t, g
        / t8 V  v; ~" V5 v% \+ q
        if sum_xy == 0.0 :
    6 o+ Q' ]8 b; O  g3 [        return 0
    " \- V3 O4 R  G, v7 W    sx_sy=math.sqrt(sum_x*sum_y) 8 K$ c+ x4 @( s( E2 O
        return sum_xy/sx_sy1 ^9 x5 Q- S* F  p& T  w$ M

    , M( s. _! M+ [8 H5 X: S6 g- O! X( z! w3 K
    #; `. `1 ^: [1 [: J5 s" j+ y2 L
    #$ G& l/ g0 G! L+ x# S) W
    #   相似余弦距离
    7 f) B) I; w# r  H#
    : i9 z% v4 z4 p: q' y$ ^. J6 r#7 K. \1 h: Z9 W& `* M
    #) L0 U9 I6 t: ~% C; Q3 {* Q
    def calcSimlaryCosDist(user1,user2):0 `! a' Z2 G1 N5 a; F$ J8 v
        sum_x=0.0
    1 l  l7 V7 u: p  ~, A    sum_y=0.0/ y; b2 D; w/ B, |) O4 n' w/ a% T: P2 L
        sum_xy=0.05 ?  R; l' k* n$ A. ]9 V
        avg_x=0.07 e7 g- C! G1 d
        avg_y=0.0+ {1 `$ X, h" x7 M
        for key in user1:
    " O$ s6 j2 a/ a9 t8 X. k7 J        avg_x+=key[1]
    ) b/ N+ g2 x  J    avg_x=avg_x/len(user1)
      \) B+ L3 R: ~0 D, g8 H/ l' I/ w; N   
    ) v2 v' @4 z2 \! Y; \% i& [# Z% u    for key in user2:; f/ V- \9 o0 Z
            avg_y+=key[1]
    , m, z5 w& q4 x. O    avg_y=avg_y/len(user2), [1 P( o3 p( B1 B
       
    # c! p6 u6 n+ O2 Z8 j4 y    for key1 in user1:1 O. t, |2 `, x7 Y
            for key2 in user2:3 V4 N, L) c4 l
                if key1[0]==key2[0] :! A( E) O- `4 C- R( u, u
                    sum_xy+=(key1[1]-avg_x)*(key2[1]-avg_y)
    9 [+ G5 B; y% ~7 _! z                sum_y+=(key2[1]-avg_y)*(key2[1]-avg_y)1 d. N* |/ R. O" W) y/ V
            sum_x+=(key1[1]-avg_x)*(key1[1]-avg_x)4 q- }3 u! V) ^! X0 L
        7 T# T7 M( i9 N$ h" Y
        if sum_xy == 0.0 :- C3 h' k; n4 \0 e% I+ H
            return 0
    2 U3 ~3 J% ]' {% l$ x# w    sx_sy=math.sqrt(sum_x*sum_y)
    9 F+ R: \( u7 F0 D+ b& I    return sum_xy/sx_sy
    1 E! @9 o6 d# T/ k' o5 @2 q: H9 W9 B    ' Z, q2 G- v. B

    / ~1 I0 Z2 ~- T, }## I" {" l3 X9 R4 x% r" y, @/ h* X3 i
    #   读取文件& ^+ F$ ~# w) b' G
    #
    9 ~7 K9 S9 }0 Q#, B  \% s" {5 \& H
    def readFile(file_name):$ S; H: V1 L& @; K: V
        contents_lines=[]
    * O% n1 X8 H7 I. `+ ]    f=open(file_name,"r")% R& l; F' k3 u* c1 F
        contents_lines=f.readlines()+ O. f3 `/ ]2 S" T+ u+ `! P
        f.close()1 y% `) P* i* P6 M) a
        return contents_lines% R; x8 Q# N( o
    4 \/ w% [3 ^, ?$ o7 w

    + Q' f% H' d1 x0 l$ u$ @8 b' W0 T* A# g$ o
    #3 H# r& w) ~) S- [* b/ G' F
    #   解压rating信息,格式:用户id\t硬盘id\t用户rating\t时间8 M) h3 n( D& s3 w% v0 N6 E
    #   输入:数据集合" |- y/ S+ h8 D) S  s
    #   输出:已经解压的排名信息
    8 O; a% p; c/ p; F#
    : V! L# o- m/ U5 M3 o; n7 G4 E$ g, Gdef getRatingInformation(ratings):
    * ~5 {3 k' ^9 T    rates=[]% ?* j3 d5 i$ h/ ^. K* W& o9 ^
        for line in ratings:
    4 g: i% L0 h8 E8 ^; C# @' K        rate=line.split("\t")
    1 t9 G5 C- N* b        rates.append([int(rate[0]),int(rate[1]),int(rate[2])])5 u: `% K. g8 I& k- @
        return rates1 B- M9 `% `, j0 q/ s$ Z
    2 I4 k. |2 W' X
    # `7 N* p" e  u
    #
    , y: R  ^; C0 V/ y5 k' K0 u#   生成用户评分的数据结构
    - O8 Y1 \! t6 r#   
    ! V9 `7 y# o1 p+ N#   输入:所以数据 [[2,1,5],[2,4,2]...]
    % m* s2 d4 f+ h6 p#   输出:1.用户打分字典 2.电影字典4 a9 |3 w  a* o: I! F) r
    #   使用字典,key是用户id,value是用户对电影的评价,; s% D! i. n. n; k+ L- d: P
    #   rate_dic[2]=[(1,5),(4,2)].... 表示用户2对电影1的评分是5,对电影4的评分是2
    . z: r+ G, [( L( i#
    6 f- f2 J+ X- V/ A) ~' [+ B9 zdef createUserRankDic(rates):
    " C& n' G1 t# f+ I& R    user_rate_dic={}
    , L& m( E, V% |; }' e  m% F0 v    item_to_user={}6 I# B+ a9 C' m( `) x# v
        for i in rates:' ?1 y+ F( i7 n
            user_rank=(i[1],i[2])
    6 r  q/ J- T" O        if i[0] in user_rate_dic:
    9 b: [# H1 v, |            user_rate_dic[i[0]].append(user_rank)* T6 o: Z! Z. d! f! W" n
            else:
    / S+ `5 q# Q2 d4 H1 Z            user_rate_dic[i[0]]=[user_rank]; U3 a. }8 p; I& f- w; z
                
    * W, A- E7 `% x9 M/ o        if i[1] in item_to_user:" ^/ @) B2 Z4 B
                item_to_user[i[1]].append(i[0])& A! W4 f1 V3 K* v' D* N
            else:4 ~6 k2 M% L5 K. P) u
                item_to_user[i[1]]=[i[0]]
    6 `8 ^9 F' o% s' E; I- J7 P            9 T' L0 J% A' Z- r, B# ]7 Z9 R
        return user_rate_dic,item_to_user5 `7 H. [& d! [1 P

    6 C& [2 B9 ?' f3 r4 p7 Z3 A  M* W/ b+ H
    #
    6 V- e: Z- L7 L& y( W$ q#   计算与指定用户最相近的邻居; {1 w8 D) n1 L$ T% C
    #   输入:指定用户ID,所以用户数据,所以物品数据. |4 n- \* u* j1 n3 s* a
    #   输出:与指定用户最相邻的邻居列表; h8 B: `5 W/ L* {$ L
    #
    ) ^( O0 A% T" Mdef calcNearestNeighbor(userid,users_dic,item_dic):4 q! S8 U$ S# ]: f' B$ Q6 y) g# Z* x3 c
        neighbors=[]; E) t7 D) }. @  h# Q# J
        #neighbors.append(userid)
    ! V4 B& o2 }1 L& x4 \$ K    for item in users_dic[userid]:
    ; G7 |! f* ~9 _# C& o        for neighbor in item_dic[item[0]]:8 p- m# X! {4 P9 ?+ }& e
                if neighbor != userid and neighbor not in neighbors:
    & X% p5 E7 d: N$ `6 b                neighbors.append(neighbor)/ `, c- o0 Z, D5 m% w' A0 k
          * f9 K; t  F9 D: v
        neighbors_dist=[]$ Y; x/ D; Y. [6 o6 Q
        for neighbor in neighbors:/ V; k6 c5 y* H0 P
            dist=calcSimlaryCosDist(users_dic[userid],users_dic[neighbor])  #calcSimlaryCosDist  calcCosDist calcCosDistSpe' d& N1 w4 [( Y  L8 N2 ^
            neighbors_dist.append([dist,neighbor])
    ) v+ y# B# O# T* T% X    neighbors_dist.sort(reverse=True)/ m! Z; `3 M, j9 m( h. e  i
        #print neighbors_dist4 t4 z0 R# N& G: |- C
        return  neighbors_dist
    ( O. M4 z, r3 X9 w
    ! q* K  ]& \# R$ _
    : s  v6 L7 P4 ^8 v4 E- t) v#
    % X% f$ X" N7 R5 |2 X7 O0 O- M6 Z& d#   使用UserFC进行推荐
    2 i6 [, f4 l; }3 J" X, j( \#   输入:文件名,用户ID,邻居数量
      x' ^. }; {9 J) ]( @#   输出:推荐的电影ID,输入用户的电影列表,电影对应用户的反序表,邻居列表' r' b- \, Q5 r+ R- n& h
    #
    : O7 l8 E: _. y4 w  q4 m) Q. Kdef recommendByUserFC(file_name,userid,k=5):
    ! I* [, B8 h- ?9 B$ `* g   
    ) y& |6 ?0 v- D    #读取文件数据, c" S/ d% Q3 f: p5 B
        test_contents=readFile(file_name)
    4 E4 [$ v- i- B2 a   
    - W$ |. ?: w. a0 q/ T    #文件数据格式化成二维数组 List[[用户id,电影id,电影评分]...] 0 L. D" t/ z' Y( l% `
        test_rates=getRatingInformation(test_contents)
    9 m. {7 W8 [  O* q/ d7 ^    8 |6 r, l7 T! F- ~* _; x
        #格式化成字典数据 6 L0 p# C* q' V1 C- F' B
        #    1.用户字典:dic[用户id]=[(电影id,电影评分)...]1 Y# \. r# a  `: E6 S- z3 G4 v+ ~
        #    2.电影字典:dic[电影id]=[用户id1,用户id2...]. v# R6 {! J. e6 \/ L4 d/ l6 P8 [9 g
        test_dic,test_item_to_user=createUserRankDic(test_rates). P) D4 J* E/ n/ e( w
       
    " q* ]$ N3 |" A! q    #寻找邻居% ~% T+ b. z! C2 ]0 K
        neighbors=calcNearestNeighbor(userid,test_dic,test_item_to_user)[:k]
    ) c) w. H) E2 B5 m' S: S        
    $ ]+ }! ~! k1 [0 b    recommend_dic={}
    / P4 n# |8 ~& ^- K# @# o0 X    for neighbor in neighbors:  y" y1 }4 [, p/ [+ n4 ]9 }
            neighbor_user_id=neighbor[1]7 n2 F* a" V& m, x0 u
            movies=test_dic[neighbor_user_id]
    2 C- R6 @$ E+ d& ]* g: m) k        for movie in movies:' \1 S% t% u+ q8 D$ c- z) g
                #print movie
    % \2 U$ e2 g  k/ U" l9 V" [& [4 p            if movie[0] not in recommend_dic:
    ; ]9 Q. F+ [- v  R9 v9 K9 L                recommend_dic[movie[0]]=neighbor[0]( V# _9 J( E8 j7 T) \3 g
                else:
    $ E* c5 O6 r' P* ]; \                recommend_dic[movie[0]]+=neighbor[0]; ~0 A1 C5 ^& R5 L: ~/ Q$ E
        #print len(recommend_dic)$ b" T+ }4 N( M- v" r
        ; K6 T+ e% n& N: O5 u6 F
        #建立推荐列表6 {6 N' |, `0 U
        recommend_list=[]% F: N0 |; J& G6 O: O
        for key in recommend_dic:4 ?7 w) ~. x1 O
            #print key+ @( o1 I9 x# g/ Z% i% }9 m4 H
            recommend_list.append([recommend_dic[key],key])
    % ?) [0 {) G" M    % I) X' M% o  Z  N7 ^7 H0 U
       
    0 v6 l9 k7 ^! |% x( u2 u% P7 B3 i4 O    recommend_list.sort(reverse=True)0 ]0 ^' k! O7 `3 O, p& b& k
        #print recommend_list
    ( E+ `$ P: T( L. X0 y    user_movies = [ i[0] for i in test_dic[userid]]- t. V. U6 s6 O( [# f3 N

    5 k: I! Q# v8 q- |* |6 f$ s) T2 I* ]# Q- j    return [i[1] for i in recommend_list],user_movies,test_item_to_user,neighbors& l( D0 g' m& ^/ a) K) c- v
       
    7 O4 C4 I1 e( Q5 t1 B! I   
    . b/ X2 q' ]+ }- C
    + i' V3 C. ~% P3 b8 A#
    ; J; w$ C; a: ]+ g#
    , B' `+ U3 K! u2 A7 L9 T#   获取电影的列表* N5 y: V6 r& N- g! U) ?- T& G
    ## H  _2 N) O, w* W& W0 v
    #
    7 S% t* t: H; q, z+ ~8 m#6 |3 [7 f; J% V1 n2 s* \
    def getMoviesList(file_name):
    / `# n* D6 h4 w8 {6 f& N! X    #print sys.getdefaultencoding()
    : X/ g, g) R; f; {6 d$ `    movies_contents=readFile(file_name)
    ) @5 E, e0 Y) B    movies_info={}
    2 N; ~8 Y  T9 r$ H0 m( t7 d    for movie in movies_contents:
    9 S" S% ]9 p6 o4 [  Z        movie_info=movie.split("|")
    * N& _" g& n7 m' K! g        movies_info[int(movie_info[0])]=movie_info[1:]
    / ?% j4 p' Y. s. e/ j8 ?: z# D7 j    return movies_info( s& }+ I% W* R; p
       
    ' y6 j0 Y: g8 Y' T. N6 Y    7 b. f  m- |+ i- y, _
       
    % P6 ]5 F* \! p! z8 n- b1 p$ ?#主程序
    6 Q7 q, n: e. T4 x3 j#输入 : 测试数据集合" ?, @- R; n6 J' m0 V  D
    if __name__ == '__main__':
    ' q( y1 L$ |+ L0 x6 C  \2 |    reload(sys)
    ' `5 H$ ?- b, y* o/ @8 Z! V    sys.setdefaultencoding('utf-8')
    . v9 R( B" _+ K* l  s6 T. q    movies=getMoviesList("/Users/wuyinghao/Downloads/ml-100k/u.item"): j* U3 ~; |# r/ ^. z4 m+ u3 O+ ?
        recommend_list,user_movie,items_movie,neighbors=recommendByUserFC("/Users/wuyinghao/Downloads/ml-100k/u.data",179,80)
    0 `% a$ P# V' @! |+ [4 z3 N: a    neighbors_id=[ i[1] for i in neighbors]7 e1 f! L9 I. U5 b( E% ?, _
        table = Texttable()8 }/ U* w6 E4 m- ~# B" j
        table.set_deco(Texttable.HEADER)3 n+ I! M( w( V- y9 e; F
        table.set_cols_dtype(['t',  # text
    / G" I& f$ |5 s1 w" ?, z                          't',  # float (decimal)
    , ?* J3 W' W2 W" j5 Q                          't']) # automatic
    1 \/ s. e. }$ I9 M4 e: O    table.set_cols_align(["l", "l", "l"])
    2 I9 G. Z: L2 x  C$ {    rows=[]
    , z, e& e0 \; o' d' t. A    rows.append([u"movie name",u"release", u"from userid"])
    $ Q. r' }+ a; T+ Q$ B. m# ^    for movie_id in recommend_list[:20]:4 `' M5 E5 t4 }2 V
            from_user=[]  B8 j. e. m7 p! b+ ~1 n
            for user_id in items_movie[movie_id]:! F1 @9 T$ f8 J7 e4 s  ^
                if user_id in neighbors_id:% o5 f/ N7 T; m! N- C
                    from_user.append(user_id)8 U% [! }9 |5 M" X9 d" S# P# u* C
            rows.append([movies[movie_id][0],movies[movie_id][1],""])
    7 ^/ m3 E, c- R/ b5 p( n7 b7 F( O    table.add_rows(rows)9 X" x$ n0 D6 S! ?+ h
        print table.draw()
    回复

    使用道具 举报

    mea_lsc        

    2

    主题

    10

    听众

    638

    积分

    升级  9.5%

  • TA的每日心情
    擦汗
    2016-4-14 14:41
  • 签到天数: 212 天

    [LV.7]常住居民III

    自我介绍
    数模新手

    社区QQ达人

    百年孤独 发表于 2014-7-19 09:22
    : K& @  i8 ^+ `, D. s# -*- coding=utf-8 -*-5 h& a. o0 ]# x7 F% [7 I4 P

    ! v$ n" g+ W8 A$ }# g, r, w; Cimport math
    0 E# O: x2 g( g; _# q
    这是什么语言的程序?
    7 @- ?, ^  K& m, S; ?1 X% }+ H
    回复

    使用道具 举报

    0

    主题

    4

    听众

    40

    积分

    升级  36.84%

  • TA的每日心情
    开心
    2019-8-30 15:45
  • 签到天数: 12 天

    [LV.3]偶尔看看II

    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 注册地址

    qq
    收缩
    • 电话咨询

    • 04714969085
    fastpost

    关于我们| 联系我们| 诚征英才| 对外合作| 产品服务| QQ

    手机版|Archiver| |繁體中文 手机客户端  

    蒙公网安备 15010502000194号

    Powered by Discuz! X2.5   © 2001-2013 数学建模网-数学中国 ( 蒙ICP备14002410号-3 蒙BBS备-0002号 )     论坛法律顾问:王兆丰

    GMT+8, 2026-8-27 09:27 , Processed in 1.624791 second(s), 68 queries .

    回顶部