QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 4168|回复: 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 H6 _: [" U- O& O. f; \
    zan
    转播转播0 分享淘帖0 分享分享0 收藏收藏0 支持支持0 反对反对0 微信微信

    3503

    主题

    537

    听众

    5986

    积分

  • TA的每日心情
    开心
    2017-2-7 15:12
  • 签到天数: 691 天

    [LV.9]以坛为家II

    社区QQ达人 元老勋章 发帖功臣 新人进步奖 优秀斑竹奖 金点子奖 原创写作奖 最具活力勋章 助人为乐奖 风雨历程奖

    群组2013年国赛赛前培训

    群组2014年地区赛数学建模

    群组数学中国第二期SAS培训

    群组物联网工程师考试

    群组2013年美赛优秀论文解

    # -*- coding=utf-8 -*-  P$ [6 I! l3 [# n

    1 H6 a+ o% G4 Q8 l2 pimport math
    & F3 Y* q- n+ timport sys
    + M$ _% J) \/ D& }' t$ Rfrom texttable import Texttable
    ) {% c6 z/ Q9 q9 I& b' y% ]$ Z$ V
    . v$ S! _) t+ K
    9 H+ J8 h- R1 y" {#
    4 U8 t& I+ {& \4 H#   使用 |A&B|/sqrt(|A || B |)计算余弦距离- U1 W1 G& j9 B+ R" G
    #
    6 @' M; f2 b3 ], i#+ k( [8 p& C: F4 E, C0 v2 n) i
    #5 I7 v* R0 i6 m9 A9 d
    def calcCosDistSpe(user1,user2):
    " S6 K/ y+ t6 S& B    avg_x=0.0
    5 k: M( g# I2 W6 r    avg_y=0.0
    4 f! U2 \) e8 N    for key in user1:
    - z5 V3 ~5 ?, {        avg_x+=key[1]
    ; ~2 X7 V) T, \/ K, ]    avg_x=avg_x/len(user1)
    6 G9 v* j5 \) v: H" c    + i9 m2 O, m+ s; \3 v) `) Z
        for key in user2:
    + d9 ~: _( Z% [7 z        avg_y+=key[1]
    4 E2 L6 I- [9 n, G$ A    avg_y=avg_y/len(user2)& n1 G' S9 W/ P
        2 R1 r6 D2 Q2 I! j6 x$ O* b5 e
        u1_u2=0.0
    ( T: }/ ?" f5 L( Y- M4 F6 N  C    for key1 in user1:
    ' b" _6 k& u. c7 H" g% C        for key2 in user2:2 f; f" g5 V! R3 @* D* G
                if key1[1] > avg_x and key2[1]>avg_y and key1[0]==key2[0]:: [2 Y8 B4 z$ {( N! B5 `4 `. e
                    u1_u2+=1: [  k& J* i8 z9 F2 L0 H$ e
        u1u2=len(user1)*len(user2)*1.0% U, {- r! G0 ^% r3 m
        sx_sy=u1_u2/math.sqrt(u1u2)
      w1 x; `# u+ p9 Q    return sx_sy* v# d9 S% ^$ m2 C4 d( b7 K

    5 \, Q  ~; P3 L( X
    5 H7 x4 o4 N. z3 K/ ?/ \; v#
    % b2 q4 Z0 s( a$ l5 C; y9 N+ d, M#   计算余弦距离
    - ~' i' k, D  Q8 A#5 O8 @  c9 G  h$ `1 g
    #
    8 U2 W+ c! s. }: j# L' _% [def calcCosDist(user1,user2):
    - E6 c. A: c8 w9 ~, f    sum_x=0.0- M  |3 h' j! x9 {. X( H  R
        sum_y=0.02 [& I, l9 i( A8 f
        sum_xy=0.01 |5 ?# G+ x9 @9 K5 T; o
        for key1 in user1:6 g2 Q/ Y0 U2 @/ Q% j2 b5 O
            for key2 in user2:' w; l* f% [8 x5 Q/ @4 t
                if key1[0]==key2[0] :
    9 B- n) A3 Q* u3 U% @5 s- B; x+ B3 `                sum_xy+=key1[1]*key2[1]( ?* ]. Q' K7 v  [
                    sum_y+=key2[1]*key2[1]
    0 b, |) U2 U0 C5 a  T# ~& e; G                sum_x+=key1[1]*key1[1]5 E+ {& w2 W0 x/ B! e* F
       
    9 Y& n. Z1 c5 l1 }7 k: z    if sum_xy == 0.0 :
    / p' H% I: S1 l0 N% b8 v        return 0# v' a( C* @7 @# L  \- {! m  `6 |
        sx_sy=math.sqrt(sum_x*sum_y) 0 p$ X  f8 A5 L( K! ]* T3 C% g
        return sum_xy/sx_sy
    4 d# X7 }. j5 V/ g) ^& O
    3 Z# I# d5 u' k
    4 \5 ]4 {! [9 a- g3 G1 b#$ B5 S, i3 i/ R8 ]
    #
    ( p0 H( A/ b  r) Z7 M#   相似余弦距离
    9 h4 i* z* C0 Z' B; K#/ }: x5 K% }% @7 F  r! f* I. b5 n9 v
    #
    " a9 Y: c- r0 y% z" c1 K( v1 t#; ~5 X+ P, g* G/ a3 C; t
    def calcSimlaryCosDist(user1,user2):
    4 z8 j8 w3 k" `4 f6 j3 F) ~    sum_x=0.0
    1 y+ x& j" m: e$ a9 E    sum_y=0.0
    : M2 U2 p6 h* T* p4 S6 }    sum_xy=0.0! T) C; v4 e% w" P( I
        avg_x=0.0. T3 f; M* ]) r  ^  l/ t5 l
        avg_y=0.09 S- C' |) H* C6 {% C  b
        for key in user1:
    0 W# G6 K$ d; k* `7 A9 o7 Q        avg_x+=key[1]' e% `; o, J5 ]' n+ ]6 A
        avg_x=avg_x/len(user1)
    2 T, i" D0 P! C: Q   
    2 Z$ R5 n3 p! C+ i6 U    for key in user2:
    4 P5 m! z) K+ e- D' d+ Q  T        avg_y+=key[1]
    " {1 d8 H7 W  H5 P$ Y, K    avg_y=avg_y/len(user2)8 u( S1 ?/ F- u% x" \5 d9 W/ k3 S
        + r) d; ~2 ]; S7 h5 H
        for key1 in user1:- M" u0 L9 n' R# q5 ~
            for key2 in user2:
    7 m" n3 z; ?1 \4 ]+ M) U! }            if key1[0]==key2[0] :: E% G8 {# S$ Q$ c
                    sum_xy+=(key1[1]-avg_x)*(key2[1]-avg_y)5 R1 `% \+ z% e1 F$ y
                    sum_y+=(key2[1]-avg_y)*(key2[1]-avg_y)
    1 f4 }; i# Z0 N  }/ D9 e        sum_x+=(key1[1]-avg_x)*(key1[1]-avg_x)0 A) K* V3 k& ^  c( L
       
    8 B  |) Q1 E- X& q0 B3 s    if sum_xy == 0.0 :
    ; d- F' s& {+ d, `  b        return 07 Q8 L& n) g$ H& |  G9 M6 @& a& L
        sx_sy=math.sqrt(sum_x*sum_y) % o; w! c/ H: @! t4 a" }( S7 `
        return sum_xy/sx_sy
    ' n/ Z! t( M: M   
    0 c- c$ W6 o! p6 m* i
    , }4 Y  C3 T: V2 Y#
    & e- d* f6 A1 u4 l% x# ?! D#   读取文件
    " L3 A1 a6 u$ \: ^#
    % Z+ {/ k+ J- ^# ~9 M9 Q' ~; T% }#
    7 R+ v  S) Y( G0 K1 K4 x4 Kdef readFile(file_name):
    ( ?, [/ f) l$ o8 k0 y$ [    contents_lines=[]
    3 R# P' A4 m; t/ \4 x( b) y8 S    f=open(file_name,"r")8 S  h( x3 o$ `; p4 @! c/ o9 t
        contents_lines=f.readlines()# t( R, k1 r4 H5 v5 ^
        f.close()
    ! k1 ~# e8 H( n& `1 K    return contents_lines' e: I1 t7 g7 ?0 T, z! v1 U) |

    9 o5 G6 j2 Z* V4 c9 d$ _" d  o
    * k2 _" N/ ^& `5 q( m- c
    2 L3 ^# S; P  w7 ?& D, F: h#1 D0 J* Q) F. j/ u6 Q2 H' {
    #   解压rating信息,格式:用户id\t硬盘id\t用户rating\t时间. ?5 X" k$ m% S( N1 D. f
    #   输入:数据集合  y3 F( c: X6 }" S; X  |
    #   输出:已经解压的排名信息
    1 n* t& }5 S4 x- [! @#
    ; N/ P9 V: O+ }$ s" |def getRatingInformation(ratings):
    ' J1 T9 U- F: A* c5 T7 F    rates=[]- a) O" Z1 A) i* \, Z2 r
        for line in ratings:
    * t& Q. O* N. u( W3 W* s        rate=line.split("\t")
    ) L3 j! Z# R7 C        rates.append([int(rate[0]),int(rate[1]),int(rate[2])])
    & m% a$ U8 |8 K: |, O' k    return rates4 C, P' Z7 `7 R+ P

    9 n! R. [0 `* d2 H" F
    : X0 f% d* }/ |  O/ P#
    1 Z4 w! i8 r$ L8 b: s# T#   生成用户评分的数据结构
      [& o" d) g( E#   # A9 F: j( m7 }6 Q7 q; `8 E0 ~
    #   输入:所以数据 [[2,1,5],[2,4,2]...]
    & B3 f& v2 a% ~#   输出:1.用户打分字典 2.电影字典: m2 K4 T0 n. ]
    #   使用字典,key是用户id,value是用户对电影的评价,
    % y1 y9 n9 J8 p) ?8 w" F) \( C#   rate_dic[2]=[(1,5),(4,2)].... 表示用户2对电影1的评分是5,对电影4的评分是2
    / S% O/ P( B7 O' Q/ \: [# S6 e#4 \8 ?5 O0 ^& r# @* h( Q
    def createUserRankDic(rates):: \5 B$ X/ h# t9 H
        user_rate_dic={}
    - S( }5 H7 U. {* v% `6 B    item_to_user={}+ t6 l! U) M1 I2 Y5 G  Y9 ]
        for i in rates:$ v. X3 g: y  Z: Y+ u' G$ ]
            user_rank=(i[1],i[2])8 @: u4 k2 w" Y6 D5 e, k
            if i[0] in user_rate_dic:7 t0 Y, v" t& i  v8 ?
                user_rate_dic[i[0]].append(user_rank)
    % B, x7 n  r9 F/ {, a8 N        else:
    % ]3 g% O7 d. `( y. G. c            user_rate_dic[i[0]]=[user_rank], }, ]  [& k3 l7 Y  [4 p' {3 A
                4 P3 M+ t8 q0 D
            if i[1] in item_to_user:
    ) i0 B- k9 L* W% ~4 m            item_to_user[i[1]].append(i[0])# e0 a1 f( c  V! C
            else:4 q3 e3 }% w  E8 w5 u* y( S) I
                item_to_user[i[1]]=[i[0]]5 k+ Z  D) E% T3 k9 w0 m
                
      T4 ]; `( [* V. a3 R    return user_rate_dic,item_to_user
    " c) F- K) l7 |4 U* S: r0 J* Y- V2 h
    ( U1 T& }( {8 ~' _, X3 s- a2 t
    ; s5 F3 ^2 m; ?$ f, I" t# V#
    7 s& I7 G4 U( _7 |#   计算与指定用户最相近的邻居
    ( s' U/ W% @: A% c#   输入:指定用户ID,所以用户数据,所以物品数据
    / G' a4 s9 ~1 k#   输出:与指定用户最相邻的邻居列表; F1 J; Z- m& y! |
    #" W4 B' D1 W! M; y, N5 ~$ P
    def calcNearestNeighbor(userid,users_dic,item_dic):
    4 M0 z6 S% |+ w. s5 ~    neighbors=[]. N3 K1 n5 k6 G0 N
        #neighbors.append(userid)
    5 v1 E( ?' y) t! L    for item in users_dic[userid]:* ~; |, O, ]4 {3 P# \7 d
            for neighbor in item_dic[item[0]]:
      H8 i- X: R3 X6 u            if neighbor != userid and neighbor not in neighbors:
    + y/ Z( @9 b( ~: L2 |# }                neighbors.append(neighbor)! Y2 G1 g& K; k
          3 J5 K& `: a9 N
        neighbors_dist=[]
    % G, r" c$ |* R" ]# @    for neighbor in neighbors:# ^, H" w1 p3 h6 _/ J$ l+ I  i4 k
            dist=calcSimlaryCosDist(users_dic[userid],users_dic[neighbor])  #calcSimlaryCosDist  calcCosDist calcCosDistSpe- m& T5 z4 C" u# H+ w0 R
            neighbors_dist.append([dist,neighbor]): K' G# x0 d3 {  `8 M5 c7 j
        neighbors_dist.sort(reverse=True)
    ; F- u' B) J8 R8 {& `    #print neighbors_dist3 K1 A* [$ d5 X* v4 Z; B
        return  neighbors_dist! \1 c0 _' j4 A1 i3 }, g) V4 T
    ' g! _0 Z, l5 K$ f% p
    " _& s4 H" R" X
    #) C, U3 k3 ^4 X: I) l8 t
    #   使用UserFC进行推荐& w6 _8 J+ I; o  ]
    #   输入:文件名,用户ID,邻居数量/ G% Z! z3 }4 g- s) d. p
    #   输出:推荐的电影ID,输入用户的电影列表,电影对应用户的反序表,邻居列表
    . |0 X! o/ j  I' }8 b, Q#& }7 V2 X$ q2 Z/ z$ j3 C
    def recommendByUserFC(file_name,userid,k=5):
    , g. Q) `( A1 D      K  p) `% ]1 g. p* ^
        #读取文件数据
    1 g5 r8 e  J  D0 G$ w: v1 M& j& t    test_contents=readFile(file_name)
    6 ]* Z! d8 O3 f1 K: W   
    ( k0 k+ g) x6 X% b    #文件数据格式化成二维数组 List[[用户id,电影id,电影评分]...]
    : q" Y5 e! T' |+ {: F    test_rates=getRatingInformation(test_contents)
    / a; V8 l; b& }; V( w9 J, w6 f; |4 E   
    ' {/ j( u9 Z/ [& y7 T    #格式化成字典数据 2 M  u: Y6 ~4 {. w1 v1 q
        #    1.用户字典:dic[用户id]=[(电影id,电影评分)...]
    4 k/ Q2 f# p2 |" x6 Y. ]6 R    #    2.电影字典:dic[电影id]=[用户id1,用户id2...]! l  `  V( _4 u# @% q' ~) Y5 S& c
        test_dic,test_item_to_user=createUserRankDic(test_rates)
      C5 k' c$ \" B# U   
    : {8 A% u1 W) b1 ]    #寻找邻居
    * ?3 U2 E; D8 z2 s  ]9 J  }0 }    neighbors=calcNearestNeighbor(userid,test_dic,test_item_to_user)[:k]
    8 F! t+ r5 S3 v" W        
      p& H2 f5 F4 d- y    recommend_dic={}4 F, h6 i* s3 @* u" G9 s, p* y
        for neighbor in neighbors:7 s9 \9 H" j8 {/ M: N9 T
            neighbor_user_id=neighbor[1]; V% V& D4 E' A8 O  x% Y/ P
            movies=test_dic[neighbor_user_id]+ G( K, D1 r5 [. v# O6 u  P7 q6 o
            for movie in movies:
    4 v% |% K8 @: f0 E* E+ L8 e8 b            #print movie( p% a3 E" n/ q6 |
                if movie[0] not in recommend_dic:: R' Y9 j: M3 o, D- t
                    recommend_dic[movie[0]]=neighbor[0]
    8 y' K; u4 Q& t: [8 b7 U            else:5 g, P% Q8 ?+ E/ Z/ |9 N  n( t
                    recommend_dic[movie[0]]+=neighbor[0]
    0 _7 q3 h9 W# U% J& m- `  j    #print len(recommend_dic)( Y: P% }8 q6 \; {( M1 F+ `
        . u  l  r9 g$ p
        #建立推荐列表
    0 P  c! N) |! p+ u' e8 a& J" T    recommend_list=[]9 @  ~4 P4 H6 ^3 G* E$ g6 \* s
        for key in recommend_dic:$ _8 U2 Q( V  A5 l5 h5 b9 }
            #print key
    ! i: T4 N: T+ F& }! E        recommend_list.append([recommend_dic[key],key])
    6 ], c# K, d$ T    " R. n5 r) g* O5 z4 U) }
        . @6 n" v( m$ U% `8 s& v
        recommend_list.sort(reverse=True)2 G/ \5 r. Q. _5 B1 T1 b0 h- e
        #print recommend_list+ V5 Z% E2 b8 S
        user_movies = [ i[0] for i in test_dic[userid]]
    , h( v- ^% Z% P0 \8 t" V' u5 n5 k+ D4 y; f
        return [i[1] for i in recommend_list],user_movies,test_item_to_user,neighbors
    % n3 f% a9 I. T   
    " \9 P- l/ S# E$ T6 L4 Z$ \8 v+ s   
    $ e4 W" ^1 t3 j  S) S# b% v2 |7 ]: M$ _% X
    #
    * L! `8 l: C- f7 ~- S7 [#7 n- V$ z3 V2 J$ [8 O/ B
    #   获取电影的列表
    2 p6 G& K) Z2 N' f#* }8 ^$ d: G8 ]. Y0 w
    #
    ! e. J" q8 ?: l7 @% W#8 [! Z4 e. I- R3 N) `
    def getMoviesList(file_name):
    8 S/ `1 H  d, s6 A, L& S    #print sys.getdefaultencoding()
    7 p% b  a4 C+ R    movies_contents=readFile(file_name)
    8 f  Y- N& a5 J& l    movies_info={}% }- M* C+ I) `0 B6 |0 h2 p- a
        for movie in movies_contents:
    * F& A0 w% V) o, G5 x        movie_info=movie.split("|")
    $ h4 i+ J8 F' \7 w# ^        movies_info[int(movie_info[0])]=movie_info[1:]
    ; e. P4 }  W! L2 f, s    return movies_info8 w' t/ M/ N5 A1 P/ ]% B
       
    4 _/ j" j5 D  \9 l$ P' {- P7 w    $ H( ?( q' s0 _# e
        5 k2 D/ e8 W# }) F9 [: X# i
    #主程序
    ( q+ t' Q3 v, O  R9 Z#输入 : 测试数据集合+ m3 A: A6 G# Z- Z- q. K
    if __name__ == '__main__':' }$ `0 n: X  J0 ^) _5 I
        reload(sys)6 d9 ?% A' a* P
        sys.setdefaultencoding('utf-8')) I6 V, ?; V( Z2 D9 F% i7 j9 f4 U
        movies=getMoviesList("/Users/wuyinghao/Downloads/ml-100k/u.item")
    ! s4 I/ I. [% R8 P8 i, H; `    recommend_list,user_movie,items_movie,neighbors=recommendByUserFC("/Users/wuyinghao/Downloads/ml-100k/u.data",179,80)1 h/ a: V' q, d
        neighbors_id=[ i[1] for i in neighbors]
    - v9 ~8 t& e4 i4 _/ a    table = Texttable()" P" u1 s( r' r' E& x% C1 J
        table.set_deco(Texttable.HEADER)2 _1 a4 U4 a9 q& S8 y; e. o& q
        table.set_cols_dtype(['t',  # text ) n1 u+ `: }. }8 A
                              't',  # float (decimal)4 \  ~/ T# L/ l1 b4 [, J4 [  h
                              't']) # automatic
    & q# ~( \7 n( I6 u7 ^2 U. m    table.set_cols_align(["l", "l", "l"])- e# ^% F! }' L! E" |
        rows=[]' f( A$ w, I* v9 }  n' g+ o
        rows.append([u"movie name",u"release", u"from userid"])3 k6 {6 k* }/ b$ e
        for movie_id in recommend_list[:20]:
    6 P  _' a  l2 a# D- R        from_user=[]) o* M( P; I8 B0 [6 n9 R
            for user_id in items_movie[movie_id]:
    1 |# e2 L+ g2 v6 Z- _9 `, P            if user_id in neighbors_id:% L% Y2 n3 ]9 T4 D; a* N
                    from_user.append(user_id)
    ) a. f7 M7 _7 }6 K+ b3 N' N! S        rows.append([movies[movie_id][0],movies[movie_id][1],""])
    / H9 y/ [1 U' G' [6 S    table.add_rows(rows)9 _& k' U, m  a3 q* V: p
        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 }& i5 z' d& T8 m% c# -*- coding=utf-8 -*-
    & T! |  m- M) c: [7 l+ b. \0 Z2 v* j6 w3 o
    import math
    ! R8 ]# K. ]* |# E7 B, F4 Q& x
    这是什么语言的程序?+ K  \! W( P# E2 Q+ b
    回复

    使用道具 举报

    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, 2024-4-26 10:35 , Processed in 0.591257 second(s), 67 queries .

    回顶部