QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 4167|回复: 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 c: M) A$ G) N2 V: U
    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 -*-5 X  [% G% @0 n$ _

    6 g" D# ^! g5 H& y' W4 p+ eimport math# h  M5 M( Y1 L1 P0 ~" {( c
    import sys( k" T: Z) U3 F, T
    from texttable import Texttable* }8 n1 k6 |) I8 t( ~+ L

    , j" a* G# F" O( n) |! J
      n4 w# F0 [6 n' Z7 f$ N+ D1 i#
    ! I, m' v/ O7 C/ ]1 e#   使用 |A&B|/sqrt(|A || B |)计算余弦距离
    " U* f: o' D) Z/ |#
    + W0 o0 p" O+ L6 M. n4 Z. k#
    ! G/ A- N2 S# f( y2 z& f#7 {  s8 O) A5 j; v# W
    def calcCosDistSpe(user1,user2):" U' w% R* O; u3 B- F0 w
        avg_x=0.0' m" p3 {9 r) \$ |
        avg_y=0.0
    8 m0 O# E% s( O    for key in user1:# U, ~9 K+ r. f( N
            avg_x+=key[1]0 n/ J+ Z8 R% z7 T' f  Z; w
        avg_x=avg_x/len(user1)/ B1 @2 x2 Q/ ?7 p9 ?5 F
          s/ j  A& W) T6 \4 u
        for key in user2:
    / A/ |" S) d+ F5 N        avg_y+=key[1]1 m& M- ^# U% k4 j
        avg_y=avg_y/len(user2)6 |' X: x6 j% `4 E& D8 v
       
    / ^  ~" e- c5 o# J    u1_u2=0.0" Y0 {" ?# U: ?+ X# A  c- I7 ^
        for key1 in user1:/ k' U, C  m$ U4 c
            for key2 in user2:
    . S$ Z) R9 s3 \/ v            if key1[1] > avg_x and key2[1]>avg_y and key1[0]==key2[0]:4 l' F6 A6 I! {" l3 C8 z
                    u1_u2+=10 @/ H# F: O- N! g/ d
        u1u2=len(user1)*len(user2)*1.02 m" E# ~9 E# U
        sx_sy=u1_u2/math.sqrt(u1u2)7 c3 s  a7 ?/ ?" Y! g
        return sx_sy
    : U  _$ X: d7 {( x7 @5 s7 |
    ) O6 m6 u( U; M8 h( [1 P9 [2 H. \5 t
    2 H. b7 W2 G# h7 U% Z#4 C. d8 h5 J) {1 W/ t
    #   计算余弦距离
    ' j1 x+ f: \! q#
    $ f$ O0 E% T" z5 `( J#
    $ C; `4 i1 T! I( vdef calcCosDist(user1,user2):
    " `' v8 `, L4 b; d    sum_x=0.07 @* n4 C8 _: Z' \+ T$ C
        sum_y=0.0
    6 G# c9 A7 n; M4 r1 B& h1 w4 J# L    sum_xy=0.0
    & ]& z  B- V4 Y2 D    for key1 in user1:' \' `/ d9 ?. H7 R$ E1 G7 \
            for key2 in user2:3 b# ^8 ?, Z4 C% ~$ C1 N" X/ b' a. j
                if key1[0]==key2[0] :$ S; ]# G$ ]9 n- k
                    sum_xy+=key1[1]*key2[1]
    ; B' d2 ~) q/ C" j! L8 d$ q4 E& n                sum_y+=key2[1]*key2[1]# }7 o9 J8 m+ Q
                    sum_x+=key1[1]*key1[1]
    : |9 I, r' f3 ~  ~3 Y7 A4 M9 q* w& u   
    ( u6 J0 k% [6 Y    if sum_xy == 0.0 :
    0 U3 f: T/ `2 n9 ~9 d7 ]0 I        return 0
    5 P; [/ R5 ?$ j    sx_sy=math.sqrt(sum_x*sum_y)
    ( @1 m3 V% h9 q9 x    return sum_xy/sx_sy  l& ^( L: f/ B: C- s
    1 a* Y( A1 S  }4 P

    2 c4 E4 P4 h: R. @3 \( ?#
    3 {$ e. w6 F$ g6 }4 c5 j#
    . G) e- T' q- c+ ^! d' r#   相似余弦距离+ _) W# Y" z# e4 o. T7 u+ A& o
    #
    1 h! i  {9 `# C2 P2 ]& P1 m## _% s+ m5 G- F
    #
    ( ]6 H6 R1 I8 c- ~" Edef calcSimlaryCosDist(user1,user2):$ z9 f' g' U5 ?. u: B  S( d& m0 b& B
        sum_x=0.0
    7 s) l) U" I4 h5 T7 n7 J8 I2 v# A    sum_y=0.0
    ! `; e1 ^3 Y  r* [' v+ R7 n# \' a1 ^- @    sum_xy=0.0
      E/ a5 J$ ^; o4 n+ _( A    avg_x=0.0' A5 u8 E; O; p' f8 l( X
        avg_y=0.0- c* D  D8 v* H
        for key in user1:. D. i+ S5 z6 L
            avg_x+=key[1]2 o2 c3 ]) w3 Y8 I/ M
        avg_x=avg_x/len(user1)
    ! C4 f+ |0 O( |- M7 I( N' I) b    + B4 ^7 p+ p" K- S6 m0 Y
        for key in user2:: v: s& ?  W/ h
            avg_y+=key[1]/ N, `' r% [: o1 M3 H: x" ~
        avg_y=avg_y/len(user2)
    . j0 w8 u2 o! q) t# d7 P   
    ; Q/ [+ A) t5 v( M- O  _    for key1 in user1:
    6 V4 j1 K% `4 S1 V        for key2 in user2:
    0 P* y$ J) \- d7 k: |+ E            if key1[0]==key2[0] :
    % G2 r% E6 U6 W9 W# M3 G8 V8 L                sum_xy+=(key1[1]-avg_x)*(key2[1]-avg_y)
    , f6 M" p! t# M( E/ G+ E" z; v% c                sum_y+=(key2[1]-avg_y)*(key2[1]-avg_y)4 M$ U" a4 ~+ ~  v6 a6 w  W; O: U
            sum_x+=(key1[1]-avg_x)*(key1[1]-avg_x)- `; X* Y$ p4 q
       
    8 N- I- y5 |; a8 y    if sum_xy == 0.0 :
    ) ~& C4 n8 z9 D" h, q% k0 r( F        return 0
    ! P5 p% e5 A( `4 H% _5 \    sx_sy=math.sqrt(sum_x*sum_y)
    ( x! C3 n4 h5 J! n9 h    return sum_xy/sx_sy5 z( {* b: A( ?4 L0 b1 ]
        " y2 ~' b% w+ v

    " S2 K. |; n: n2 G/ b#! p5 g3 F9 O# c% W( c
    #   读取文件  s, e$ a/ v8 V8 t- L
    #' D2 r1 J/ v& Y8 \8 j& I
    #6 L& H$ o( F, O" O
    def readFile(file_name):6 [( O; M3 t( Z  \
        contents_lines=[]
    # O! c; F. K( a; |  [    f=open(file_name,"r")5 r; o& Z, W+ [+ `5 s
        contents_lines=f.readlines()
    , l. l8 E  P% o+ D! |* [0 b5 x2 i    f.close()+ u2 J3 A* ]! Z
        return contents_lines1 O: F1 t3 z4 Z5 B
    5 i) M4 O6 m$ e4 v; C
    7 w/ m3 G; L- Z* p. `% s

    5 S3 `2 m1 H3 p3 J3 Q/ h+ o! _#
    . B2 m1 h2 O* \#   解压rating信息,格式:用户id\t硬盘id\t用户rating\t时间8 s; u& |5 f0 }$ f( e
    #   输入:数据集合
    1 {+ m' y7 R2 g" E' q#   输出:已经解压的排名信息0 Q, J  C5 ~/ t1 P9 G3 C
    #
    8 p9 L) K! x6 Z% p) B' o, Gdef getRatingInformation(ratings):! @" M$ |7 J( {. B" E+ T
        rates=[]. [& V. E0 H, r7 P, }" G% g
        for line in ratings:
    / `" Y) w  J, K* N# K# b. Q        rate=line.split("\t")
    ( J# H+ l2 P4 _8 s! N        rates.append([int(rate[0]),int(rate[1]),int(rate[2])]): Q, S. R* n  q" c8 P9 ?/ [
        return rates
    " \7 k; g* r0 n- R5 m6 o
    3 A3 L0 N& a2 T& j
    # c, Z) J/ k  n#( z2 T5 X' @: P6 s. G3 n7 X
    #   生成用户评分的数据结构
    + j0 n0 a- p3 D7 B0 u5 z#   
    . U/ M. v; O/ h" E% ]* S#   输入:所以数据 [[2,1,5],[2,4,2]...]3 }, C# {! u9 Z8 o+ o
    #   输出:1.用户打分字典 2.电影字典
    9 @  q7 q) k: N4 _4 s4 Q( V3 \8 P#   使用字典,key是用户id,value是用户对电影的评价,
    : N( x6 [7 M5 Q/ I2 [#   rate_dic[2]=[(1,5),(4,2)].... 表示用户2对电影1的评分是5,对电影4的评分是20 N2 I; \5 p& O5 J
    #
    # @6 k# H' D' k0 G4 Q  pdef createUserRankDic(rates):, ?3 U$ S# J' F$ o. n7 C
        user_rate_dic={}
    " }) e7 Z' n: H, F' G7 i    item_to_user={}
    1 a1 L; [* I8 e% ^9 `9 `* P    for i in rates:5 E7 A( N' _/ |' ~6 C7 C
            user_rank=(i[1],i[2])$ ?3 p$ _+ @4 T- I
            if i[0] in user_rate_dic:
    . k: Q, j$ C% d1 s" S8 q/ L            user_rate_dic[i[0]].append(user_rank)! Q' t+ w6 V- H
            else:' i# K3 s4 L& z7 k) k
                user_rate_dic[i[0]]=[user_rank]8 D2 h) h: w1 }( D7 A. C0 L
                
    " w% D' I3 b. ]7 p        if i[1] in item_to_user:
    - t8 `4 Z5 E7 R. X1 x3 P            item_to_user[i[1]].append(i[0])* c: ]) J' e! F$ t0 L* Y% P& w; |/ E
            else:5 C) F1 c) @0 X, N6 M( O# p
                item_to_user[i[1]]=[i[0]]" A) n! }( a. a# }1 r3 G
                
    , D0 z% J2 Y, o5 D; y, h) C$ V. {    return user_rate_dic,item_to_user
    5 E8 C- R& t3 W# j3 I" o2 v: {, I: K  t

    , i+ r2 q; q6 p#, x: X8 k* _2 Z" t( @; A- {
    #   计算与指定用户最相近的邻居, E+ L4 h- H3 [9 R3 C2 r6 |
    #   输入:指定用户ID,所以用户数据,所以物品数据
    : ^+ W* g& ], Y1 g' L, q- f#   输出:与指定用户最相邻的邻居列表( W; @+ `5 Y  b' r4 a3 s9 n6 {
    #7 @" l! H# w; W0 R# L2 O( B
    def calcNearestNeighbor(userid,users_dic,item_dic):0 r# d* ^& U( Y
        neighbors=[]& S4 b3 M3 O+ x/ Z7 ]* l
        #neighbors.append(userid)
    " v: I  }2 D' d+ K& F2 C/ z$ A    for item in users_dic[userid]:
    6 E3 c& |0 L) v, k6 K        for neighbor in item_dic[item[0]]:) C8 j3 f9 x6 U( ^5 q" d
                if neighbor != userid and neighbor not in neighbors: 2 G8 P( q9 Y/ R; F
                    neighbors.append(neighbor)
    - m  d- A# V! ]% p( Y3 J      
    % ]  I, [; d/ s' x- X- `    neighbors_dist=[]/ [9 s% C0 X& x* w% M) X
        for neighbor in neighbors:
    5 h9 [: V2 x+ c* S8 I        dist=calcSimlaryCosDist(users_dic[userid],users_dic[neighbor])  #calcSimlaryCosDist  calcCosDist calcCosDistSpe
    2 v7 k* N' Q: \- M: A# ~        neighbors_dist.append([dist,neighbor])
    ( Z5 \- e+ I1 Z! l( M" i; v    neighbors_dist.sort(reverse=True)
    4 k/ V/ x3 J# w, k9 I    #print neighbors_dist
    ! a" `) w# T( L3 e  h    return  neighbors_dist& P# l: L* z7 W. t2 t0 m

    & |; f) [( |1 F
    : }) Z2 I+ Z9 c, v#
      X8 u: v6 m; K% a, K( L* Z- ?4 ]5 _4 o#   使用UserFC进行推荐  ?7 T1 Z3 n% o: {6 D+ U! T; e" t
    #   输入:文件名,用户ID,邻居数量
    6 p0 Q- V& @; l3 O0 U9 w& m8 f  b5 z#   输出:推荐的电影ID,输入用户的电影列表,电影对应用户的反序表,邻居列表
    7 {& e' B# }* o, l" \% ^5 [#6 K/ @' f. ]+ _" q+ _
    def recommendByUserFC(file_name,userid,k=5):
    4 ~" Y2 @9 i7 M* ]. d/ @    3 M# ], G* A7 O8 |* {) g
        #读取文件数据9 l- F' H: v, E2 `; s
        test_contents=readFile(file_name)  W+ C( l" L& Z) y( T4 x& b% i
        8 h! d9 Y, z4 I2 e8 M
        #文件数据格式化成二维数组 List[[用户id,电影id,电影评分]...] : p7 z# u# J" [
        test_rates=getRatingInformation(test_contents)
    8 b  r, S! p8 f% r. o( V! @0 Q    : o; o. H, X8 }4 G
        #格式化成字典数据 9 ~+ G5 n7 t$ A4 Y! T
        #    1.用户字典:dic[用户id]=[(电影id,电影评分)...]
    ! @5 n0 s4 r) n2 W( x! l    #    2.电影字典:dic[电影id]=[用户id1,用户id2...]
    / M9 d* x4 d8 G3 u. w    test_dic,test_item_to_user=createUserRankDic(test_rates)' v0 Y* v! x2 n4 t$ ~4 h- z
        + o4 W3 e# V5 X  l1 M
        #寻找邻居6 E$ f; G5 B8 \& N9 I; S4 h
        neighbors=calcNearestNeighbor(userid,test_dic,test_item_to_user)[:k]" Y4 y8 g6 W7 R' w9 J% V" Q: |
            
    : n8 X' v! v5 E1 \    recommend_dic={}
    ' m- \+ c) m/ A) n    for neighbor in neighbors:4 ^9 b/ c! \3 x1 ?# {1 W: u0 g
            neighbor_user_id=neighbor[1]
    % G2 u/ H* a* c( R        movies=test_dic[neighbor_user_id]
    # u' D" [" R' s; G9 X+ q        for movie in movies:& z& }* B5 e* _3 [5 t$ a
                #print movie6 ]) l. d1 v! N+ S
                if movie[0] not in recommend_dic:/ y1 ?# y& y0 c2 a; ?  s
                    recommend_dic[movie[0]]=neighbor[0]: ?9 O, {# R$ y; r! u# Z' T, |% x
                else:; o& H, G6 O8 h4 |5 V/ C
                    recommend_dic[movie[0]]+=neighbor[0]
    6 ^* \. I8 g& ?% W    #print len(recommend_dic)
    ! F4 ?) }7 w  j" D, {9 u: _   
    ! F. v/ ]3 n' z: K7 l    #建立推荐列表, T4 q" V  ]  S. Y+ \) U9 q5 y: v
        recommend_list=[]5 H9 p) H" |: ]
        for key in recommend_dic:' ^$ C2 C# k0 r6 n
            #print key4 q) O, w! A7 `5 c' ?$ Z
            recommend_list.append([recommend_dic[key],key])
    3 B$ ^/ u# [, R2 [/ m# l   
    % @+ }+ p! _4 F" a3 g0 D; A   
    6 d9 O$ n4 Z0 }: @& v    recommend_list.sort(reverse=True)% z9 y( F; O+ [2 W6 H! U
        #print recommend_list6 z+ I8 |2 ]# Z/ `- D/ @; [
        user_movies = [ i[0] for i in test_dic[userid]]( ]0 H; j4 x) ~& R; ^. S$ X

    9 \2 v% d5 Z& T# A    return [i[1] for i in recommend_list],user_movies,test_item_to_user,neighbors5 ^; c2 i! x8 f! v3 s3 G5 j# C
       
    " y& a7 i$ @5 [) C) _+ y  |, L# q    ) l8 `% g) _& [+ S# O! p0 C7 p3 @' u

    2 F4 W% c# S2 r. g8 l#
    5 j" ~2 c/ ^& W  t! }#, \! o0 h& n! v/ h5 C) \
    #   获取电影的列表& U2 ?+ y0 @7 a" d
    #+ E8 p- n; x: s0 T
    #
    . J# S# K5 J) {: R/ p" p$ ~#7 g1 ~" d3 n; J
    def getMoviesList(file_name):6 E+ t* e8 I4 f  r/ Y. E* ?
        #print sys.getdefaultencoding()" E* ?" v6 e- F' ~6 q; k& u1 @
        movies_contents=readFile(file_name)
    , H# E) S  C; M8 z6 W) l    movies_info={}
    . i4 T2 e) J4 Z1 V; V8 l    for movie in movies_contents:
    ) n! }" N4 m0 J% s$ u        movie_info=movie.split("|")
    . b) L; c* b+ R        movies_info[int(movie_info[0])]=movie_info[1:]
    : S$ J' _' x. @, [    return movies_info
    - O% p: v3 p* ^2 `, q9 v3 e   
    3 z, W/ V& f+ `! p" J( W. @   
    6 O- c" U* r1 F( Y7 X    4 C0 n; ?9 K4 P1 [5 U0 f
    #主程序( t% a0 D, O) F8 b
    #输入 : 测试数据集合6 l1 T! e0 P! e5 w
    if __name__ == '__main__':
    $ e4 o7 c7 H$ {6 Y: }    reload(sys)- ]) ]% ]4 Y& b8 u8 M0 |2 n. k
        sys.setdefaultencoding('utf-8')
    ' P7 A( B8 g. T( l8 k# S! A- k    movies=getMoviesList("/Users/wuyinghao/Downloads/ml-100k/u.item")3 R* L4 u# C3 c: J
        recommend_list,user_movie,items_movie,neighbors=recommendByUserFC("/Users/wuyinghao/Downloads/ml-100k/u.data",179,80)
    ( U! Y+ J* H# B    neighbors_id=[ i[1] for i in neighbors]" v5 x* `9 ]3 y, M
        table = Texttable()9 v: R$ K: I' V2 q- t  c
        table.set_deco(Texttable.HEADER)
    9 ?6 b  w" i- R, c2 b    table.set_cols_dtype(['t',  # text 2 k: P. f% [; H
                              't',  # float (decimal)
    7 x1 v, F9 @. Y2 ~  p  f* A5 S                          't']) # automatic
    5 X- W- D& }+ c. S4 M0 y0 C    table.set_cols_align(["l", "l", "l"])
    2 A( {6 @7 Z4 F  m+ h) Z3 V7 X    rows=[]
    2 p* q4 Z7 g- }1 f4 V5 i    rows.append([u"movie name",u"release", u"from userid"])
    0 e- ?% U2 j/ v6 J) o    for movie_id in recommend_list[:20]:1 \1 y. G5 s  x" w- {# V0 ?
            from_user=[]
    ' P+ c3 {! t; n# i8 o4 D% V. y        for user_id in items_movie[movie_id]:' n& F' w9 P: s: c6 B
                if user_id in neighbors_id:2 f% t/ {) i2 {; ~$ }6 h0 u, l/ E
                    from_user.append(user_id)
    0 _0 h9 o& I1 _9 k* ?        rows.append([movies[movie_id][0],movies[movie_id][1],""])" H1 f! |1 \* b" P$ V- F
        table.add_rows(rows)
    * N5 d. Q/ d6 B7 d8 A  I    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 : z! t0 ^& j! u! g" {& R
    # -*- coding=utf-8 -*-
    & B9 ~+ ?* `$ @0 k6 X2 y
    , E7 f: {7 p5 e+ H$ {4 Timport math

    ! d$ Z! s( i- J" K% O8 x这是什么语言的程序?
    ; Z( ?) V2 i! e4 ^. ?' N4 p& M
    回复

    使用道具 举报

    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-25 14:21 , Processed in 0.373442 second(s), 67 queries .

    回顶部