QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 5370|回复: 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
    本人在学校参加暑假培训,需要这个算法做题!求大神赐教,感激不尽
    $ L8 Y- o- \( u2 i: _9 w6 _* {
    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 -*-% a: P0 V; Y( _! J: J, n* G

    - d& G( I" t  w; yimport math
    : M7 O( U% r# A" R" b: zimport sys! ^  _% s. N& h& U8 r' k" u
    from texttable import Texttable( J; R  \) o/ `- D
    $ R& [/ `2 ~8 }9 h* c4 K) b6 q: b; O
    ! i' `, R7 V0 d. G2 q, v
    #" H% o7 F0 t5 U
    #   使用 |A&B|/sqrt(|A || B |)计算余弦距离
    ( x7 H* u) n2 c; E" Q#. Q/ d6 [4 u2 ~* u$ ~9 C- @
    #2 X& ~' Y6 S" w" q1 v
    #& f) O5 ~/ Y4 B( ~% W; F
    def calcCosDistSpe(user1,user2):' Y+ W) c( a2 m9 ~3 X# D' Y
        avg_x=0.0
    0 y/ B3 V" T. @9 y    avg_y=0.0
      X1 z4 _3 T" {, u3 ^' w9 ~- b% @    for key in user1:0 X8 {- U% f% a5 ]5 z( N
            avg_x+=key[1]
    " F1 a; _! M5 {9 [    avg_x=avg_x/len(user1)
    2 x; }) k# t% ^: @- C   
    , i  O: n$ D& K) m/ g    for key in user2:# ]3 u" i3 \/ N5 U7 r: c: m
            avg_y+=key[1]
    $ ]- g9 Y9 `/ s; {    avg_y=avg_y/len(user2)
    ) ]3 R  P* `' ]& b0 i# g   
    & g* _4 t' Z- n2 Z% O    u1_u2=0.07 D! Y$ K- t6 j$ q  G: H
        for key1 in user1:8 M; m% I+ U) j& n, \1 M
            for key2 in user2:
    + i$ s7 c3 q) E+ s& f            if key1[1] > avg_x and key2[1]>avg_y and key1[0]==key2[0]:
    & S" F/ ~/ E: Y& k; x6 Z. u7 A                u1_u2+=16 _6 F9 \, J1 ~) |+ m4 t
        u1u2=len(user1)*len(user2)*1.0
    7 |6 l/ f# m' x: e) |. [) H" ~  @9 g, m    sx_sy=u1_u2/math.sqrt(u1u2)
    8 u) M- X( [) a% c+ B) n- _$ w    return sx_sy
    : N- h* s' `$ e# `; x% u0 @: I1 {! o& K$ o/ E
    * b( j( j, ?, M
    #
    , d: A% Y/ Z% D* K#   计算余弦距离9 z9 \$ @$ n* W! [  L# s  Q: M
    #. m1 }  z/ Z% a
    #
    : K. a1 n8 q* P. Z: ^def calcCosDist(user1,user2):
    & Y) N9 V: k8 {; w+ b# E. o. ^    sum_x=0.0
    ' B5 s" B. J  _) t2 ~    sum_y=0.0
    1 f: o% w0 ^4 T! U' @# E& l# y    sum_xy=0.0& x0 u% B" M$ l
        for key1 in user1:
    % q6 F; @' ^6 [  R        for key2 in user2:
    3 {* d4 {0 J' }/ m1 D            if key1[0]==key2[0] :- [: l2 M" w5 J# ~- x. v  |/ }
                    sum_xy+=key1[1]*key2[1]
    7 }1 Z% y4 f, W2 E: ^8 x                sum_y+=key2[1]*key2[1]
    6 l8 a5 o" Y8 d7 G% T                sum_x+=key1[1]*key1[1]
    2 v2 E4 s/ Y+ ]% v% R5 y% g   
    8 w9 ~- m) L) T" v. B* q    if sum_xy == 0.0 :. V6 n% z! m5 o" q+ R. U
            return 0
    , n& P0 ^3 I3 v; J( |    sx_sy=math.sqrt(sum_x*sum_y) 6 o5 F2 b5 `4 B" M  z3 f' z
        return sum_xy/sx_sy
    3 f6 T+ p. n0 k) C* {
    3 J6 O% F3 c  d, A# }' p, G4 h8 _3 b( c& E, g/ U
    #9 I+ R# g' J0 W0 N
    #" n  y$ [  n( B
    #   相似余弦距离6 d) n0 [  I! l5 i
    #
    5 @+ h7 p; c4 K3 f#$ c6 f0 E* {- K0 x# H: r0 v
    #! J$ f9 {& P2 f- Y2 k/ T
    def calcSimlaryCosDist(user1,user2):
    3 a7 R4 W) w% @0 w* W    sum_x=0.0
    : O7 L1 Z( A3 @+ @! p" S( B9 x    sum_y=0.0
    8 ^& t6 d+ r; O: P: b9 S    sum_xy=0.00 w- i" Y6 k- T8 v
        avg_x=0.0
    6 |8 u$ R& x* `+ c5 t- w# m0 x3 q    avg_y=0.02 y2 s. k7 |$ k4 G. v
        for key in user1:! }# w% D7 y, L, m/ H! k
            avg_x+=key[1]2 C- Z( S( c) X
        avg_x=avg_x/len(user1)
    % N  u6 _; w9 D- O4 v3 t: e( N   
    0 ]8 r7 s  d  B    for key in user2:
    ! x1 o0 e% Y1 s! B2 l9 V        avg_y+=key[1]
    4 O* }5 F) P+ ~; s5 J    avg_y=avg_y/len(user2); }% i& W- q" E4 _8 @
        2 ?! L, y& R6 u) q9 E; ]
        for key1 in user1:6 l1 \/ |" N1 c' E/ n& H
            for key2 in user2:0 `5 J- b! i; B4 _
                if key1[0]==key2[0] :0 [1 f, c" n3 q* h. q
                    sum_xy+=(key1[1]-avg_x)*(key2[1]-avg_y)
    4 ?6 g% T/ `# \3 V                sum_y+=(key2[1]-avg_y)*(key2[1]-avg_y)
    ) z9 Z- c, _3 L) o) a        sum_x+=(key1[1]-avg_x)*(key1[1]-avg_x)
    7 F# q+ v+ B) |0 U   
    : \  m* Q) r$ M: y2 H    if sum_xy == 0.0 :7 z; {1 K' P# N8 Q2 |, i( X. {% o9 ~
            return 0% L! u5 l) l+ n" ]7 t7 t, p3 j
        sx_sy=math.sqrt(sum_x*sum_y) $ `# U1 I0 M7 P! x  _; m* j8 x% |
        return sum_xy/sx_sy
      Q: O& P; U9 i, t; ]    * m& W( a5 A1 _* v
    % M3 f# ]- y+ c1 [( y6 W1 N! K5 A
    #
    : ?4 k2 Q7 M- T* [4 n, n& Q#   读取文件3 F' W/ u5 v; Q4 T1 h' _7 g% H/ ^, B7 y: V
    #
    4 y) j2 m) ~+ r( {; c" N8 m* c* @) W  z: q#: J2 \, g# |/ E7 t/ j
    def readFile(file_name):( k* }0 i* l7 a/ ?' l
        contents_lines=[]
    , L$ k* Y1 h1 I/ H$ j$ T    f=open(file_name,"r")0 l( o! r) ^+ g6 J" A% v3 f
        contents_lines=f.readlines()
    * P- \" n4 N( \& ?3 `2 L# s    f.close()
    # S5 Q, Q. V2 `: A4 |2 Q    return contents_lines8 N6 R  E, @: w  b

    - Q. q. Y: D# L4 u  a
    ( g7 i( q5 `2 o& C. k8 @9 H8 T1 Z, [- Y0 M
    #
    " Q- m0 v+ ^1 `$ E1 t#   解压rating信息,格式:用户id\t硬盘id\t用户rating\t时间, c2 f8 J- c$ Z
    #   输入:数据集合
    / z$ @' C2 {, K! n7 m  Z! _#   输出:已经解压的排名信息+ B3 }6 t) t* S# G3 w% Y
    #8 p4 u+ s  s  t& F
    def getRatingInformation(ratings):" s4 N8 V3 h8 {2 w9 t
        rates=[]
    ! @# _; x9 N! E2 ]    for line in ratings:
    : [+ W" ^4 S' \- y0 ^3 S        rate=line.split("\t")- t3 P; D$ C* g: k
            rates.append([int(rate[0]),int(rate[1]),int(rate[2])])
    & u' b& O7 P* K' I/ V    return rates$ a' j: e4 ]" T$ p  c

    ; \% _1 w0 `7 s; Q7 o0 i. j& g
    8 n' U: K1 h( h$ ~) j  Q; ?- y! n#
    ! w' f9 ^8 \4 ~% f) O" D0 c#   生成用户评分的数据结构
    , l* j- j9 i3 ^* t#   ' q- w9 r$ p, v& t- N2 _, j
    #   输入:所以数据 [[2,1,5],[2,4,2]...]
    ) t$ _5 J) Z# u0 C" Y3 ~4 V! _2 Q#   输出:1.用户打分字典 2.电影字典) i0 V" P( s* E! H+ v8 T
    #   使用字典,key是用户id,value是用户对电影的评价,
    9 R7 v/ ^% Q% C0 U) t8 U5 \#   rate_dic[2]=[(1,5),(4,2)].... 表示用户2对电影1的评分是5,对电影4的评分是2
    7 E. q, h  P$ ^  n9 Z5 V#
    0 |- y  o+ H% m( w, wdef createUserRankDic(rates):5 y$ ~3 P; E9 P$ x4 j; C. k
        user_rate_dic={}' j1 J/ L3 n. }" T" l" k
        item_to_user={}
    7 \) P, F) r: x# N    for i in rates:
    ) V0 |& p' Z" B: {' X: K        user_rank=(i[1],i[2])
    - I5 U3 g1 u2 J5 F) H8 A        if i[0] in user_rate_dic:
    & x1 j0 I+ _1 k' ^            user_rate_dic[i[0]].append(user_rank)2 W0 G; q; T( |9 J# ^
            else:; H% k( B" r1 A: I" j0 L
                user_rate_dic[i[0]]=[user_rank]
    2 X, F; X% c2 n% ]+ p            - O0 w- J% v  H, I
            if i[1] in item_to_user:
    6 |1 ]0 N+ m6 [+ P! J            item_to_user[i[1]].append(i[0])' e; c; _9 P: }2 b  _) b1 F2 m' G
            else:
    - l# a) v/ u6 i$ \5 a1 p            item_to_user[i[1]]=[i[0]]
    2 }7 V3 |1 R9 O6 B# m, L            ! {* z' X4 ?2 N6 j( n
        return user_rate_dic,item_to_user6 ^  ~+ r6 t  f" ~$ M) [9 d% {; O

    8 Z/ w5 g6 P8 L5 \
    % I' e6 ~5 j! H' `1 S/ E#; c* s2 e; @% w' p: [
    #   计算与指定用户最相近的邻居2 k" D$ D  i% S$ k% N$ K, p5 a7 Q' H
    #   输入:指定用户ID,所以用户数据,所以物品数据
    ! s/ c4 Q& R# [8 L! c7 {+ t#   输出:与指定用户最相邻的邻居列表1 Y' y' D4 e6 A) k7 h
    #% O" r7 [3 x" m4 j
    def calcNearestNeighbor(userid,users_dic,item_dic):+ T9 h7 Z0 p1 f+ {" l0 [) o9 |5 C' Z
        neighbors=[]
    6 M" A$ B9 h0 \  ?    #neighbors.append(userid)/ T# A  {3 T5 U! j' S
        for item in users_dic[userid]:
    3 {' M7 }: T6 U& U- w        for neighbor in item_dic[item[0]]:
    5 [" @8 [$ H, H3 V            if neighbor != userid and neighbor not in neighbors:
    2 P6 b7 O, t! K" c8 O$ L& n                neighbors.append(neighbor)
    . G" N$ }4 {' R( \; H  _* f      * i7 B' O) ^+ p: I6 f% [' I+ _9 s8 w
        neighbors_dist=[]
    3 G2 B1 X% \' ~7 E. P    for neighbor in neighbors:: \4 y& R& x* R% o! x' K% M
            dist=calcSimlaryCosDist(users_dic[userid],users_dic[neighbor])  #calcSimlaryCosDist  calcCosDist calcCosDistSpe
    ; Z- C7 |( a+ C        neighbors_dist.append([dist,neighbor])3 I+ I& F, ~, n! B/ E5 U
        neighbors_dist.sort(reverse=True)
    * f; X2 @3 F* h- H    #print neighbors_dist
    7 ]* N3 I' g  A; Q    return  neighbors_dist* l& J$ X3 R' z- A' `1 w$ O
    ) Q1 j1 W& C0 L- B% k: W. n
    6 m' q0 U# Y  B' M
    #
    $ l" g5 V" F- q! k& D#   使用UserFC进行推荐
    + W, ~1 f/ u0 `# Y9 i1 h/ ]: B#   输入:文件名,用户ID,邻居数量* J8 T  Y, I/ r
    #   输出:推荐的电影ID,输入用户的电影列表,电影对应用户的反序表,邻居列表
    1 G, b& p) `, ^2 G## L5 n' E2 Y, J( n$ |
    def recommendByUserFC(file_name,userid,k=5):
    8 w* q) N: q' d- ?  w   
    0 J2 D* P! y& y# [4 c    #读取文件数据' J1 X/ U; y1 a  N: K
        test_contents=readFile(file_name)
    / ]2 h" }$ n" l6 R& ~) C2 @. `   
    - }; z: o0 c) `( M9 O: W$ ?8 R% G    #文件数据格式化成二维数组 List[[用户id,电影id,电影评分]...] 2 R+ R, @0 Y. {2 _1 N9 W
        test_rates=getRatingInformation(test_contents)) L. |% V. K4 r' g6 h* L- a
        $ |1 |3 Z6 ~, x! @9 r
        #格式化成字典数据 1 U% o1 k  b# v* }8 O% O$ C. \
        #    1.用户字典:dic[用户id]=[(电影id,电影评分)...]/ m7 R, A5 H. N) t' w9 e8 L
        #    2.电影字典:dic[电影id]=[用户id1,用户id2...]3 j4 F2 M+ b/ f0 n8 F
        test_dic,test_item_to_user=createUserRankDic(test_rates)
      y9 z) Z7 K( g/ O   
    * ]6 f# K( d, g# `$ e! z: R    #寻找邻居
    ( D4 E9 [: e0 M+ r1 \  d    neighbors=calcNearestNeighbor(userid,test_dic,test_item_to_user)[:k]
    ! j( D2 c& E4 O, a4 r" S# m0 Y* k9 c        % \% D9 ]+ i0 {0 W. _
        recommend_dic={}# R3 v8 E$ d- G3 e
        for neighbor in neighbors:
    6 H8 E6 ^. W2 m. _; `. J        neighbor_user_id=neighbor[1]
    5 n" O& g7 B0 J% U        movies=test_dic[neighbor_user_id]+ b9 u2 L1 j% R0 G, s* i
            for movie in movies:. E% i# M) I1 Y2 {1 H$ a$ @+ ^& K
                #print movie
    5 j  k# x7 z( w( \- g            if movie[0] not in recommend_dic:
    3 `1 `* d' q* h# Q6 ~0 Q                recommend_dic[movie[0]]=neighbor[0]
    " l3 D  y& ?8 V: T4 ]- M7 @, d+ P            else:; h& V' k6 d) i
                    recommend_dic[movie[0]]+=neighbor[0]
    8 ^) a6 u" {7 h6 N. j& n0 K$ n    #print len(recommend_dic)
    : G) U# V2 J3 J! k6 n   
    $ U' h6 x( z! o, K1 Y    #建立推荐列表" ^6 a6 J+ ]8 {
        recommend_list=[]% O' i# I+ Z2 p% `- Q) {
        for key in recommend_dic:
    3 r5 `  [( X* \7 |; P$ K        #print key
    " C  b7 l6 I* ^/ R. w: `" R7 y        recommend_list.append([recommend_dic[key],key])3 p! G' t# }2 F# R" R
       
    8 I& [: A/ [: P% J/ k1 N1 m9 m   
    : B# E3 i; r) r( Z* w6 H    recommend_list.sort(reverse=True)
    ) m6 R( C! Q; R( ]1 h! p" P3 c; p    #print recommend_list4 L1 a' h' y2 d7 d2 M  V$ f) x
        user_movies = [ i[0] for i in test_dic[userid]]
    1 \1 e$ b4 i* f- V3 Z8 o* L. O" {+ u% ~0 j
        return [i[1] for i in recommend_list],user_movies,test_item_to_user,neighbors( F$ {0 z( x' ~% r2 E  c" w( a
       
    9 x% x* t* d$ q$ h& t2 S. {5 `   
    , B" I/ V/ d7 L. R& s" {+ l6 s5 e7 v. [9 }: e6 ]; ^
    #- D; T; e+ I! N$ v2 D$ T8 J- _
    #
      @4 p; [9 L0 |: k0 h#   获取电影的列表
    7 _5 W3 i3 m# I# I- {: ?#
    8 V: C4 p& ]8 J3 F#! R( L( @4 h+ [9 z( Y
    #
    7 S  ]: w, E9 ~- p& zdef getMoviesList(file_name):
    / L$ C; N8 |! ~; M    #print sys.getdefaultencoding()
    # y& T' z% E5 t& E- _    movies_contents=readFile(file_name)
    ) E' A) G3 }- e3 |( V" o3 [  z1 K4 y    movies_info={}1 \/ }$ X/ Q4 n& U' F& A1 _
        for movie in movies_contents:1 N- f8 j$ [# v  o
            movie_info=movie.split("|")! }: _. e! t& R! Y
            movies_info[int(movie_info[0])]=movie_info[1:]
    . D& w4 g8 R  a: c$ E  h    return movies_info
    ; |# f. i7 j( C9 |; g7 t    1 e* a: Z; V) h6 t* h6 H5 \
        ( f, Q. H* n4 \+ f
       
    - i7 Y' Y! P: ]7 ]#主程序# F. k) o/ X9 v3 Y6 e' p6 A; S
    #输入 : 测试数据集合
    & ]0 ?2 c& c, t+ Q6 ?if __name__ == '__main__':
    , R3 o$ v; t3 T+ K- f' H    reload(sys)
    $ @8 `0 `* }9 O    sys.setdefaultencoding('utf-8')
    ! Y/ g0 u, H! v  b0 j5 y    movies=getMoviesList("/Users/wuyinghao/Downloads/ml-100k/u.item")
    8 C( C( L2 Q: n7 h% Y  Q    recommend_list,user_movie,items_movie,neighbors=recommendByUserFC("/Users/wuyinghao/Downloads/ml-100k/u.data",179,80)
    3 I* N% j4 H1 F' \    neighbors_id=[ i[1] for i in neighbors]
    7 D" W( n: [2 q9 ^    table = Texttable()1 t6 K$ t: y' g0 b( L3 Q& ]8 P6 Z9 ?
        table.set_deco(Texttable.HEADER)
    2 ~/ K/ l8 y( N' K( S    table.set_cols_dtype(['t',  # text * K- H! r$ D# ]8 |( X# d
                              't',  # float (decimal). \  E/ C+ L  i% P
                              't']) # automatic8 O' H' }- r( k0 b4 x0 H' ^
        table.set_cols_align(["l", "l", "l"]): W$ l6 h  d; ~0 N
        rows=[]6 }8 o) F# e' V4 V% m
        rows.append([u"movie name",u"release", u"from userid"])
    7 r9 o* w7 Y) X  {9 \    for movie_id in recommend_list[:20]:" g5 |! e3 [# e5 \. o! Q
            from_user=[]
      K" Z6 ~* h" s- l; v7 O* {3 n/ P        for user_id in items_movie[movie_id]:( m$ L# N* m/ C4 \, T( v# O
                if user_id in neighbors_id:
      P/ n6 c, i1 h' [$ V                from_user.append(user_id)
      f) X$ t2 @; n  ~' e; @        rows.append([movies[movie_id][0],movies[movie_id][1],""])1 e. y9 G4 x7 T' h
        table.add_rows(rows)
    ; u* M5 L* U3 I    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 1 ~. ]" C. j- D6 G0 N5 E
    # -*- coding=utf-8 -*-% q# W1 \3 @. D- P5 e' t, [

    4 `/ e- @/ @, N! qimport math

    7 F8 r: O6 x# G! V7 i1 k这是什么语言的程序?
    ! f# I$ c. K% p! g; s3 H6 P3 c
    回复

    使用道具 举报

    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-9-4 23:02 , Processed in 0.441109 second(s), 67 queries .

    回顶部