QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 5318|回复: 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
    本人在学校参加暑假培训,需要这个算法做题!求大神赐教,感激不尽
    - \+ P4 C0 ~" e/ \) j6 n
    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 -*-
    8 J4 `+ o4 L" D* ?( y- B
    7 W" l) q( ]1 m- S& j% \# rimport math5 n, e* F3 {8 J% u
    import sys: U: P5 \+ q8 G8 s, K9 H# R# |  _
    from texttable import Texttable
    / L$ g, e& H& j; X3 s7 o/ S! Y; ?+ k5 b8 V, t% |' W
    + @% V( X; X7 O% C+ g
    #5 Q6 z3 p3 n  F0 N: Q7 i3 K
    #   使用 |A&B|/sqrt(|A || B |)计算余弦距离
    : k: V9 G( ^* M5 |#8 T, a( [( U2 Z' a7 G; f5 ]
    #! d$ S0 a- Z0 o/ G
    #
    ; F7 W) |- P- l6 E1 d& c1 ]" Q6 ndef calcCosDistSpe(user1,user2):# z2 S8 p+ z1 W% d
        avg_x=0.05 \: {* _, @6 L2 s1 M1 o: D
        avg_y=0.0
    ! [/ j. }3 d( u    for key in user1:
    ) }0 h  s5 }3 {% g% P& A9 s        avg_x+=key[1]- I5 ]6 t1 m$ _/ L8 d
        avg_x=avg_x/len(user1)
    0 _& [( ]  w) l. A5 W   
      V: D+ M8 k6 n, |6 q+ G    for key in user2:9 f! d7 O4 ~! m$ `4 g
            avg_y+=key[1]
    , c0 z6 h- t6 u" C  P8 A% i    avg_y=avg_y/len(user2)+ |* B8 Y& H+ @
       
    , o+ `1 O( {- }% ~- z9 n6 ]    u1_u2=0.0- h0 R# b. v: u6 ^* P- b
        for key1 in user1:' z2 l/ k6 r( b' O/ D8 m! i" V  Y
            for key2 in user2:, |5 ^2 J) r1 |% @# j% H5 i
                if key1[1] > avg_x and key2[1]>avg_y and key1[0]==key2[0]:& M8 v5 q; y5 i
                    u1_u2+=15 `" M  y0 \* X  c( f
        u1u2=len(user1)*len(user2)*1.0
    ) A8 s; u: b& N5 |    sx_sy=u1_u2/math.sqrt(u1u2)
    - T: p0 ]( g' o6 u# L; p8 ^    return sx_sy
    8 l5 r" w$ C5 s; j$ `
    $ W1 i$ @5 M2 C
    9 r+ P5 `" D( p* p  g#
    + p9 A2 U/ _0 S4 i5 }#   计算余弦距离- R* {3 s. b% g  J+ n3 c
    #  e. e) |- H$ ?- z( N- S+ b& U
    #
    ) d' m: {1 T$ I2 {4 w6 X; _def calcCosDist(user1,user2):  D- W2 E1 s% E( J& P6 F
        sum_x=0.0" |  f. {) g; G8 N5 H! b
        sum_y=0.0$ j$ r9 n4 M1 N" D
        sum_xy=0.0
    : ~% I6 P% \$ w    for key1 in user1:% Q: w* N; X* ?. G8 o
            for key2 in user2:9 _" g! R" c' w0 O
                if key1[0]==key2[0] :5 q* F- y! `! e# j. L; V
                    sum_xy+=key1[1]*key2[1]
    ( K) [% R2 m$ ?, W! W% {                sum_y+=key2[1]*key2[1]9 X5 Z* I! X& a" |
                    sum_x+=key1[1]*key1[1]5 A) e7 {; Y2 Y+ o) n2 [& o2 F
        # ~/ |+ J6 }: z+ {2 F
        if sum_xy == 0.0 :
    3 J' ~; I' Y! o  w7 V& l        return 0
    2 @: T, T8 J/ Z) ~    sx_sy=math.sqrt(sum_x*sum_y)
    1 V8 Z  P& {4 F" v    return sum_xy/sx_sy! o+ T5 {+ U( e- O0 W5 V" B+ b

    # _7 |4 P, s' p! u
      [% O+ P* y, @( x#7 s! W0 Q% V6 M3 h
    #
    : K! D, n* k, j" b' R) K#   相似余弦距离
    , P. u+ I& c( Z+ B#7 r# T* j2 B* K
    #
    : S. k, e" R# R1 k#
    ! v# Q. K4 t0 @; kdef calcSimlaryCosDist(user1,user2):
    5 Z! E+ B: s3 Y    sum_x=0.0; S3 R4 |! ]" V; D' `$ r7 h8 d  o
        sum_y=0.0
    * {9 Y; \0 |% F5 w! j! p  ]    sum_xy=0.0
    ; |9 H/ E. F4 k( N: b    avg_x=0.0
    ! Q6 X/ b6 q, ?. v  i0 q" K    avg_y=0.08 U) }% z3 L+ M
        for key in user1:
    # P+ i4 ?* \3 d        avg_x+=key[1]* j  s; w/ V: U* b. o$ h6 H
        avg_x=avg_x/len(user1)
    ' Q, e# a3 U1 N7 y+ t) N% h4 o   
    $ M3 T- L( F0 v1 g' ~/ Q    for key in user2:3 q3 D" ^" S, P
            avg_y+=key[1]5 C) b  W  R; B
        avg_y=avg_y/len(user2)+ [8 r% M. G) U2 ?% f  e5 J% x
        # m) |9 Z  @2 j) Q$ J& o
        for key1 in user1:
    2 j$ l# E3 D5 T6 Y/ i+ t1 l: C        for key2 in user2:
    ; Y+ A9 R' P: m, {& Q# \/ Y0 n            if key1[0]==key2[0] :9 k* N+ L0 c4 T- [8 f
                    sum_xy+=(key1[1]-avg_x)*(key2[1]-avg_y)
    2 Y2 R( d1 s" `. a6 Z                sum_y+=(key2[1]-avg_y)*(key2[1]-avg_y); R! t9 I9 Q9 |8 l9 P
            sum_x+=(key1[1]-avg_x)*(key1[1]-avg_x)9 f: b0 D5 D2 v1 N( K8 V* n
       
    6 l" b! N! ]5 `1 V, L1 t( P2 ^    if sum_xy == 0.0 :7 w- R' g. ~' k. T
            return 0$ j& O2 }0 B7 g4 F# B8 V/ a( B- p
        sx_sy=math.sqrt(sum_x*sum_y)
    8 S- d' p; r  R7 b' ~    return sum_xy/sx_sy, z, k* f. F' X; x9 Z/ f
       
    7 R9 [1 l" e7 d# z
      p# Z  E: h* d* F- V#
    ( l) c/ ?+ _* \: R0 Y#   读取文件
    2 J- a# ~- w! d8 L#
    ' r( n% f7 a, [. f: Z3 O#: w" h! M" K: ~+ C! f0 Y4 t4 M. M% T
    def readFile(file_name):: J# M; h9 Z3 B# Y  u7 |4 h
        contents_lines=[]
    ) W! e& p. u+ O6 y* U. V- H    f=open(file_name,"r")) n" h7 q7 h  N) ^
        contents_lines=f.readlines()  W) Q  b) G" b* s/ @& U/ ~
        f.close()
    ! H; {3 t; B$ j2 k    return contents_lines; r7 w% z* W& f" u( `" \
    / X/ r& Q6 d* y' L

    / t$ ?# A+ M$ _' `+ z6 K2 u; y4 ?2 A6 o( R- ~6 h  L4 K, Q" c; Z( w
    #
    " f* o/ t, K4 B7 |! }% ~' ?#   解压rating信息,格式:用户id\t硬盘id\t用户rating\t时间
    7 [6 q" }: C( e5 o2 A8 p: N#   输入:数据集合8 w& w% c+ K/ k4 H3 V) V7 `7 v$ v
    #   输出:已经解压的排名信息
    ( [' `, v" t# Y1 p8 O#
    0 }' m( @4 P9 g7 F# p9 ]" X, Y" Cdef getRatingInformation(ratings):% e& Z$ N: U0 g! ]  E) |. l
        rates=[]
    7 L  l; ]' ?, ~    for line in ratings:6 H$ p5 S$ x8 _8 O% T* ]
            rate=line.split("\t")
    7 \; r# d; ?% H        rates.append([int(rate[0]),int(rate[1]),int(rate[2])])2 y9 h% D& S- P9 x' h. U
        return rates4 k2 O" W; z& @7 v! u
    # e$ S, J" ]+ t+ Z% D6 J
    / p4 y$ l2 C8 t( V5 K
    #
    2 R: I1 o0 s$ a#   生成用户评分的数据结构
      p; C6 k! u- _+ F0 z9 ^#   8 o$ W1 \- {3 h0 h0 y9 j6 E* k$ N% E
    #   输入:所以数据 [[2,1,5],[2,4,2]...]( T/ x5 |: W. Z* s) j
    #   输出:1.用户打分字典 2.电影字典# C: A. m  t  F7 ^: e
    #   使用字典,key是用户id,value是用户对电影的评价,
    ' j5 h4 ?' V; w" o#   rate_dic[2]=[(1,5),(4,2)].... 表示用户2对电影1的评分是5,对电影4的评分是2
    ' I" a$ t- u8 {9 v1 S* C; u9 ?#
    $ ^, \9 v1 m0 ~. C! Pdef createUserRankDic(rates):' _" M- J4 @! w* Q
        user_rate_dic={}" p( M0 L2 }3 L$ v7 E2 E& A/ q
        item_to_user={}, I( `) Z* \- d
        for i in rates:
    6 c. F/ X/ k: W' q        user_rank=(i[1],i[2]); p: [. G' S. J2 U7 S3 w0 e
            if i[0] in user_rate_dic:
    5 z, ~" }/ O2 G" J4 I1 a8 u1 H            user_rate_dic[i[0]].append(user_rank)
    ; B) B- j% v$ y" ^- F5 |        else:
    % E4 @, L& i: f( m* [) g            user_rate_dic[i[0]]=[user_rank]+ \1 v1 Q( L6 A4 `( G" r6 K
                
    1 E" f2 y7 w  k" K        if i[1] in item_to_user:9 Q/ t6 u* h  o6 B$ t* o6 v% I* B
                item_to_user[i[1]].append(i[0])
    # }' `( e) u) M& Y) `! ?: R! X        else:2 ?% ]: v8 l% ~
                item_to_user[i[1]]=[i[0]]
    ; \( A$ k) a, H: H            ( i5 ?8 U* E/ G9 B5 z
        return user_rate_dic,item_to_user  ~" m+ w+ W8 ~. B' c- y- P+ K
    5 P2 G8 T; x6 |: ^1 P1 b6 f4 {
    & V( M5 ]* R9 A5 d
    #" S2 F2 x( g. C8 F' Y
    #   计算与指定用户最相近的邻居$ k$ Q; Q8 w/ _6 h' q: M
    #   输入:指定用户ID,所以用户数据,所以物品数据
    ! `! _5 T. y( q4 W. Z6 F#   输出:与指定用户最相邻的邻居列表1 t: K  }: z8 {, Z
    #
    2 E  R. Z( ]5 i( j% z" ndef calcNearestNeighbor(userid,users_dic,item_dic):/ H' h3 w  K7 I/ K; Y  q/ ]
        neighbors=[]
    1 F6 H8 Y9 D  W- T: G/ [4 m    #neighbors.append(userid)
    # ~  J* ?) j% U    for item in users_dic[userid]:) Z: p- ^6 X# ?1 N2 h
            for neighbor in item_dic[item[0]]:
    6 v- N2 t/ \( x$ b6 |% Y            if neighbor != userid and neighbor not in neighbors:
    ) x8 L- [5 ~3 G" L2 s  W' Q                neighbors.append(neighbor)
    ; f% v  x5 f- w, E- c      ) ]! W/ q  T  A2 M; \8 C2 R
        neighbors_dist=[]9 Z7 \# \2 e# N7 {% l& J
        for neighbor in neighbors:3 S% {7 Z" |( X& p
            dist=calcSimlaryCosDist(users_dic[userid],users_dic[neighbor])  #calcSimlaryCosDist  calcCosDist calcCosDistSpe) m4 g" B( |0 o+ D; ^; O" |
            neighbors_dist.append([dist,neighbor])  R- k0 V+ k4 ?3 e) s' q
        neighbors_dist.sort(reverse=True)! P) a* n  {, n3 m) G. n
        #print neighbors_dist
    ! w, ^) }7 E0 b8 q) J) o& U- s    return  neighbors_dist9 d2 q& Q, {% \: \/ ?, \

    0 ^6 O+ \2 j8 S8 t+ W
      s, u* e; ]4 g: f5 ]7 M#$ J  g! I7 J1 [9 [; v3 D
    #   使用UserFC进行推荐0 I( s. v7 {" Z, ?0 i9 P& I4 _
    #   输入:文件名,用户ID,邻居数量
    3 P5 g" }$ S" F% w: U. a  I3 W#   输出:推荐的电影ID,输入用户的电影列表,电影对应用户的反序表,邻居列表
    6 E* H, t9 l* Y  J. }# z. k9 G#
    7 X/ c5 }. k, y. d% h. J+ Xdef recommendByUserFC(file_name,userid,k=5):
    " C. |7 M1 c% d1 j& P" C; O8 g8 K    ( q/ q; P) F. ]- t
        #读取文件数据/ Y/ q0 C/ O2 a5 `& }; Z. `
        test_contents=readFile(file_name)& t5 L" J$ v/ @7 z, @
        5 B6 J( E8 O( [8 T8 f6 I$ N
        #文件数据格式化成二维数组 List[[用户id,电影id,电影评分]...] ; Q6 H4 u( e' t' y2 G; e
        test_rates=getRatingInformation(test_contents)
    + E- w6 d5 l3 T6 i0 t   
    7 @* {8 v% L/ D0 w6 K6 m8 c    #格式化成字典数据 & \& i5 d+ [) }  E1 z0 a# p9 L) G; P
        #    1.用户字典:dic[用户id]=[(电影id,电影评分)...]
    9 L- r  t6 }2 ?1 ~    #    2.电影字典:dic[电影id]=[用户id1,用户id2...]% p& H, w  K1 Z( h
        test_dic,test_item_to_user=createUserRankDic(test_rates)! ^9 v6 e& L: Y  n) q
        6 b3 {& r& W7 n4 \  Q
        #寻找邻居' U! \3 h( Y6 B$ D: M) R# d, o
        neighbors=calcNearestNeighbor(userid,test_dic,test_item_to_user)[:k]
    / q: ~: P1 g, d0 w/ L* m        
    ' l. G* f3 w4 p* i  c" z5 j2 _    recommend_dic={}7 s% l$ d1 F0 L) T( \
        for neighbor in neighbors:
    ! |& q# ?3 B8 b7 p5 I' `        neighbor_user_id=neighbor[1]
    ! z9 y" }' S6 r- G, T" g        movies=test_dic[neighbor_user_id]
    / d0 N, S& {: o/ V/ r        for movie in movies:2 |. r! [: w4 [9 N5 E
                #print movie8 `6 F, O% C+ D% Q0 u, O& L) u6 a
                if movie[0] not in recommend_dic:
    : R4 }- m+ x* @6 G; J3 ]# W                recommend_dic[movie[0]]=neighbor[0]9 v. o; J: i8 l  i
                else:
    3 O' A' s4 V' `$ r& y2 E7 T/ d                recommend_dic[movie[0]]+=neighbor[0]
    ! S1 z% ]2 Q8 {) ]- U1 ^1 D    #print len(recommend_dic)
    % N4 W4 ?( L, F+ [   
    5 b9 u  Z) e# [0 b7 x    #建立推荐列表
    % o, T' Q( X& N1 h" f    recommend_list=[]* i. s# C, p- O6 U6 B1 C$ @: W
        for key in recommend_dic:
    / K4 j8 s: X3 ]8 u9 h        #print key
    2 }" |5 j% F0 v" \# D        recommend_list.append([recommend_dic[key],key])
    4 a: K  M6 R3 ~   
    7 S5 l3 s  `% V- j4 a. i   
    ) r1 h* @6 b' h8 S8 _3 n5 K% R    recommend_list.sort(reverse=True)9 m5 r* e% z& }. z3 N6 |
        #print recommend_list% ]0 E$ v2 P" P
        user_movies = [ i[0] for i in test_dic[userid]]) n( v8 S, X8 j; Z1 \1 P

    8 h! }& H# G' v9 I6 X  t    return [i[1] for i in recommend_list],user_movies,test_item_to_user,neighbors* o2 y$ J$ P. Y5 {
        0 S* @. F% ?5 [( W1 ?6 l3 I  ^
        # i) ^' @- F+ d% u
    ; \$ V3 m+ ?- E( b9 u1 }
    #
    : f6 }7 X. Y% T1 @# m' u: M5 x#
    : p' O- K  R7 d1 O1 k4 a! Y2 r#   获取电影的列表# \, g+ A' l4 i3 B" W9 V0 n, x
    #
    & {4 _- J  C8 F9 a2 h  m#
    $ r1 ~; p" v' }) c: `2 l5 Z# W$ l#3 ^1 S; Z7 o. L
    def getMoviesList(file_name):& F3 g' F, ]2 x8 z- b8 l
        #print sys.getdefaultencoding()
    / v! j; ?3 P2 N4 H+ m  x    movies_contents=readFile(file_name)
    6 n$ f/ x& G2 H& L" J, ~    movies_info={}
    8 z( B; n+ z8 b    for movie in movies_contents:+ B9 q- P5 Z6 n* n9 {/ a
            movie_info=movie.split("|")# t3 {) U3 v0 B
            movies_info[int(movie_info[0])]=movie_info[1:]- |# a: k# v" `+ @4 T3 m, t+ U6 M: w: [
        return movies_info
    1 B# b3 v# X# g& @# S' u/ W# i    5 C- B/ Z; A, o' A# q( |; o: O
       
    ; ^8 U% N0 a$ h5 O   
    & ~7 f. F, R  i% E$ |#主程序1 w6 x. @  N' @& b% m' H% h
    #输入 : 测试数据集合+ h  w* }: k: F0 W8 Y
    if __name__ == '__main__':
    2 a# g, A- q, ~4 K" H  k% ]. ?0 s    reload(sys)
    3 B! X1 ~! I! K' x0 v- `0 U    sys.setdefaultencoding('utf-8')
    & u/ N2 o; W8 l5 i8 l8 ^: I    movies=getMoviesList("/Users/wuyinghao/Downloads/ml-100k/u.item")
    . ?$ t! ]/ h5 d! z2 l% }    recommend_list,user_movie,items_movie,neighbors=recommendByUserFC("/Users/wuyinghao/Downloads/ml-100k/u.data",179,80)& U8 x4 M5 K& ]% E) |- q3 z
        neighbors_id=[ i[1] for i in neighbors]
    6 W! x: ~2 W' v  _+ x    table = Texttable()  l- {+ w( G& J7 Q
        table.set_deco(Texttable.HEADER)
    ( m8 ^! d. _% H8 u2 f$ ~$ g    table.set_cols_dtype(['t',  # text 3 l; Y: ?! Y8 H+ y
                              't',  # float (decimal)
      `* T3 I( P$ D                          't']) # automatic
    . Q+ w9 o' J6 f$ J6 l, r/ G3 D    table.set_cols_align(["l", "l", "l"])+ h* \7 O% y, m& }
        rows=[]
    / \' K: p% G9 Z8 }9 U% c7 C* Z    rows.append([u"movie name",u"release", u"from userid"])
    4 N) t# j5 i) O$ J( w0 r    for movie_id in recommend_list[:20]:
    ' E* M: v% C& y/ e9 ?3 Z        from_user=[]5 G( [6 T# Z" y0 P6 t% I5 P
            for user_id in items_movie[movie_id]:# Z5 k! r$ `. p6 W5 R
                if user_id in neighbors_id:# ?& n+ g1 ~# m8 B4 Z
                    from_user.append(user_id)
    4 k" f- S: h8 a- @        rows.append([movies[movie_id][0],movies[movie_id][1],""])
    4 X' p$ J" U* v6 R. L2 {) C    table.add_rows(rows)
    ) ^( B* _' E! x8 Y6 U    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
    & ~; m: n: J% A" c1 q" l# -*- coding=utf-8 -*-& L2 f, r8 `5 I: S
    * \; ?% P) E# J
    import math
    8 F; e  T8 N4 V, v3 a* U
    这是什么语言的程序?
    ; q- L: D- u# [( N
    回复

    使用道具 举报

    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-7-19 16:01 , Processed in 0.372479 second(s), 73 queries .

    回顶部