QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 5298|回复: 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
    本人在学校参加暑假培训,需要这个算法做题!求大神赐教,感激不尽2 z, ?& M* o& \+ g# V
    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 -*-
    6 L7 Y: q# J4 y1 E* \: [. Q' J3 h
    . U5 ^( M9 Z5 r7 cimport math' q' p% R8 @% @$ q
    import sys- |3 y+ J9 C4 i
    from texttable import Texttable
    $ |( b" a7 Z0 }7 y+ K
    : D& ^/ [/ K& I3 W. ^+ u
    ; i( b3 Y3 Z( ?- Y+ R( H#- U; P9 {1 E5 L! E
    #   使用 |A&B|/sqrt(|A || B |)计算余弦距离
    & W4 ?; ~4 y* e7 o0 {#
    $ v6 Z# p1 d$ C' E3 m& R#
    ' f$ C. h- `% G* B, O  k) m$ `1 G#3 [) g/ P/ L3 Z. |( v. s
    def calcCosDistSpe(user1,user2):7 {9 p7 ~4 `9 c+ j# \( Y3 l
        avg_x=0.0- f: ^) R! E2 v
        avg_y=0.0
    ) o" ]; c. @; e8 r! I    for key in user1:
    / m+ d( g" q+ L# P        avg_x+=key[1]
    8 x, q7 A2 h/ \% J! K, ^    avg_x=avg_x/len(user1)- L4 Y% U: M" ]
        1 A% H) B; ]' P4 c
        for key in user2:( U: T. T  B8 m1 x9 h* j, ?3 Y
            avg_y+=key[1]1 O' f( G7 T: g  P& H$ a0 G
        avg_y=avg_y/len(user2)9 k7 g+ }( r/ ^3 n9 x% k
       
    ; E, w9 g/ W3 N    u1_u2=0.08 E; h9 I9 }( ]" `( q" `
        for key1 in user1:
    2 l. X* K4 f" g        for key2 in user2:% x+ q* O9 c  s6 [
                if key1[1] > avg_x and key2[1]>avg_y and key1[0]==key2[0]:* h4 }( `: f! U
                    u1_u2+=1
    6 j7 z7 w( T1 b# C$ s: @4 {    u1u2=len(user1)*len(user2)*1.0) }  }: u' k* d9 @5 l- u. `( y
        sx_sy=u1_u2/math.sqrt(u1u2)
    . R( S0 P: R* |: j    return sx_sy
    ; x8 M& r$ p( A2 O: W$ X6 r" ~9 i/ O! P6 A. t3 C5 O

    # ?6 ^! h: f+ }. r1 h#
    ' j1 a' e  s9 T2 g; r$ p2 M#   计算余弦距离
    ; e. \' U( o9 p4 b/ R5 K' U; q#" q, I6 _' p2 X* s- }
    #' n/ A; ?3 V/ o9 w0 D
    def calcCosDist(user1,user2):
    % M1 _7 T4 O/ e$ M$ @9 P4 W+ l    sum_x=0.0
    $ y. A" z5 _8 S0 ~+ o    sum_y=0.00 M3 W4 R- \: Y) T8 P  {- l5 _
        sum_xy=0.0! T) p) T6 e, @, p$ y5 V( E$ P
        for key1 in user1:
    5 e2 z+ ~+ W5 m7 d1 ]  S& Q, X        for key2 in user2:, E' z" o  f0 @! e6 i$ O
                if key1[0]==key2[0] :3 b% t) g( s$ w! T5 k6 B! p, l
                    sum_xy+=key1[1]*key2[1]# k% l* y3 ]$ j8 z
                    sum_y+=key2[1]*key2[1]
    6 b4 S$ }1 |% T% P2 j0 C+ u% a- n  I                sum_x+=key1[1]*key1[1]
    % h- i% X& n' @/ s2 E: y   
    9 ^/ Z# X3 G% J, Q4 j! e    if sum_xy == 0.0 :& `5 m% A6 R4 o: t1 ^4 r2 \% J6 v
            return 0
    & L3 c$ J/ @# O7 J! q8 G    sx_sy=math.sqrt(sum_x*sum_y)
    ( Y- Y% Y. r' x& A) m% W/ b5 l5 w5 A    return sum_xy/sx_sy$ F/ k  X, ^- ^! j. B: y' H

    1 l& U+ w" ]% N0 W6 H' Z) l8 o$ O# c* k1 }3 L0 N3 h- X
    #
    4 V7 z& _; R& w; X+ B% z9 l- z#
    0 n9 y! j3 l: K. t9 t#   相似余弦距离
    . D6 @/ O; C# H( U6 e8 b2 i( ^6 u#
    , x! N( \6 v* x  F+ ^+ d#
    5 Q, {' p- ]" p% x8 w$ Q#
    5 y7 Z3 t0 A: f" S+ V; ?  F( @8 ydef calcSimlaryCosDist(user1,user2):
    9 ]! h7 \7 V/ L1 j) i* R% w/ {    sum_x=0.0
    / `# }& ?4 C6 |% {2 y  M* N    sum_y=0.0. W) e7 R# |, Z  ]. ]% ?- L
        sum_xy=0.0
    3 n' ~) A# F- U' J/ J' @  L3 n    avg_x=0.0
    ! y0 I" l( I8 S: s    avg_y=0.0
    ! {1 ~' _% B1 f" v; Z) I    for key in user1:3 r. M" ?* x, I, e: ]
            avg_x+=key[1]. E/ S' r" ]  T: Q' \8 S* G
        avg_x=avg_x/len(user1)
    9 {/ K- M& w, X" ?   
    $ f% C* a5 |! g" g    for key in user2:; N% w7 }* u7 r9 Y; r$ g' C
            avg_y+=key[1]
    ) G8 r, `- B0 t/ Y    avg_y=avg_y/len(user2); t4 Y* l, C. @
        8 Y( A. |0 Q+ @4 P8 l
        for key1 in user1:& T* A0 q6 u, v1 i9 f/ j8 z5 {
            for key2 in user2:- E7 X8 s8 O4 H, B0 T4 G
                if key1[0]==key2[0] :
    # y( v! s/ n5 o; }& |9 R. Z                sum_xy+=(key1[1]-avg_x)*(key2[1]-avg_y)
    - [3 e1 U$ {1 t* B                sum_y+=(key2[1]-avg_y)*(key2[1]-avg_y)
    ( v9 K5 N; a, G4 ]9 x) s/ g5 C        sum_x+=(key1[1]-avg_x)*(key1[1]-avg_x); O! I: y/ B: H- E  |+ |  z9 s. U
       
    5 \' J1 f$ {, j9 t; K    if sum_xy == 0.0 :* d9 F1 _& F. M- U
            return 0% J3 `4 |( r8 k4 d
        sx_sy=math.sqrt(sum_x*sum_y) : @4 u; d5 b2 a/ N/ ^# q
        return sum_xy/sx_sy: Z5 v5 R" _" c: A# F; F' K3 }
        & C. }0 l9 a- I+ w) t# J

    ) t) x& c* m$ h/ l$ N#1 L) h& Q# [: N& C8 p# _+ N% V/ z
    #   读取文件5 N) Q* @7 i! S* J, h1 h2 N
    #
    / R" y& f7 g7 a* i( t8 l; O! [! X#( C  k4 ~5 x' N, x' g
    def readFile(file_name):$ {* @6 |4 k7 s  j
        contents_lines=[]
    ( K5 E2 w6 L& F# G  t    f=open(file_name,"r")
    0 h2 g* b$ g, @    contents_lines=f.readlines()) ?7 p* W* h( a" B
        f.close()8 E5 v, ?6 Y, T
        return contents_lines
    3 W6 v4 n; ?# g( e/ j6 R/ s0 m
    ! M: p0 ^% D( e: b% d1 e: O
    5 ^9 L; F! [) ~6 {- i% c6 b
    , ]. v9 V1 R8 C& d5 ]( {#9 b0 B; d* k, x) F& ]2 p1 W8 q
    #   解压rating信息,格式:用户id\t硬盘id\t用户rating\t时间/ v% [8 Q* R! U; h
    #   输入:数据集合
    ) A/ {: T+ [; J1 z/ F#   输出:已经解压的排名信息
    5 j; T1 y1 x  h$ [/ ~/ }#% J) k* m  s! G* }) a$ A' F
    def getRatingInformation(ratings):
    , I5 o* O1 _9 o" o5 L    rates=[]: w* M! E* R, _) s
        for line in ratings:0 X5 l& ]/ Z$ L5 l
            rate=line.split("\t")1 h& ]  O9 {; {! C. V9 m
            rates.append([int(rate[0]),int(rate[1]),int(rate[2])])
      ?* v2 i  R2 a    return rates
    " \0 I% O2 V) T: q/ E& A! N3 Q4 G( o) f' C* f) q
    0 ^/ ^0 {, Z6 z8 h" p: ]8 l
    #8 S: U% W7 I; u6 w1 f/ a+ Z- ]# _
    #   生成用户评分的数据结构
    7 N* Y/ G# X" C8 Y#   3 K0 E3 x5 h0 D- i# g
    #   输入:所以数据 [[2,1,5],[2,4,2]...]( a* w5 x# ?8 Z8 m" a8 f" k
    #   输出:1.用户打分字典 2.电影字典
    ) l9 r- v9 y7 K* |4 Y$ y#   使用字典,key是用户id,value是用户对电影的评价,
    7 a! U0 P2 c$ M#   rate_dic[2]=[(1,5),(4,2)].... 表示用户2对电影1的评分是5,对电影4的评分是2
    % M3 o* X: \# r8 o% S1 o#
    : }5 q; I2 \. _4 C; z" p8 K! Fdef createUserRankDic(rates):6 u& f6 {6 U/ R: s% b+ M% O) N
        user_rate_dic={}
    % F% q: }/ E. m, Y; C; H    item_to_user={}# w3 D5 U5 O, G! r
        for i in rates:
      N& o7 B7 R4 |        user_rank=(i[1],i[2])
    # d6 p  L* V1 l) ~- n        if i[0] in user_rate_dic:
    ; [: ]+ F2 N, R9 W! M5 S& I4 ]6 ^            user_rate_dic[i[0]].append(user_rank)
    / |2 ^" M5 }, {        else:7 D( F% M: u6 V' H* h7 ~
                user_rate_dic[i[0]]=[user_rank]+ x' S1 f8 T" C
                
    8 W% c( X, h6 \% y1 G2 T        if i[1] in item_to_user:
    7 M( ^$ l: I7 z/ D            item_to_user[i[1]].append(i[0])
    & q+ X" E! C2 q; o, L' p+ c) q7 T        else:
      s. R, P  c% X1 ?4 J, c- k4 K            item_to_user[i[1]]=[i[0]]7 \+ c8 l. T& R  }
                
    ; ~  p! |8 E4 S% A+ g% u7 Z    return user_rate_dic,item_to_user
    4 Q! J5 z* ?! G8 M
    + u7 j3 P! N1 l) P1 e, t- |0 H) m' p4 b6 ^% x
    #
    ) V; L! c/ c; @7 ]% v1 j6 N) u#   计算与指定用户最相近的邻居) ]* _( u6 w7 d6 z5 t) E
    #   输入:指定用户ID,所以用户数据,所以物品数据, ^# T. q4 i/ e1 a. b
    #   输出:与指定用户最相邻的邻居列表
    / e7 N  s& o+ |3 K7 r, c( M% A#
    ' Z5 x% B: ?, P  k) A- I9 cdef calcNearestNeighbor(userid,users_dic,item_dic):: @" M, @, {& P# ?4 K8 i% `/ E1 a
        neighbors=[]) R* R6 q" C2 y+ d& |) m" K5 v6 F
        #neighbors.append(userid)
    7 Q. k* V' b' J* z; i    for item in users_dic[userid]:
      Y& l/ _- `- O3 K' D        for neighbor in item_dic[item[0]]:
    $ i' N8 z' N0 v; u# f* l3 p# K            if neighbor != userid and neighbor not in neighbors: 0 T" ^: ], I( l: k( g8 g3 J
                    neighbors.append(neighbor)7 c# z% @4 \! U
          ) ]' Y8 G, E  N+ c! `
        neighbors_dist=[]6 n. q: v; c# K, N+ Z  B& P
        for neighbor in neighbors:4 p( `& }/ {; Y$ t
            dist=calcSimlaryCosDist(users_dic[userid],users_dic[neighbor])  #calcSimlaryCosDist  calcCosDist calcCosDistSpe" o: z8 b; N( D: q0 z
            neighbors_dist.append([dist,neighbor]): ^/ U" C& L" S, W/ T4 V
        neighbors_dist.sort(reverse=True)
    $ S  F' s. o) j" T    #print neighbors_dist
    0 w1 z' c8 t- [; s9 d0 i    return  neighbors_dist
    3 |7 T' M, R, p" {; }- H6 _2 j/ `) B

    # e4 M8 p/ p# a6 ?3 \! q) T6 m#
    7 k* Y# F' B6 c#   使用UserFC进行推荐
    * ]4 }- P. I8 _#   输入:文件名,用户ID,邻居数量
    7 X% s) K( u9 b/ P( d#   输出:推荐的电影ID,输入用户的电影列表,电影对应用户的反序表,邻居列表+ N: C7 E1 F" ~/ |! c
    #. R' R5 X9 u; m' Z& O$ t. J
    def recommendByUserFC(file_name,userid,k=5):
    % W/ h: A" d5 g- O0 g   
    ' y( d* ]* O9 k    #读取文件数据9 A3 @) y" M4 c  l
        test_contents=readFile(file_name)
    * Y! P+ }  H; V. ?      w/ V1 e  g3 T% W5 _. N( T
        #文件数据格式化成二维数组 List[[用户id,电影id,电影评分]...]
    % z2 Y7 F* S' u2 q( I. D0 f& {    test_rates=getRatingInformation(test_contents)
    8 }, e$ P- l2 Y0 A: h+ f      W, [* E0 E' R" j* v( ~9 A% E
        #格式化成字典数据 . t1 q. S* n/ |9 G: f
        #    1.用户字典:dic[用户id]=[(电影id,电影评分)...]
    ( o2 z8 E; Y' n# d, Z    #    2.电影字典:dic[电影id]=[用户id1,用户id2...]& ]+ r" s! ?! y0 C1 ?
        test_dic,test_item_to_user=createUserRankDic(test_rates)
    / z) U9 X( l) g6 z* ?$ p   
    8 W0 h) y4 g5 C; j1 }, G2 x' L    #寻找邻居
    4 e% O; J; {0 @$ e! G    neighbors=calcNearestNeighbor(userid,test_dic,test_item_to_user)[:k]0 s/ P* }) X5 v9 \
            3 K9 L) u' Y5 O: o. K. Z0 {1 M
        recommend_dic={}
    ! W3 V5 ^7 X% R* K/ J# k: M6 V    for neighbor in neighbors:
    " B* c; `: f3 C1 N+ x) B. @. L        neighbor_user_id=neighbor[1]
    7 v& J- S7 N: M0 l. `, K5 S. y4 y        movies=test_dic[neighbor_user_id]
    7 d* O5 z6 i% a$ X& R, N        for movie in movies:
    ( }& L! O8 ?; b            #print movie# \: |% Z) I( @! u- I
                if movie[0] not in recommend_dic:2 X$ ?. ]9 @, Z6 m$ X7 s
                    recommend_dic[movie[0]]=neighbor[0]. Z. Q' @  l( Y  o' E4 W
                else:
    ' [& c8 [8 p# H2 z3 _0 \, ~                recommend_dic[movie[0]]+=neighbor[0]+ X6 x4 {0 x2 ^1 g- E
        #print len(recommend_dic)
    6 U2 I2 j3 X3 }+ r    * |2 n5 l: l% H
        #建立推荐列表; ?+ l% Z( n3 u- [" Y
        recommend_list=[]. F) y0 ~% e3 Q. t8 C
        for key in recommend_dic:
    $ C& n  _2 m9 Z0 v( U5 V: q5 N! v        #print key
    ; n( \0 Y$ ^6 _1 y        recommend_list.append([recommend_dic[key],key]); I" R. Q# w4 T8 w
       
    $ J3 u! ?9 X1 v2 H, |2 w0 N    4 a. u( V9 H5 t0 M8 \1 U
        recommend_list.sort(reverse=True)4 d9 n) Y: ~  \3 _, h# j, ?
        #print recommend_list- Y  S- _# k6 M$ x: x
        user_movies = [ i[0] for i in test_dic[userid]]9 Z0 n0 E7 I5 w0 k

    # U( s4 q1 B1 o2 G    return [i[1] for i in recommend_list],user_movies,test_item_to_user,neighbors) Z! _: q$ H0 f; w6 g( n
        2 n2 N9 ?; M. L  _
       
    $ r( t5 F4 e2 O2 D. x& a" B
    & m- J. N( C* A* P#9 ^3 r7 E1 W5 W: S( _( E
    #/ f5 n- Q7 W! z  M9 B
    #   获取电影的列表
    ( n2 I3 X+ c: @#
    / H, p# l/ S0 A# I7 S& e8 I#
    ( ]9 t- E- U1 \#, J2 n0 I! [1 {
    def getMoviesList(file_name):8 n- \6 F8 Z+ J5 G5 L) q9 s
        #print sys.getdefaultencoding()
    + G0 E, Z# r4 L" B( x+ M% K    movies_contents=readFile(file_name)
    7 v- z) |) a) U) O5 q+ m    movies_info={}
      E! A0 d& a( N( _8 U+ s    for movie in movies_contents:4 N- w  q# k; `! F
            movie_info=movie.split("|")+ w$ f' v. {5 ~# d' a  k% t* U
            movies_info[int(movie_info[0])]=movie_info[1:]
    - r. d& y; Y% q( R# O4 A    return movies_info
    . z1 p, }0 a0 P# ]; O/ y    0 [, a0 t- I0 \
        8 p* H, ]! |# W8 c
        $ K# Z; Z5 C; I- u6 h
    #主程序- i! e& x# d+ F  B+ K
    #输入 : 测试数据集合, F% ~5 ^; O0 N
    if __name__ == '__main__':
    $ v2 T# |; S- m6 B% H5 N+ i    reload(sys)- P% o5 M+ H7 p3 \0 h
        sys.setdefaultencoding('utf-8')
    4 j( B% {5 i0 o; @    movies=getMoviesList("/Users/wuyinghao/Downloads/ml-100k/u.item")
    7 b* o/ d% ~! ?3 _    recommend_list,user_movie,items_movie,neighbors=recommendByUserFC("/Users/wuyinghao/Downloads/ml-100k/u.data",179,80)
    : e3 d. F( F, u6 i' _% |    neighbors_id=[ i[1] for i in neighbors]
      a: C1 c# z# _3 x* h6 y; \    table = Texttable()& g+ V7 q6 B( c2 [: A+ E
        table.set_deco(Texttable.HEADER)
    # p$ _: D! p( X+ ^. Z4 U- b* ~    table.set_cols_dtype(['t',  # text & a: J5 D+ p# |7 Q" L
                              't',  # float (decimal)
    / b  B3 l% K! U& v- T* R! y6 P% s                          't']) # automatic
    ! c' I# \; N5 l    table.set_cols_align(["l", "l", "l"])
    * }! |0 r7 A0 F! @& j  u    rows=[]9 d+ W0 M8 f8 ?
        rows.append([u"movie name",u"release", u"from userid"])
    * o" F# z+ u7 J; x; R5 E1 q    for movie_id in recommend_list[:20]:( O0 G2 g2 z& X. p3 [/ [% I% T  \
            from_user=[]0 \% h8 y) s" N. g4 n
            for user_id in items_movie[movie_id]:1 ]% v% E/ E" S4 j4 u( Z9 o2 a
                if user_id in neighbors_id:
    6 N( ?3 X& C" _# A7 k$ C                from_user.append(user_id)
    # u% }1 p5 }! n* [, F/ F        rows.append([movies[movie_id][0],movies[movie_id][1],""]), l4 W: V' Q" u3 b# B0 ^) R
        table.add_rows(rows)
    6 R, I6 S; b8 ^3 j( j1 E    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 $ Y4 ~' M, F$ q2 U0 C0 D
    # -*- coding=utf-8 -*-: e- Z; E( q0 a/ F: x# p

    3 u% b8 F2 h. y; a- e/ [+ M* Dimport math

    # X! P( ]1 q, t" ?这是什么语言的程序?
    / ~: f: n  D  M( y  \7 F
    回复

    使用道具 举报

    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-6-14 22:08 , Processed in 0.479341 second(s), 68 queries .

    回顶部