QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 5251|回复: 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 |. H# H/ b9 h- U+ u. R3 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 -*-
    ; M% Y3 l+ o# a) T. w3 ~8 H
    . [' u  B; e  _6 D8 Qimport math1 O8 m1 {4 Q7 X; J7 A* s
    import sys
    ( P! A& `. M: _/ y% ~from texttable import Texttable$ S6 r, C0 U( y

    9 |( R# b1 e, Y) G: h( l' k5 k, L/ b/ |
    #
    " n9 H2 b* J4 G2 R) F#   使用 |A&B|/sqrt(|A || B |)计算余弦距离" N# m4 _, F; v' @4 x6 H& I
    #/ a5 {' E$ [- a3 L  L
    #- J; I( ~; Z/ d
    #
    , A' C  x( _9 w3 Udef calcCosDistSpe(user1,user2):
    6 R$ V. O4 d8 {9 R1 n5 q) k3 e    avg_x=0.07 A, O5 A; l0 I) O
        avg_y=0.0
    ! L- v1 q) j: S8 q# b3 b( x; f$ l, N    for key in user1:
    ) _( o* y. J' R6 L: i2 y6 d        avg_x+=key[1]% V+ F' ~/ }) g7 X* q
        avg_x=avg_x/len(user1)* Z( J, r1 V& P7 Y# i0 q+ L; B; k  j
        % T9 E- f+ \5 l3 B9 c* H
        for key in user2:$ }) ?" ^. ^, I/ r4 z  S( ~& i: M+ Q
            avg_y+=key[1]
      _7 X/ b6 t0 O$ J- Y7 A$ e    avg_y=avg_y/len(user2)
    8 v2 O+ \( d) Z. V- X# J- a    ) O0 Y# E. G: O; G7 U4 u% t8 s
        u1_u2=0.0. Q$ l, E  |& _5 v7 u. t" V
        for key1 in user1:* w' \! X0 i. e9 H/ l
            for key2 in user2:
      x9 ^. L7 S! U, _$ h# `; }/ ~            if key1[1] > avg_x and key2[1]>avg_y and key1[0]==key2[0]:- J$ ]1 {8 x( u1 O8 M! f
                    u1_u2+=10 }1 A! M( Y$ M& R- c. Y3 |
        u1u2=len(user1)*len(user2)*1.0
    # _$ W% w. [- s( b% P! q) M+ I) i    sx_sy=u1_u2/math.sqrt(u1u2)
    7 }/ o! c. m; P  @    return sx_sy
    3 I+ `! |3 v/ Z
    3 _& t4 y2 r8 H3 r' x: o; c+ @0 f+ z6 l# v' P: U
    #
    2 b6 s) p' M8 D% x" L9 m#   计算余弦距离
    ( {. G5 J: t- k* i& T* e6 W2 q#* C: M# p# ]4 M: f
    #. N0 c1 K1 E7 t! h
    def calcCosDist(user1,user2):8 B# _* ?, f) F7 r
        sum_x=0.0
    / S7 p) p2 d0 U% [3 L/ ]; O; n    sum_y=0.0) I4 K' T0 O2 q7 g0 V+ B; b
        sum_xy=0.0
    3 n. W2 q2 M+ O    for key1 in user1:; r7 }1 e3 `7 Q* E6 P3 N
            for key2 in user2:
    / Q+ H- w( _. W! T5 c! y            if key1[0]==key2[0] :# ?) g7 v1 A( y/ f' x5 u
                    sum_xy+=key1[1]*key2[1]
    6 x6 B( u/ D$ u0 z$ |                sum_y+=key2[1]*key2[1]
    ; L3 ~! H5 x: M% Q                sum_x+=key1[1]*key1[1]
    % G2 q3 n. O6 Y# ~* @  a; C0 T    " }. i: `! G9 _7 \) s
        if sum_xy == 0.0 :
    + o2 s; f0 g$ j  z! k3 Q        return 0
    8 D: u8 L3 X! J9 e3 \    sx_sy=math.sqrt(sum_x*sum_y)
    ( r8 L2 f+ d6 Z" j) T$ P7 b( m0 q$ |    return sum_xy/sx_sy, y4 E; D  o4 l

    . [* z  `* T# Q5 o* L/ l( Z* s; f* E+ Q2 p! s: k
    #5 {( q, c9 X- S: j! x5 ?
    #9 z# B# i' Q/ Y* H. W# j3 W7 H3 y
    #   相似余弦距离& M0 E7 \) o! G. y: Y/ N. _+ ?
    #3 i, Y# M$ l# [3 L8 H
    #  |' w0 c8 X7 V
    #
    7 S; c9 T6 X9 A, O; kdef calcSimlaryCosDist(user1,user2):
    $ b1 a5 i6 C. G8 k    sum_x=0.01 D. s# C, ]! K7 o) H
        sum_y=0.0
    8 M1 R4 b/ m% R7 `$ ]; B& [    sum_xy=0.0! @# d% W8 }9 ^/ H! P
        avg_x=0.0
      X6 i" O& G! F6 R7 T& [# i6 X    avg_y=0.0; k- G$ |; f- }/ G
        for key in user1:. ~# s1 r- z( M3 O
            avg_x+=key[1]1 s" j5 b/ R9 o
        avg_x=avg_x/len(user1)
    . @  x$ A- j! H8 I   
    + S. p) S% Y) d    for key in user2:
    & Q% c8 s/ _+ \# K, S        avg_y+=key[1]( Q0 ]: x( V) M# n( ]  L
        avg_y=avg_y/len(user2)
    5 q% m5 e3 y' c* D  N4 Y1 s   
    7 R) Y8 n! S5 }7 N) m    for key1 in user1:5 z4 @/ S+ b4 S* g8 T! J& k6 ~/ m
            for key2 in user2:" ^5 d: [7 U4 ^
                if key1[0]==key2[0] :
    # N( s: g+ h* X                sum_xy+=(key1[1]-avg_x)*(key2[1]-avg_y), x& z9 v) w: f! s# a8 u
                    sum_y+=(key2[1]-avg_y)*(key2[1]-avg_y)$ a: C! |- \6 Z" P& L* C# i" _4 n
            sum_x+=(key1[1]-avg_x)*(key1[1]-avg_x)
    7 K6 e- @1 L" V1 x) j    4 {, u- S% z; V% v9 Q4 J
        if sum_xy == 0.0 :
    % A. G: R; T0 |% O        return 0
    4 ^, |: i5 h' q, H/ b( n  B1 J    sx_sy=math.sqrt(sum_x*sum_y) 7 b* p  g/ g/ b( I
        return sum_xy/sx_sy2 |1 `8 g. w; i9 J) D
        + A; Y7 r) d" K  \6 K/ B- i

    0 Y; h8 i* g- r' ~+ j$ }#
    $ P% j- ~; U+ W9 l/ W#   读取文件8 K; l: x& f  k8 G  S( c. V
    #7 K0 v8 o" E, M
    #
    " F9 E' p( ~- ~  \% a% |7 Wdef readFile(file_name):2 r. T4 }3 J$ o% J2 h& b! u" F
        contents_lines=[]5 A/ h" ^2 @/ c
        f=open(file_name,"r")
    ( a: p' r. W1 C- _7 K8 o9 u    contents_lines=f.readlines()
    & h$ S! ]; e+ ]# E( J3 U( |' g    f.close()3 W# c% s) S8 C; u! @
        return contents_lines
    $ A' E5 i! [% t7 E1 I; X6 g- \( [# f! d) @7 G+ c0 W% |, i
    2 i8 q9 ~2 \, {( x( g. v: }

    * {( M4 I- Z6 u% r, p3 W#9 q) I2 E- @' S( i! ^" H: J) @
    #   解压rating信息,格式:用户id\t硬盘id\t用户rating\t时间
    # q4 w3 ]+ L3 ?- |3 ?% B#   输入:数据集合0 D  C( i  ~& `- `3 @  Q0 r* ]) S: L
    #   输出:已经解压的排名信息
    & b0 P6 U* c; Q0 B# |#- n. w5 c0 l& D6 O4 H: }5 {9 b. B
    def getRatingInformation(ratings):2 |  G6 t, s! r8 A
        rates=[]
    , j% h6 _: [/ a    for line in ratings:; r$ G" @, o& {7 E; Y( F
            rate=line.split("\t")
    ! T$ E4 ^# _# }: o7 a( b" y        rates.append([int(rate[0]),int(rate[1]),int(rate[2])])& p$ p- S' m3 K
        return rates" ?- [. _7 |, Q: ?( p

    " O" y' r" n0 u4 B) q% \
    9 M# o9 D' p7 X* _- J6 v#0 f+ ?1 ?: z/ g! [! I' ^$ \  k
    #   生成用户评分的数据结构( I& `" C: w9 e5 h  R* x, [. ^% O
    #   ; |. A7 O2 w  s, I9 M+ }0 w
    #   输入:所以数据 [[2,1,5],[2,4,2]...]! R, B- n# F) y) |
    #   输出:1.用户打分字典 2.电影字典
    $ A1 A9 e0 o" z$ L6 d#   使用字典,key是用户id,value是用户对电影的评价,/ k+ h0 D  j8 i" Z6 }
    #   rate_dic[2]=[(1,5),(4,2)].... 表示用户2对电影1的评分是5,对电影4的评分是2
    0 U. S4 [0 R. S#, |$ F2 ?7 ]% [1 ?5 g
    def createUserRankDic(rates):
    ! J2 ^% G6 [0 \    user_rate_dic={}  y7 @, e8 x6 M
        item_to_user={}* M" n& p+ a7 u5 B6 R
        for i in rates:
    ( l, f7 T) C- L4 v        user_rank=(i[1],i[2])6 q6 b4 C" R3 l' A! B3 v
            if i[0] in user_rate_dic:
    5 X6 y: B" b, D* w# w            user_rate_dic[i[0]].append(user_rank)" _" u5 f! B  k, o
            else:* D+ x" x" K( @1 h+ i4 M: |
                user_rate_dic[i[0]]=[user_rank]
    9 k6 k' s4 r; |; T6 Q, @- e            / {! H; q" y0 l- T
            if i[1] in item_to_user:) W6 O6 a8 W) @  C% z& x' }6 V
                item_to_user[i[1]].append(i[0])$ v7 h9 E2 E2 X: ~" T% U, q
            else:: U2 G/ w2 j* N+ n" i
                item_to_user[i[1]]=[i[0]]/ \, `; O1 e1 E) ~3 ~3 g  j& e
                
    . G- Y5 i$ \+ J    return user_rate_dic,item_to_user
    . l0 }+ Z! g# _8 `/ l* l- \) X: X8 H" R- i
    , Z$ s5 U- }! }8 F
    #) j6 j1 s9 r5 j0 g. _: R3 E4 a( E
    #   计算与指定用户最相近的邻居3 g7 H" D# S8 A% z! t7 ?  t
    #   输入:指定用户ID,所以用户数据,所以物品数据7 c9 Q* D* X! L
    #   输出:与指定用户最相邻的邻居列表6 I6 Z6 d5 T& Z% H0 K
    #6 [/ \$ d0 P( w$ x
    def calcNearestNeighbor(userid,users_dic,item_dic):% ~5 F7 {( H5 q% j' @* g
        neighbors=[]; x$ T! P) c4 Q# s) }0 N! s' n
        #neighbors.append(userid)/ ]6 Y, K4 a8 h4 l: r7 e
        for item in users_dic[userid]:' s& O+ X, g0 }8 X# o, v6 m
            for neighbor in item_dic[item[0]]:# |  b7 a& H5 H. N1 o: l
                if neighbor != userid and neighbor not in neighbors:
    , c8 B( j7 A$ v                neighbors.append(neighbor)
    , E+ ~) S: m. I/ n5 q      9 D6 J. P  x: ~2 p$ `  D9 E0 |
        neighbors_dist=[]
    7 h% v& e6 @8 G: `# v    for neighbor in neighbors:8 k% H' `! |' L# r
            dist=calcSimlaryCosDist(users_dic[userid],users_dic[neighbor])  #calcSimlaryCosDist  calcCosDist calcCosDistSpe' Z* a" D) d; c  N+ {4 o% ^& A
            neighbors_dist.append([dist,neighbor])
    + N7 o: E$ _: z/ M9 p/ G4 T2 J' b* j    neighbors_dist.sort(reverse=True)& Q# [# a6 [" z4 ^' N% h
        #print neighbors_dist
    ( @: h3 ]2 X& K  p: W+ N3 N    return  neighbors_dist2 L( x5 S: a6 q6 F3 }+ ^! v
      Y0 v0 U& c5 `, U
    0 f  F( m' P. ?8 c
    #
      O+ X1 l0 d! o#   使用UserFC进行推荐
    2 B$ N7 s. K* e6 ]6 w; h#   输入:文件名,用户ID,邻居数量! j7 L  Z$ U! Q
    #   输出:推荐的电影ID,输入用户的电影列表,电影对应用户的反序表,邻居列表) [6 J6 P9 ?- o7 @7 U
    #4 R! \. X( b  w. }( [$ }+ K
    def recommendByUserFC(file_name,userid,k=5):
    9 S2 V* u; D; g& P8 R    6 J( S2 B( }: K9 S+ p! n: i
        #读取文件数据
    . ?9 X! @; Z# C2 M. e    test_contents=readFile(file_name)
    ) G! G0 [4 e; V7 b6 o   
    ; r4 s5 |4 B8 P# `! M    #文件数据格式化成二维数组 List[[用户id,电影id,电影评分]...]
    7 C! O" k/ l" b+ m    test_rates=getRatingInformation(test_contents)3 w1 d4 E- w5 i0 y6 U" |7 _
       
    & W6 a6 h' Q' ~  S1 i    #格式化成字典数据 - U1 t8 z: ~+ E8 }
        #    1.用户字典:dic[用户id]=[(电影id,电影评分)...]8 B* d  b2 i5 F7 `! R5 U' X
        #    2.电影字典:dic[电影id]=[用户id1,用户id2...]1 k! M  \; w. J4 M
        test_dic,test_item_to_user=createUserRankDic(test_rates)1 _( [9 M( a, N; b/ Z3 C  R$ Y
       
    ; I7 f' F" z1 e1 }, C* M% b5 D    #寻找邻居5 ]7 v6 a% {6 @& j6 G  Z
        neighbors=calcNearestNeighbor(userid,test_dic,test_item_to_user)[:k]9 q) [7 }. x6 e3 j" W% e
            3 ~7 E) S- A2 ~+ o* i7 D3 ^
        recommend_dic={}% L3 [6 V! l5 J: ]8 E. m( r% O7 k
        for neighbor in neighbors:
    $ F( R7 I+ E, o6 m        neighbor_user_id=neighbor[1]* W. n+ `1 U% x: B: H; y+ M
            movies=test_dic[neighbor_user_id]# q$ d5 X$ e0 ~; Y- x
            for movie in movies:
    ' M0 e; A- s, x  E' E            #print movie8 Z4 q8 I$ b1 k
                if movie[0] not in recommend_dic:+ l+ Q5 `: Y+ j8 g  L9 {
                    recommend_dic[movie[0]]=neighbor[0]
    . {0 r) z' T- Y5 H) V( b3 u            else:% d5 e9 }; U* r! l) H
                    recommend_dic[movie[0]]+=neighbor[0]
    % Z+ y! Y1 y$ a& f/ ?9 g    #print len(recommend_dic)  m8 N3 Y. ]) c# l
        1 u$ ]& I' X3 Z, e, R" g2 ~$ q, p/ t
        #建立推荐列表
    5 B$ I3 W: U  h    recommend_list=[]2 J5 B1 Q, P7 |; n- ]
        for key in recommend_dic:) z0 S- T! l6 s: N! Y* r% W
            #print key
    / ]( O1 y1 w% K2 `* D* K; B        recommend_list.append([recommend_dic[key],key])
    ) X% R9 D1 n% B   
    - h4 N2 i3 J' B8 c$ X   
    9 m1 ~* I4 ], O: y    recommend_list.sort(reverse=True)
    7 s2 c0 g. |. z3 W1 V    #print recommend_list
    . C; l' ]5 v( _1 x- R    user_movies = [ i[0] for i in test_dic[userid]]
    4 O4 V1 ?7 T; {# M1 I( e( X& \( ]% a; e1 P" X1 ^- [" O. h
        return [i[1] for i in recommend_list],user_movies,test_item_to_user,neighbors
    % Y- H- l7 c& X7 ^4 D7 Z    1 ?! i; o& J/ P) R1 Z$ F
       
    . r) A  z  ]/ L; P# V( |5 J8 r. j  ?  \$ ~3 ?
    #1 z# a/ O3 r6 T  x
    #
    5 Z! E4 W4 G0 k& j% {9 \9 C#   获取电影的列表4 b3 _5 s; Y8 L! L/ o& e8 d# w& P0 M
    #6 _2 h6 |  P/ i& l
    #/ ~, C$ U+ p$ C. e+ |6 k
    #
    # U/ Z& Y4 S1 U0 d- E& O+ }; W* ]6 q6 Ldef getMoviesList(file_name):
    : e* ~/ ?+ u, ~" g    #print sys.getdefaultencoding(): s$ O& u6 V5 R* Q& J1 }
        movies_contents=readFile(file_name)! P  Z4 E" [* h8 t1 K3 p) @8 h4 A/ u
        movies_info={}5 \* D- \, @, h% F: c6 p
        for movie in movies_contents:) I. p# M  v' V4 Q" `
            movie_info=movie.split("|")
      W2 v/ Y5 Y0 f2 o+ n2 d        movies_info[int(movie_info[0])]=movie_info[1:], B  A0 T8 |; Z" t! K5 E
        return movies_info
    . q: H+ z; _- Z0 V7 d    8 l: B1 `% e) M7 f/ M+ j3 ^
        ) X9 \) S' N6 f
       
    0 }  p' c2 O7 [* E+ X#主程序
    ! E! y5 M8 a, W8 L& w' ~+ t' e1 i#输入 : 测试数据集合
    ! k% V1 b1 p9 a2 Y- N  d! Rif __name__ == '__main__':
    9 A/ L3 x8 O: C0 g, f    reload(sys)
    - \# i/ a& I! x3 e9 `    sys.setdefaultencoding('utf-8')( l  g- {: s% E% F5 [, E: u- g0 M
        movies=getMoviesList("/Users/wuyinghao/Downloads/ml-100k/u.item")- W1 [0 o* {( w' U4 @% i
        recommend_list,user_movie,items_movie,neighbors=recommendByUserFC("/Users/wuyinghao/Downloads/ml-100k/u.data",179,80)' v4 L2 d9 b* i5 F7 R: }& D
        neighbors_id=[ i[1] for i in neighbors]7 n+ O5 V8 x; _* F/ S- |! l
        table = Texttable()
    / H3 |3 F4 }* d+ l' x* d, t" C    table.set_deco(Texttable.HEADER)
    + O5 J' e7 t, [    table.set_cols_dtype(['t',  # text ( G+ \4 l- l; ?1 D0 {* l
                              't',  # float (decimal)5 P& o% @: l+ M) B
                              't']) # automatic
    . W3 z% `9 P. Z    table.set_cols_align(["l", "l", "l"]): H! _& Y9 V: ^# U
        rows=[]
    5 _4 o0 A7 L7 ^( b% m; e* C    rows.append([u"movie name",u"release", u"from userid"])7 {/ A. S# Q5 A- B' X
        for movie_id in recommend_list[:20]:
    ( _7 h" ?0 F: p        from_user=[]& b- V$ l' Q# C, |- Z3 s
            for user_id in items_movie[movie_id]:" f. E7 x# R* v) Y& o& m0 w
                if user_id in neighbors_id:
    3 H, _( a* l& P! D3 |7 n- O                from_user.append(user_id)
    # j2 i' m/ x8 d        rows.append([movies[movie_id][0],movies[movie_id][1],""])
    4 R) F+ D# [8 v: `8 R4 B    table.add_rows(rows), r( U: Z# }. w; V2 ]" W/ M% A
        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
    # @2 m3 F" O* D: q; [* }  b# -*- coding=utf-8 -*-
    ; f( [* {. F- x: A6 Z; G! T9 u; y% G/ S, K; P
    import math
    - r) _8 k, ^! @7 N
    这是什么语言的程序?
    2 |' o  Z/ K, i! g+ z
    回复

    使用道具 举报

    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-13 20:42 , Processed in 0.464195 second(s), 68 queries .

    回顶部