QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 5256|回复: 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
    本人在学校参加暑假培训,需要这个算法做题!求大神赐教,感激不尽
    6 r9 V: H7 {$ h% C
    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 -*-1 B6 H* _) y2 ]0 z/ ], y: J7 c
    ' }6 O8 R. T* {+ j2 m
    import math
    ! W3 x  @9 a$ Mimport sys
    * Q. d3 u, b: G' S( h9 G0 N) M2 Ffrom texttable import Texttable
    & N8 c' A1 h6 f9 Q2 M& h" h3 v- V
    ! N( w# V& b, U9 N8 j: x
    & v2 N$ N3 ?8 ]; p) l) d' i3 h- e#
    5 j3 P$ y; m/ ^' Q+ h#   使用 |A&B|/sqrt(|A || B |)计算余弦距离
    ! I. J% z5 U6 x! k: b0 }3 E#
    + e) ?, @3 `& D+ ^( V; {) M#
    6 C& L. l) ?- X' ^! L) |#
    # V4 V( J6 _3 f2 ], [( G5 ddef calcCosDistSpe(user1,user2):) q% G" C0 j) m; ^) M
        avg_x=0.0/ _' T; f/ W( k6 \  d4 c) i
        avg_y=0.00 t0 |8 U3 a6 o
        for key in user1:
    0 j; g/ g; A& H3 x1 w* R4 ]" c        avg_x+=key[1]/ M+ \# t0 X- x9 z( x: u
        avg_x=avg_x/len(user1)! d" X. K# V2 l- Q' T
       
    1 d; i; l- G: e2 w9 T  o    for key in user2:$ g+ z3 [# h) U
            avg_y+=key[1]
    ! x2 T$ [+ h/ \$ s    avg_y=avg_y/len(user2)2 c/ M/ c9 C. g9 N
       
    ( Y+ r) z* Q$ K: W    u1_u2=0.0# f' p; ]% o. {; T
        for key1 in user1:
    / @3 R$ ~! N" y9 j- N        for key2 in user2:
    * f$ ]: u/ {. I: Q2 H/ X3 U; Q( u- z, s            if key1[1] > avg_x and key2[1]>avg_y and key1[0]==key2[0]:
    : `1 w7 x4 B6 c9 q1 y5 ?                u1_u2+=1: _0 `) G- ~# ~0 H/ `+ Z* ]
        u1u2=len(user1)*len(user2)*1.0
    & o6 A: \6 k; `( Y6 |3 Z    sx_sy=u1_u2/math.sqrt(u1u2)
    . Q2 T4 @4 q# F/ m: _    return sx_sy
    6 v+ W: F7 H5 l, I) J/ r5 C4 I+ s: {8 h/ S
    * W9 F& r* \  X! k  D  n. E
    #
    5 L: C8 A3 \  [1 N+ C#   计算余弦距离; z2 y( l, a' W+ r; c) Z
    #
      Y2 c6 g3 \+ [, N#
    $ M  X8 D5 l+ r3 }& O9 [$ o: edef calcCosDist(user1,user2):
    : F9 \4 j+ ]- y    sum_x=0.0
    , Q& ^8 T1 c% [% v) F    sum_y=0.0
    % F' o4 D- K1 W+ M    sum_xy=0.0( [5 m, a1 ^$ S; u* [& ]& p
        for key1 in user1:
    0 F- h' x. h6 N        for key2 in user2:& b4 b, q2 O4 ~9 k: y
                if key1[0]==key2[0] :
    ' t1 K9 t4 L1 [& G  d                sum_xy+=key1[1]*key2[1]
    " f! {% J7 U5 q# |% O) U! S6 t3 N                sum_y+=key2[1]*key2[1]
    ( n2 l/ O, ^* F! B                sum_x+=key1[1]*key1[1]$ x5 J, Q. N) Q! `9 V0 k5 m
        ; P. {/ V6 T: b7 w- U
        if sum_xy == 0.0 :% z2 S& o% y' Q1 i3 Y3 U0 ^1 s
            return 0, ]. U( e( D# j% u9 u' f
        sx_sy=math.sqrt(sum_x*sum_y) 7 P, D! g; p' m: A8 |) z; C: g2 R
        return sum_xy/sx_sy/ d: u( H1 T% i) S) [
    6 Z# Y- P5 R& x: d) T# C3 d8 p4 {1 A
    + ~$ a5 c8 Y* S
    #8 _8 u7 U! m1 ^5 J( p( i, z
    #
    ! V7 m7 C  W" n- @  A#   相似余弦距离$ e* V# Q6 u. W/ I, G; k& g; p
    #1 T; T) X+ z# [# G
    #, f" L  l1 g% u1 U# I
    #+ u* @9 c% h. I% {
    def calcSimlaryCosDist(user1,user2):
    ( ?- F& t0 J. {3 K2 {7 q8 u    sum_x=0.0. @& _. w3 y4 u/ j, ]
        sum_y=0.00 B5 M. P0 ^/ s+ K6 F
        sum_xy=0.0: y: l2 O) L7 M( y
        avg_x=0.0
    2 k! n9 j3 X0 J5 O  W" \* n/ N    avg_y=0.07 _" b& f8 T# a7 v, ]
        for key in user1:
      T: D5 ~5 ]. r        avg_x+=key[1]1 t7 L$ g2 P- h8 B
        avg_x=avg_x/len(user1)* }$ w0 i% k! t) @/ z
        - Y( R/ p  `* X, z" N
        for key in user2:
    $ Q! }  V; }" e& G" h  Z) ?        avg_y+=key[1]1 M6 s  i8 h* a1 @7 E/ s
        avg_y=avg_y/len(user2)2 R1 j6 E8 I- r
        $ R. a/ Y3 I( L& M
        for key1 in user1:7 [' E, [- |' ~
            for key2 in user2:
    8 J! ^6 P" M  P1 O/ t7 x$ i, U3 G            if key1[0]==key2[0] :: e! h# b' _/ _  `' [/ W' D
                    sum_xy+=(key1[1]-avg_x)*(key2[1]-avg_y)
    7 a( d) W( [) P& }) ^# z' Q- M                sum_y+=(key2[1]-avg_y)*(key2[1]-avg_y)
    - D' ^6 g3 T8 }* A8 I        sum_x+=(key1[1]-avg_x)*(key1[1]-avg_x)
    7 ]2 e' L2 b+ S4 M, @0 B* Y0 N   
    ; S) N2 g  ]7 P- U    if sum_xy == 0.0 :
    ) l  B# q, m/ X% X! f6 k        return 0/ z/ ]2 C, V" C5 I8 b' W& w
        sx_sy=math.sqrt(sum_x*sum_y) . x9 y7 \/ u$ D7 I
        return sum_xy/sx_sy
    7 _5 Y5 U4 i: d  j    ' e: T: C. Z* A9 d

    , H9 m. f; N' E1 Y#! \" n; r- S( \; ^' U+ t+ Q! @
    #   读取文件
    * U. T" J8 ]$ y! f#
    . [- a+ R1 M( O: L5 X) r#
    . f; g8 ?% k" f* zdef readFile(file_name):
    ; m3 W; S0 q2 G5 `& q    contents_lines=[]8 a( g  g  r( k" \
        f=open(file_name,"r")
    - r' U+ ]6 Z+ Q+ t    contents_lines=f.readlines()0 \# f8 ], F; d0 c% R6 k
        f.close()# e* d7 u! F# B2 o3 Q1 S9 J  A
        return contents_lines
    / M7 S* P8 _  V7 n
    % ^* P  }- B$ n! ^9 X7 x" a; S$ V+ _
    0 C6 V: }9 Y  R& x
    8 F* A* K, o9 T) \9 [#4 ]9 ~# q' s" f- {% i% d
    #   解压rating信息,格式:用户id\t硬盘id\t用户rating\t时间# G( ?  Q; s+ _, }* v# D
    #   输入:数据集合
    * O: R7 b6 Y+ i; h* h; y+ `" V#   输出:已经解压的排名信息
    4 {, y% \+ `; J8 S) ^6 D#
    8 l2 @7 W4 f7 d: i& Z! Qdef getRatingInformation(ratings):
    " K8 k4 w: ~9 h$ E1 U* `% c    rates=[]$ j0 d3 a3 ?/ b
        for line in ratings:- r' ]& B- V7 @+ P2 z0 [+ A
            rate=line.split("\t")/ Q5 M5 A0 _7 O+ U, H
            rates.append([int(rate[0]),int(rate[1]),int(rate[2])])/ l. `; O. x1 P7 ]
        return rates( w* z1 Y' ]8 r

    6 `$ g3 p; U: M0 O9 z7 I& M  z: C9 b: p0 y! H1 a; p* S- V
    ## Y- B. z* [7 a& j
    #   生成用户评分的数据结构- l, i; d. p  T& S7 D  l2 z3 |
    #     C" E9 |9 y" i
    #   输入:所以数据 [[2,1,5],[2,4,2]...]
    2 |% O: e! g) G" |' V- |#   输出:1.用户打分字典 2.电影字典
    2 l1 J% h+ D  n. |; J6 Q+ p#   使用字典,key是用户id,value是用户对电影的评价,( i+ c- ]) M% {
    #   rate_dic[2]=[(1,5),(4,2)].... 表示用户2对电影1的评分是5,对电影4的评分是2: s' ^8 o) X9 ^. _
    #
    & U. j: i  i$ w8 Gdef createUserRankDic(rates):
    8 M+ t8 @" y7 T    user_rate_dic={}
    7 j9 [+ O- z  F8 B! w    item_to_user={}; g7 j4 G5 i$ \
        for i in rates:
    ; \9 W3 {% N" n2 T4 X( O; W        user_rank=(i[1],i[2])
    8 o; V2 Q. R3 C# L7 C% x        if i[0] in user_rate_dic:
    ! Q* L/ I  W/ D* f1 z% X! r5 p! y            user_rate_dic[i[0]].append(user_rank)& t/ b. c4 s8 b: A, D
            else:
    0 L! f7 Y& m) L            user_rate_dic[i[0]]=[user_rank]# m7 f! \: y" Z  c4 i
                0 u# M! r2 G0 [3 _
            if i[1] in item_to_user:* _$ ?1 R$ g& Y# y
                item_to_user[i[1]].append(i[0])- o7 @! C" C* r
            else:
    # o' f$ t: @  i/ u6 u2 {            item_to_user[i[1]]=[i[0]]' F9 Z1 p: q* G
                
    ' M+ K1 X6 h, o. a* B4 w    return user_rate_dic,item_to_user7 a  C( k- K6 X/ M! r1 t1 W' w

    4 X2 i! |" w: u: r& Y7 Y
    & \/ C4 B$ _: \$ K! |  q% }#9 m! @  ~$ A7 k" e3 y/ N
    #   计算与指定用户最相近的邻居3 k# t/ ?! }* B
    #   输入:指定用户ID,所以用户数据,所以物品数据
      V7 x  [- I% U#   输出:与指定用户最相邻的邻居列表
    - [8 A3 C7 ~8 ~/ e0 ?, ^#
    + K6 N# `* K0 B# |' q' t( f4 Hdef calcNearestNeighbor(userid,users_dic,item_dic):! @! v& D( H8 E. e0 F) i  z$ M
        neighbors=[]
    : S9 h/ r& [# n8 g' G    #neighbors.append(userid)6 r8 _' g. f7 `  G
        for item in users_dic[userid]:# e; p0 I  {6 r+ d9 `
            for neighbor in item_dic[item[0]]:9 c8 L9 y  b# Y# Y* l0 R
                if neighbor != userid and neighbor not in neighbors:
    ; }9 g  i: A" Y0 _5 x7 ~1 B5 p4 `, A                neighbors.append(neighbor)" ]* `5 a3 K) o% {1 r
          1 H: F- I" {1 Z1 F2 b/ H0 z
        neighbors_dist=[]% K% L# h9 [8 b, G& u7 k
        for neighbor in neighbors:0 d( @$ `8 {: B' w6 u
            dist=calcSimlaryCosDist(users_dic[userid],users_dic[neighbor])  #calcSimlaryCosDist  calcCosDist calcCosDistSpe
    5 H; v: N% K" G# |3 \/ X0 T. n        neighbors_dist.append([dist,neighbor])
    % j9 m4 `' N2 ]. w6 F0 B) f    neighbors_dist.sort(reverse=True): F9 ~" ^, w8 y: t, }' Q
        #print neighbors_dist
    " p9 T* n- ^8 ^' z    return  neighbors_dist/ N; T/ s& h6 v& z+ e) X  d4 `
    * r4 L* Y+ [4 I8 p' \/ r# T6 P4 y" b
    / r% n' L( Z! P: W* ~# i% k* }
    #+ J* C2 m8 t7 s& p: z3 T+ {
    #   使用UserFC进行推荐5 E+ p0 v3 S' b& @# O* F1 ^
    #   输入:文件名,用户ID,邻居数量
    2 u7 M! n) c* d+ {#   输出:推荐的电影ID,输入用户的电影列表,电影对应用户的反序表,邻居列表
    5 X6 q+ ?# u6 P+ k$ T#
    $ h9 d: V# s2 m8 x% c8 @8 vdef recommendByUserFC(file_name,userid,k=5):
    2 j, o* `' R$ _5 H# }   
    ) q6 \: s8 X4 i. Q1 m    #读取文件数据
    ) C* Q: E. b- h; ]# y3 Y    test_contents=readFile(file_name)) n" N' a& b* T( a" \
        / e0 e/ L! k7 M$ t$ B
        #文件数据格式化成二维数组 List[[用户id,电影id,电影评分]...]
      ]7 O2 p  c2 z& J6 Z! x6 W6 k    test_rates=getRatingInformation(test_contents)
    ) z+ E# h2 Z6 R& Y6 o   
    ' t" e0 Q$ B9 |# F7 \2 b    #格式化成字典数据
    2 P* o. \1 H1 m  g, `! g9 D$ j1 x    #    1.用户字典:dic[用户id]=[(电影id,电影评分)...]
    6 w# T" j3 [+ @* ?    #    2.电影字典:dic[电影id]=[用户id1,用户id2...]" @6 g! h0 N( V8 r% Q% y6 s
        test_dic,test_item_to_user=createUserRankDic(test_rates)
    ! ?( W8 O. }2 x, }3 m4 K   
    " c3 N, K8 n4 l4 W2 h& D7 q    #寻找邻居
    4 Q& t0 ]  S9 G7 J( k    neighbors=calcNearestNeighbor(userid,test_dic,test_item_to_user)[:k]5 V. w4 x" T! ~4 M3 t$ n
            
    0 _- N( S! c: n7 J/ t; m8 B    recommend_dic={}
    % K. N$ F# G) Q- Q    for neighbor in neighbors:7 _6 v  E/ ~% ]6 F5 Q) G" |
            neighbor_user_id=neighbor[1]
    & N% G9 k: C) ]5 ?. r! E; k: t        movies=test_dic[neighbor_user_id]
    3 N+ O- {' p) d' _, \1 y- R        for movie in movies:- R3 M, }' _3 s& Q1 N
                #print movie
    2 ]$ R' ~; z* b+ O            if movie[0] not in recommend_dic:& w! ~: f6 q: s6 ~& P- J* z; h/ x
                    recommend_dic[movie[0]]=neighbor[0]
    / V# C# J: Z- @            else:
    # R6 i+ j4 @6 k. s8 o5 s                recommend_dic[movie[0]]+=neighbor[0]- v( x; x# Y, Z, `2 \
        #print len(recommend_dic)
    ( D% j& M5 ^) N* s% b# x0 L   
    7 z  V, d! c2 N3 e    #建立推荐列表
    3 d# g+ V4 [3 o- _/ Z    recommend_list=[]- N, Q* {4 C' e4 R/ z8 W! l
        for key in recommend_dic:  o* o; E3 }" w- q6 @. A7 m! u
            #print key% C6 d# p" i4 c. c6 P
            recommend_list.append([recommend_dic[key],key])
    . |$ C7 m& b: n- W& A% y, [3 j   
    " f: K8 h& ?4 w# S    ' k$ \- K7 U% X/ g; P! k. q
        recommend_list.sort(reverse=True)
    8 G0 F& }% R- m+ m  C' ~    #print recommend_list
    0 R% S/ A3 |8 a; Y1 f8 q: U4 ~+ x    user_movies = [ i[0] for i in test_dic[userid]]: q- l! Y' ~; x4 s% j
    $ j; f& @" U; E; H* v
        return [i[1] for i in recommend_list],user_movies,test_item_to_user,neighbors8 j, ^4 K# Y; k, [7 h0 S* O) ^$ j
        6 n0 Y" s, s7 v7 c
       
    + K9 F7 B8 Q9 P+ P! d2 x
    : N+ l! f& \. k2 j* `! z& i# a$ K#- g- B; S: l+ n- N2 Z: |9 y$ I
    #1 N" |9 u" ]; R; P# }4 m. B
    #   获取电影的列表
    / o4 Q" b( p- ]& q: X2 F#
    # O. i* s% a2 w% U; G' f#
    " q% C1 A9 {; W#
    3 S( g- l9 y( }2 M9 Bdef getMoviesList(file_name):- U" T+ m0 @# j( i
        #print sys.getdefaultencoding()6 r% c4 N3 |  W& j. k3 v% L
        movies_contents=readFile(file_name)
      O; W4 x6 {0 F3 d" E- r( r    movies_info={}
    : G" O9 \# G6 }' v7 G/ L5 O    for movie in movies_contents:
    . @' N' {8 S& l& k        movie_info=movie.split("|")& f5 u5 d& l6 G) ?
            movies_info[int(movie_info[0])]=movie_info[1:]& |) G: w) ]& Q- |- [  T
        return movies_info( b% l0 h3 @: r) {( W
       
    9 x! S+ \6 c, t1 E. \   
    * S8 F7 d) ?; p$ ^: l$ g. W4 J5 t   
    4 |; q. }* A9 K#主程序
    + {! E  A5 N0 |% P2 w5 H/ S+ o' r#输入 : 测试数据集合
    ) p+ S2 t( l  v; X4 aif __name__ == '__main__':: u1 c) q- F2 h) ], L. i
        reload(sys)7 l# d1 U! Y1 y$ _: `' @  Y* P
        sys.setdefaultencoding('utf-8')
    1 y4 ?7 ~( `$ P/ L* j# W    movies=getMoviesList("/Users/wuyinghao/Downloads/ml-100k/u.item")* w! g0 D2 s% }5 [4 @
        recommend_list,user_movie,items_movie,neighbors=recommendByUserFC("/Users/wuyinghao/Downloads/ml-100k/u.data",179,80)
    : C7 |/ f6 z' a; J    neighbors_id=[ i[1] for i in neighbors]
    5 K6 R+ a% q6 d7 u    table = Texttable()6 m7 n) i% \1 R. |  S1 f
        table.set_deco(Texttable.HEADER)
    - Y  r, W) n0 f# e, G7 T, _    table.set_cols_dtype(['t',  # text 7 k, f3 o3 W/ X4 e9 b& G9 Q8 D' l8 m
                              't',  # float (decimal)
    8 N) A8 V8 n# [6 p: U. W' j/ Y' S* }                          't']) # automatic
    / d- {' o  \+ a3 s8 U0 J    table.set_cols_align(["l", "l", "l"])
    5 a) Q/ B+ z# \! X2 P; S    rows=[]
    + b. t( D# q3 `- i+ p    rows.append([u"movie name",u"release", u"from userid"])' u* i0 j2 q  {; K: ]2 C" y
        for movie_id in recommend_list[:20]:! M, @1 W$ d2 T% V/ l
            from_user=[]
    6 F" w5 [0 ]/ I% H# a; S        for user_id in items_movie[movie_id]:. y8 c- |# G4 g9 B& g
                if user_id in neighbors_id:$ E5 P* K% A- o
                    from_user.append(user_id)
      _4 a) n0 o( E8 j9 e9 C        rows.append([movies[movie_id][0],movies[movie_id][1],""])
    , w% Q" l& w* J5 z8 V1 S, S9 E9 a9 _    table.add_rows(rows)
    * N$ n' c' j4 ~& h3 }7 g! N* s" V    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 ( p9 R0 J; B+ K
    # -*- coding=utf-8 -*-
    ; y* j% X7 o# F1 ]( I; H2 w: C: z
    import math
    : ?" `% u! M) N+ q; \* e1 s! p
    这是什么语言的程序?8 w& E( _* t$ {9 K0 a# z- m  @* x
    回复

    使用道具 举报

    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-4-16 04:17 , Processed in 0.437714 second(s), 68 queries .

    回顶部