QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 4789|回复: 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
    本人在学校参加暑假培训,需要这个算法做题!求大神赐教,感激不尽
    $ t: E# ]# E' p8 T, H  v, Q1 d6 `
    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 -*-5 e0 C. y) `7 ^. J  ~  z- c
    7 @7 Z: k; [+ V; V. t
    import math
    ) I( c) G5 X4 wimport sys
      s5 D8 ^$ q! H3 rfrom texttable import Texttable
    2 u9 j  M: @4 g# D9 _/ n2 y4 E
    8 j. b* q+ E4 m/ U9 s, K4 ^' z
    1 ?, U; _, i! D+ ^* ?; x#
    # x1 q5 u) Q$ A: ]. X" i0 u. ^/ v7 [#   使用 |A&B|/sqrt(|A || B |)计算余弦距离
    $ S$ C2 O+ u% |( @#
    ; T3 ?- {* D9 U1 N#; b( f1 K5 c  T
    ## |. ]/ H+ ^; q
    def calcCosDistSpe(user1,user2):+ Y# i3 u* V" B9 z+ z% D+ ]
        avg_x=0.0
    ) h" ~- J& D7 ?" I$ C  W2 i    avg_y=0.0% o- K. U, O; K- E) I, D, M
        for key in user1:
    + h* ]- c! D) U1 A2 ]) `7 t        avg_x+=key[1]2 u4 x. `6 q. ]: @
        avg_x=avg_x/len(user1)
    6 Z3 Q. i; \+ S( U    6 y- K; |/ Z; m) `: `
        for key in user2:
    " Z# k: h6 U9 b& o# J# ?' G* t% a, P        avg_y+=key[1]; U( N5 m7 ~% N% E$ a
        avg_y=avg_y/len(user2)7 b. N$ ^6 n3 I7 ]& n6 e
       
    8 S+ x4 B6 Y( Q% I6 y% ]    u1_u2=0.0
    8 j) e. ]$ j2 V8 q1 j    for key1 in user1:
    ' h$ [- g! \( a        for key2 in user2:7 ~5 {# D+ i5 V- E- l% }
                if key1[1] > avg_x and key2[1]>avg_y and key1[0]==key2[0]:  g" c2 Y4 P* o
                    u1_u2+=1
    7 B+ h1 k, N% S8 x    u1u2=len(user1)*len(user2)*1.0
    3 m4 d6 j' h* {* o    sx_sy=u1_u2/math.sqrt(u1u2)0 ?9 p6 h, t0 b# c9 a
        return sx_sy
    # p: ~7 T$ X" C! q. u' V. l8 k; |5 D- m
    ; ]+ O6 u- v* W5 T8 j
    #6 W  ^. \+ R# y9 |& F
    #   计算余弦距离
    % {8 [- H$ N5 J3 d- S2 H#* i( i4 C9 A0 E" n0 P) W
    #
    # j4 T) F+ r9 m! xdef calcCosDist(user1,user2):
    4 P. H/ \+ e4 X9 a6 k0 X0 U    sum_x=0.0
    " G. k# g6 K& u  N: ?    sum_y=0.0, j  a4 ^0 b0 z: y
        sum_xy=0.0
    ; C, k5 w5 Q- I9 j+ I1 o    for key1 in user1:) V- i  Z  e- t* |4 q
            for key2 in user2:# j0 U1 a2 w7 y5 V
                if key1[0]==key2[0] :
    2 t6 B; o4 p$ `, X7 m& q                sum_xy+=key1[1]*key2[1]
    ' e4 G! V9 x4 Y" {% B                sum_y+=key2[1]*key2[1]
    & Q# z" v# }; U                sum_x+=key1[1]*key1[1]
    - |% N1 g; s9 S6 `! B0 b, x    * [) x! H& x6 X. @/ Y1 b5 z( M
        if sum_xy == 0.0 :2 r2 Z- S2 o% ?" s. F4 ?+ i8 j2 j9 k
            return 0, E9 N7 w  s( P7 i# f
        sx_sy=math.sqrt(sum_x*sum_y) % c4 `% E- x: y9 W
        return sum_xy/sx_sy
    ) D2 W# L! ?& ?, y, c
    . f2 p% o1 B$ p& F6 V- M1 K  L1 G1 g  n) \' a' }
    #; x* A* a0 n( q7 [4 K- W
    #
    ( a6 h$ M" H8 A+ Y- B  L# p, B#   相似余弦距离
    - ]& t- t  ~2 k. J$ m7 R* z#
    ) z! p" o1 J& k, s" P& l#& c( w/ B/ f( b$ C) |4 B8 t
    #6 L& a1 S! o6 Q) M0 W# q# v
    def calcSimlaryCosDist(user1,user2):9 @0 W6 K( D  j
        sum_x=0.0
    7 A6 S& _. _' J; D# O) ^& i    sum_y=0.0
    9 m8 V; l" h- {6 A' ~    sum_xy=0.0
    0 U+ {% p+ }( L) F" i% d7 b    avg_x=0.0% U4 ~* V% Z5 q2 h1 ?0 f% q5 e( J
        avg_y=0.0/ `# w2 Z8 A" T
        for key in user1:
    ( [0 o8 L, B& F        avg_x+=key[1]* d* p6 ?6 b5 Y5 A# |  P
        avg_x=avg_x/len(user1)  v1 \# R& V  w% C" ], ^' ^
       
    ; V! E* ^) O+ u2 W* ]! x    for key in user2:/ q" u- s2 o) r  z  y* j' E, M
            avg_y+=key[1]
    9 ^9 _0 C# v" R    avg_y=avg_y/len(user2)
    / r; U( X( J1 _' |   
      T7 z( v' i  w5 z    for key1 in user1:
    ! o' u- U  \* ~3 ~) K/ S; E: \        for key2 in user2:; E, B2 W8 s! B& t4 p  c
                if key1[0]==key2[0] :3 O; }: G+ X5 I0 H% u1 u3 p- I8 H1 @
                    sum_xy+=(key1[1]-avg_x)*(key2[1]-avg_y)5 i: Q  d9 ]& U% u
                    sum_y+=(key2[1]-avg_y)*(key2[1]-avg_y)
    0 m7 D2 ?1 z9 W/ z        sum_x+=(key1[1]-avg_x)*(key1[1]-avg_x)5 I0 \( {7 R3 S4 @
       
    5 b/ E6 ?0 z* I8 R/ U2 S4 |    if sum_xy == 0.0 :
    $ i- V4 w/ ]) p6 v' \- _        return 05 S$ z7 t5 p9 m! i, q
        sx_sy=math.sqrt(sum_x*sum_y) ! N! X+ D4 u2 H/ K! J/ ?% d0 l
        return sum_xy/sx_sy
    : \, m6 Z+ Q; @; T0 [/ L2 R' n    * E- i, V% E3 u  A
    - J. @  S4 J% y- h7 }* e7 R$ ?" W
    #$ {" A/ p  Z! p$ Q
    #   读取文件# ]4 j5 z- e" {( C, c
    #
    - ]8 E, M6 P! M$ x) I3 i## ?5 M9 l! M& w, b# @
    def readFile(file_name):. I* {4 W7 _( O9 r+ X) Y* ]
        contents_lines=[]
    : Y1 w% L: y. S8 M' ?% d% t    f=open(file_name,"r")2 }7 X6 `- O0 T9 W0 i3 x0 X$ R
        contents_lines=f.readlines()
    $ G* M7 l1 O1 \    f.close()* A7 K. e3 B  P. q" h/ l% @0 k: H
        return contents_lines
    . w, ]3 q" U0 y' D4 B% q* a0 l. k. f3 e% x2 j

    4 y1 a% D" q  I% Z& s& U2 G. H7 ?& \! |9 g9 k) |" ]
    #* X  B4 B" o  _- S  j
    #   解压rating信息,格式:用户id\t硬盘id\t用户rating\t时间
    . \- p7 j+ ~7 v4 Q. ?+ g#   输入:数据集合
    + i. H: u; q) }" ^5 t#   输出:已经解压的排名信息
    % K- z5 O3 o( _2 \+ i! \#
    ! o5 w6 }0 {5 B; o& |4 ?0 ndef getRatingInformation(ratings):
    ) B7 n7 ]- p9 L2 Y2 j. L    rates=[]6 S+ K5 s0 L; S! y
        for line in ratings:2 {; o, X) Y* v3 |$ B; Y0 W, ]5 F. d
            rate=line.split("\t")+ J8 r5 J0 x& v! N% r* V
            rates.append([int(rate[0]),int(rate[1]),int(rate[2])])
    9 U  z4 C) h$ Y; Y    return rates0 X/ d4 h1 k& y" v/ A  z

    , E6 O/ k8 A$ T: _/ p$ g9 o
    $ F0 \8 G. ?6 Y0 Z; ?3 ~3 k, L$ X#3 [9 l1 F% l* t7 \# ?
    #   生成用户评分的数据结构" H1 y3 {( D8 Z' J0 Z
    #   . f$ w' }- w8 j3 d3 s& |* _$ W
    #   输入:所以数据 [[2,1,5],[2,4,2]...]
    - s2 Q+ p% T7 y#   输出:1.用户打分字典 2.电影字典  O" O% |, }! L  j, F
    #   使用字典,key是用户id,value是用户对电影的评价,  k: d5 l, K5 `) E: Y9 w$ {6 t/ v
    #   rate_dic[2]=[(1,5),(4,2)].... 表示用户2对电影1的评分是5,对电影4的评分是27 N0 g. F: D) b' x' y* B
    #
    : H3 c/ |) c) W, g2 q% n6 Pdef createUserRankDic(rates):
    - A* W/ l' e# x) g    user_rate_dic={}
    + D* e3 Z$ `- h( b$ S    item_to_user={}
    : O6 T5 M6 x4 j5 D    for i in rates:3 ]- M9 N, a0 O2 q2 V
            user_rank=(i[1],i[2])9 T& e7 u8 M- B9 k- W6 G( ?" w/ Y
            if i[0] in user_rate_dic:* g: S/ a, ^6 D
                user_rate_dic[i[0]].append(user_rank)9 N8 k+ x& l5 A) L: d
            else:
    + N5 Q/ l) h1 U6 Y& W$ H* G            user_rate_dic[i[0]]=[user_rank]
    * e4 d3 i5 A: P+ y& C            9 r% V# H- v* t! W
            if i[1] in item_to_user:+ F( X: n' J6 k
                item_to_user[i[1]].append(i[0])
    - \  |( ^7 v2 s9 y; p        else:# C+ n7 K' G, S" D$ j4 m0 x
                item_to_user[i[1]]=[i[0]]# [3 a% [3 l- r7 _1 b
                
    & K7 f5 u6 s/ F    return user_rate_dic,item_to_user1 t1 [: L. @5 Q/ ^0 q2 [

    $ u: x7 @4 ?% j. N$ O
    ; |$ M; X2 ?1 s0 O#
    . |6 V0 ?3 q; c# ?5 `  q1 F2 \6 `#   计算与指定用户最相近的邻居
    3 o, P& z% D1 f+ L, ?# ~# p#   输入:指定用户ID,所以用户数据,所以物品数据. o% G9 q- r, ~& A% A
    #   输出:与指定用户最相邻的邻居列表
    $ y1 x1 I5 i2 I9 D  s9 K#
    : K0 A2 U( Z# y& J9 p  sdef calcNearestNeighbor(userid,users_dic,item_dic):
    3 d, L0 T) l- p2 j, T9 u/ ]    neighbors=[]
    " y& d  e& ~7 o! k0 F; K+ m    #neighbors.append(userid)
    / H+ }3 V5 J) _8 p& D& V0 j1 I3 b! c    for item in users_dic[userid]:' e% o3 \4 H8 c* _  l! D
            for neighbor in item_dic[item[0]]:
    2 `. W6 ^# \$ }/ ~            if neighbor != userid and neighbor not in neighbors:
    . h2 u: p0 W7 q9 F& e. N                neighbors.append(neighbor)
    & d( I& S3 y9 P# h      
    - I% _4 q# h6 I% A6 V    neighbors_dist=[]
    " B: O7 B; Q5 _/ H9 Z) R    for neighbor in neighbors:) ]2 ]0 @( M( r% t4 Z1 c
            dist=calcSimlaryCosDist(users_dic[userid],users_dic[neighbor])  #calcSimlaryCosDist  calcCosDist calcCosDistSpe
    , p6 e2 \4 b* k! ~2 Y; u        neighbors_dist.append([dist,neighbor])% i( b) u& G- j3 ]2 b$ o+ H
        neighbors_dist.sort(reverse=True)
    0 ~. }4 r% i! d0 h- ?( C    #print neighbors_dist
    ' r/ E' e6 C3 z$ p: u5 X    return  neighbors_dist
      V1 {7 m( ]9 q6 {. _1 R3 O0 `$ W7 Z& B$ P! t) t5 n3 O$ B

    / e* k2 x8 @$ {: E0 k7 V: K, K#
    5 m, P3 a' T4 h0 e: F#   使用UserFC进行推荐
    3 o3 S& D! M3 T4 g7 g; O2 y( I9 K0 ~#   输入:文件名,用户ID,邻居数量5 x% b- Y* m* ?( X* ^
    #   输出:推荐的电影ID,输入用户的电影列表,电影对应用户的反序表,邻居列表
    0 Y& H  ~( ?( f* {#8 D  M# d9 P0 Q$ O* A9 z$ A, Z
    def recommendByUserFC(file_name,userid,k=5):. G# {1 Q' Q) ^4 n1 w
       
    3 |- I3 K( C8 {7 m    #读取文件数据, Q7 p* T1 I3 y5 f* X5 G- c' {
        test_contents=readFile(file_name)
    1 w1 N/ }- e* N    % @& x% M) Q% P: D2 o" ?
        #文件数据格式化成二维数组 List[[用户id,电影id,电影评分]...]
    . i4 C: ~, T5 J, w* r# F# O  d1 h    test_rates=getRatingInformation(test_contents)
    0 u1 r4 `1 j, d/ s0 J4 O1 i   
    : g, F  X/ J( R  A    #格式化成字典数据
    ! l" P+ |# W+ t- C6 r5 k: ^# j    #    1.用户字典:dic[用户id]=[(电影id,电影评分)...]
    6 p4 {2 i3 M; h$ @    #    2.电影字典:dic[电影id]=[用户id1,用户id2...]
    / J) p+ B1 |2 e. g    test_dic,test_item_to_user=createUserRankDic(test_rates)3 o5 L4 Y" K% Y% }$ J
       
    " E$ \/ ^: x  g" e1 l    #寻找邻居7 w, Q: L: U* L% v
        neighbors=calcNearestNeighbor(userid,test_dic,test_item_to_user)[:k]
    - t7 y6 t: v" N* G) e- U9 r4 D5 r; t        ( v9 |* E" f) b) w  I( b+ p$ W
        recommend_dic={}
    8 h7 w/ L$ x1 e4 o    for neighbor in neighbors:
    , Q9 d- K2 @% _* D& L' U6 H' L        neighbor_user_id=neighbor[1]/ y& s9 M6 u$ Z# r% ]
            movies=test_dic[neighbor_user_id]
    4 G2 d* m* k, H8 m; M/ V5 ?& C        for movie in movies:3 n: K  O" ~7 j4 v. Z$ _
                #print movie
    $ F7 t) l, `, H2 B: I6 w: e$ S            if movie[0] not in recommend_dic:
    3 f8 j9 N; m, d, |- y! L  X6 |( y                recommend_dic[movie[0]]=neighbor[0]5 g; m+ F% I9 x: h! [( @7 ]( X
                else:) {" Q4 V2 {  C/ r/ W
                    recommend_dic[movie[0]]+=neighbor[0]( X/ r# y; S2 i. ?8 O" `0 Y
        #print len(recommend_dic)
    & o# W1 }6 s" N" b4 Y, n3 d    6 J# X; `/ @+ ?4 ^" D, K
        #建立推荐列表
    ' y+ X; ~1 n2 }7 K( U    recommend_list=[]
    4 ^5 v( b+ v9 p$ L+ I" J$ h: i7 |    for key in recommend_dic:6 D6 N0 L& f- E# k5 `
            #print key' p/ D$ f3 F/ N  m' B  T' u
            recommend_list.append([recommend_dic[key],key])
    9 G" L) Q; w4 Q% ^5 N   
    % s, m! Y1 @. v7 y/ D  F4 ^   
    ; S* i4 l/ i# b1 K% M    recommend_list.sort(reverse=True)
    1 I6 I8 O8 y7 S    #print recommend_list8 T! U- @6 L) [$ `
        user_movies = [ i[0] for i in test_dic[userid]]# R0 u: @# h' H
    ; v9 ~3 o1 T+ H. V
        return [i[1] for i in recommend_list],user_movies,test_item_to_user,neighbors
    ) t: L( H0 p- U& z' d/ A3 Z   
    ( h6 Y# p' O9 w4 `; o; H/ v    & p7 S' ?# S! `% c! g7 j

    - N  Y/ C& c) z# c1 s#5 Z+ O* [3 w( U0 a- E
    #+ ?- \" f# |, u2 X9 Y  {
    #   获取电影的列表7 D* @9 T. y9 z& U
    #
    5 M8 L  T8 @( G- y4 j' v: q" i#" G# r! E& \8 z5 W
    #
    $ t! f  V# Z& v, J) Gdef getMoviesList(file_name):$ K- Y$ h. g2 j4 U/ i$ e& t3 o
        #print sys.getdefaultencoding()
    0 s" t1 a  t. t) u' n$ s4 {    movies_contents=readFile(file_name)/ b! ?+ j0 z7 B; M
        movies_info={}
    $ h) u- n2 E" G    for movie in movies_contents:
    8 R! Q7 f6 A% i  u        movie_info=movie.split("|")
    % h/ E6 W/ Q; g$ z% u) q# {        movies_info[int(movie_info[0])]=movie_info[1:]
    4 h7 ^" w) u: Q* h$ U    return movies_info5 ]' `, n. p/ x$ e
        ) x: J8 _. H2 K& z
        5 k2 G  `! o" E* Q7 S) q
        " [, B; \' E5 q* g; J
    #主程序3 `5 p0 V" _6 H. y
    #输入 : 测试数据集合
    ! t2 N5 q& o' uif __name__ == '__main__':
    8 V+ X: E( v6 E: A; f& {- _3 B    reload(sys)7 N7 w  b/ Q& D7 k0 ^
        sys.setdefaultencoding('utf-8')
    4 Q9 ^9 o, l9 x! n2 D    movies=getMoviesList("/Users/wuyinghao/Downloads/ml-100k/u.item")0 h6 H& i+ B# v
        recommend_list,user_movie,items_movie,neighbors=recommendByUserFC("/Users/wuyinghao/Downloads/ml-100k/u.data",179,80)* |: S# @" J( ~7 K$ Z6 M  ~3 Y
        neighbors_id=[ i[1] for i in neighbors]5 |4 j+ E5 J4 H( z- |
        table = Texttable()( b  I5 F+ K+ A1 {2 L/ C" P3 K& Y
        table.set_deco(Texttable.HEADER)! H/ d( L; e: t- B
        table.set_cols_dtype(['t',  # text " ?3 X9 }6 \7 G: S
                              't',  # float (decimal)& a- g; Y- c: k! V: u4 n9 `
                              't']) # automatic
    * Y3 O( k5 p5 x& V    table.set_cols_align(["l", "l", "l"])
    % ~3 E, i% i( ^    rows=[]" m. h  S& q5 Y( v. n  c
        rows.append([u"movie name",u"release", u"from userid"])
      S& [  l3 {, t    for movie_id in recommend_list[:20]:
    ! |" y% t0 Z5 h        from_user=[]4 p& g% F! r" q- a
            for user_id in items_movie[movie_id]:! \, x# J7 h! S4 _# g0 d4 {
                if user_id in neighbors_id:  z9 I' Q  O  y, Y, A8 k
                    from_user.append(user_id)
    / ^1 w2 ]  F& m9 I  x# U+ M. q        rows.append([movies[movie_id][0],movies[movie_id][1],""]); f* U' Z% X0 a6 O7 {. [( `5 T
        table.add_rows(rows)" e3 H3 g# \" I" W- ^$ m  `
        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 0 S  C+ E4 z4 Q7 G# k, |" @
    # -*- coding=utf-8 -*-+ e7 I0 E. q7 e! Z( J
    1 {* }- P$ l& x
    import math

    6 t6 r  W. e0 ?" f, C; i. R这是什么语言的程序?7 C: U2 ?' F$ H9 J9 I" ], `
    回复

    使用道具 举报

    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, 2025-5-12 07:08 , Processed in 0.616468 second(s), 67 queries .

    回顶部