QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 5070|回复: 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
    本人在学校参加暑假培训,需要这个算法做题!求大神赐教,感激不尽6 A: X) |. b! E0 q% J
    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 -*-
    ( h" n$ u" ~% t
    7 ?1 O5 \: y" o/ ~) w- Dimport math6 I2 a* Q: E1 G
    import sys& [7 Y+ B2 V2 j( O
    from texttable import Texttable
    ) I6 r4 o% g( f% l7 t/ p
    9 P6 v9 h: B  J% x5 o6 t
    + k  k" T& w, }+ o) m7 T" J#  u" u* e6 @& R# {7 Z1 ?( q
    #   使用 |A&B|/sqrt(|A || B |)计算余弦距离
    4 _$ T/ P, P& _) v! R#7 l" x9 r4 q& t2 n
    #
      u; T* n; \. [" ~7 V# l% p- M. v#$ j0 Z; I( n: v1 t' }
    def calcCosDistSpe(user1,user2):
    2 O5 C: D0 ~  D" U  @& k    avg_x=0.0; U! o: `+ l" V, x. T
        avg_y=0.0
    , O9 \: d' O, f2 ~5 v8 O3 G, @    for key in user1:# e9 J/ Z; ]. U
            avg_x+=key[1]
    5 n$ G9 `$ N# p" o3 ~    avg_x=avg_x/len(user1)
    ( V* R: k' A, ~5 U7 F* o2 r   
    3 d1 W) U& z$ _: |    for key in user2:" T( D- d1 T6 @+ v
            avg_y+=key[1]
    : q/ Y& |- A2 {8 ^  u4 T& e    avg_y=avg_y/len(user2)4 G/ J; J# N) W9 }5 ]
        5 P/ T5 J7 f" i& ~3 x0 Q4 Q
        u1_u2=0.0
    " a# K, x8 S0 R( i    for key1 in user1:
    ! q4 j' c5 C" m+ \2 N! I        for key2 in user2:) P7 P% V& Q9 A' g$ y! _
                if key1[1] > avg_x and key2[1]>avg_y and key1[0]==key2[0]:
    . L8 B$ g, ]# `1 H5 c6 u                u1_u2+=1; d& k- h+ ]4 f( K& D' }2 h
        u1u2=len(user1)*len(user2)*1.0
    : G, X' ^- e+ a9 J8 G5 M    sx_sy=u1_u2/math.sqrt(u1u2)
    ' U5 R: f; ]2 o8 s$ h3 f6 G/ p    return sx_sy  L* |  D$ Y6 z$ ^  Z3 W9 O

    ; n* {* b( `) Q$ s. t8 G7 M" |$ ~, w  D2 g7 ?8 f1 p3 k0 v
    #0 Z! o/ ^9 r, W0 K9 A
    #   计算余弦距离+ A( e* [0 p! Y) ?/ V
    #7 \: z) D" f6 ^7 |! _
    #7 n, K$ g; c) q- [5 |: T3 g$ k
    def calcCosDist(user1,user2):
    ; B9 m' I0 n1 B    sum_x=0.0* W5 o) b. Q- \
        sum_y=0.0' R5 X) i7 W, l6 }
        sum_xy=0.0
    # k9 ?4 R+ X/ j* X: B    for key1 in user1:
    / d& [; Y9 V8 V$ P) {  ]! f7 y        for key2 in user2:7 @) _7 R8 J2 W1 X# ]. P
                if key1[0]==key2[0] :4 M& o# R) A( v# S5 T7 W) t
                    sum_xy+=key1[1]*key2[1]
    + J: n4 c- H- v  t) b" G# s                sum_y+=key2[1]*key2[1]
    9 X) ?! e( Q, H9 ^                sum_x+=key1[1]*key1[1]. I' W- n( i  R* i- ]! L
       
    3 D# `, P% b) j) S. }    if sum_xy == 0.0 :7 z1 U1 ^; b0 o/ @: Q* V( G6 a/ d
            return 0
    / T/ Q2 a$ W& h5 `3 |# C1 Z& X    sx_sy=math.sqrt(sum_x*sum_y) 0 r# H& N! d/ Z; k* u2 R3 Z! `
        return sum_xy/sx_sy" q4 a( n/ ]3 X% f9 M2 c$ d' z2 s, t- r
    # Z! `- @, c5 |# |" w4 V
    : [4 C8 y7 O* i/ |" v1 J
    #
    , X& J1 f+ h. K5 B#
    0 k- M. t$ u; b$ Q# p, o#   相似余弦距离
    0 j4 K  V5 g# [5 C; \8 y$ [2 C#1 Z8 ~5 ~) i" y# {& ^
    #1 }7 e8 C" K! b  \
    #" E: L; U6 P; j
    def calcSimlaryCosDist(user1,user2):
    * ~( H4 }, k  o) D# K    sum_x=0.0
    , V1 s  z/ c) E2 j, b    sum_y=0.0$ U3 s1 b- ~1 Y1 V3 o. x
        sum_xy=0.0
    * ]# o7 {4 ]  N" _4 ^" j; _    avg_x=0.02 A6 C7 Y- Q$ b5 B6 _! C$ M
        avg_y=0.0) W, M- K8 S( N1 Q" }; O
        for key in user1:5 p7 p0 c- k+ Y/ w" M
            avg_x+=key[1]
    % v+ m" V) U2 c, u$ v4 V5 A+ w    avg_x=avg_x/len(user1)
    / L- q, U& f7 k5 V* e    + ?. m1 }6 C+ n+ {3 a5 g7 d* Z
        for key in user2:  w1 q+ X# c, C2 d' w5 o0 R
            avg_y+=key[1]/ o8 q/ B# }8 \+ V0 Z3 p
        avg_y=avg_y/len(user2)
    ! E& W) E8 t. g0 z0 |7 z    ! @. O% ^; l+ }6 t
        for key1 in user1:
    : U, E8 D8 W5 e+ `) D* D! A% u        for key2 in user2:
    # y: z  M' d( g6 O            if key1[0]==key2[0] :
    % t- Y0 H6 e6 v' ^+ w. E                sum_xy+=(key1[1]-avg_x)*(key2[1]-avg_y)
    6 A! F% t% W/ A                sum_y+=(key2[1]-avg_y)*(key2[1]-avg_y)
    * q( a) y$ t- S        sum_x+=(key1[1]-avg_x)*(key1[1]-avg_x)
    / c$ |. u% m0 }, v   
    ! ~& q0 J/ S0 v+ `# A" h    if sum_xy == 0.0 :
    - M; J2 P  S& I; h) ]        return 0( |" m5 P1 C* X
        sx_sy=math.sqrt(sum_x*sum_y)
    ' x- E* }; f* i5 k9 W7 \    return sum_xy/sx_sy
    3 \! w$ y$ \  e( g+ g, o3 W4 S   
    1 F" ?% R! H+ O* k) h- Q
      E0 y' ?5 {0 j0 G$ ~& x+ ^+ c#
    ' O# `2 t1 d! ^#   读取文件
    ! s9 S8 L% m( A# T% g#
    % z% d/ C! Q9 T! N' _! K. z, q* W## U2 x( S: }1 d: W- \, a! g3 B  G
    def readFile(file_name):+ f. W" }$ G( _: M$ w
        contents_lines=[]' o4 r" u% f4 B" T" \  k
        f=open(file_name,"r")
    3 @' w- I2 B; X& E' V* k9 B6 |, \    contents_lines=f.readlines()4 ~6 N0 }7 m2 B& e
        f.close()
    * I# D: w7 c8 V    return contents_lines
    9 F* o! c- t: [
    * }7 C# J# p3 f: T0 ~; o- B. z5 W8 J. l2 }7 R# \

    . M7 _/ X# s: N+ o3 z+ @5 [#
    ) `2 R) C2 B5 ^# ^& c#   解压rating信息,格式:用户id\t硬盘id\t用户rating\t时间
    6 I+ ]2 I* _3 o$ T3 Y! f) L#   输入:数据集合" O8 K9 [; Y' }. S. `7 a0 `; f
    #   输出:已经解压的排名信息
    % t% X/ a$ L) |#
    " k! G" j0 v9 |& b) ~( ]def getRatingInformation(ratings):9 k. p, a% R7 r( Z" |  _5 o
        rates=[]
    + k! X! a: w6 \' q/ G4 ^: a: b2 }# _    for line in ratings:
    4 _( W$ s# K4 o$ k" d' J1 l        rate=line.split("\t")
      x! I5 h1 [, T; j% u9 m% {        rates.append([int(rate[0]),int(rate[1]),int(rate[2])])4 v1 @8 Q6 v9 L+ x1 S/ ^5 r
        return rates/ P' a# m2 z0 Y( [# @9 }+ v8 a4 x( K; c
    ( S. v" u- J+ r6 v6 B( I

    1 b+ e9 w5 o/ N/ |#" d( Y, e0 i( q
    #   生成用户评分的数据结构9 v! j9 d6 j/ j: |* b" B
    #   ( |) L! m8 X, X7 t, l% Z
    #   输入:所以数据 [[2,1,5],[2,4,2]...]
    & J2 I2 q+ q3 I" d$ [; @# V" F: W#   输出:1.用户打分字典 2.电影字典
    * S9 I9 I3 v/ v#   使用字典,key是用户id,value是用户对电影的评价,
    ( I2 X! d5 x+ M& Z#   rate_dic[2]=[(1,5),(4,2)].... 表示用户2对电影1的评分是5,对电影4的评分是2
    ! z! i* U/ e+ O! p. I* z2 A7 C; O#! k. S  l5 W% J1 @
    def createUserRankDic(rates):
    : g1 w5 O3 d4 X    user_rate_dic={}
    9 o9 c  {7 u; e! t: D    item_to_user={}
    # y# E9 P1 ?! x  j1 q    for i in rates:
    9 M9 y/ S- M# \6 y        user_rank=(i[1],i[2])5 Q5 U, b* `; b6 `
            if i[0] in user_rate_dic:  n" U( _4 t% m. N8 y; G
                user_rate_dic[i[0]].append(user_rank), R$ E% V( o$ P" q% L( f" k4 B6 `
            else:. t) v* t( y+ d
                user_rate_dic[i[0]]=[user_rank]
    , q% J# I  X3 X% K8 ^            
    2 |' O1 I" k! Z# D, y7 F* l        if i[1] in item_to_user:
    ! v( T' L" S, k3 `! N  i3 B            item_to_user[i[1]].append(i[0])
    & E! F; m* s! X/ \        else:" g1 \9 @: C9 y! x( J; f: w: m4 }- P
                item_to_user[i[1]]=[i[0]]
    6 n# }( H% I; ?- `$ m1 Y) z            
    4 t3 j+ F' s' p9 ?( G. Y2 d9 k    return user_rate_dic,item_to_user
    8 a" J8 @' I& ]
      W5 j# i5 S& @7 H' \, ~+ q* q( e2 e  z7 e
    #
    ) p$ t: X5 i: E8 t#   计算与指定用户最相近的邻居7 R. `) V% p  j- U
    #   输入:指定用户ID,所以用户数据,所以物品数据9 v' b. F+ J8 b; Z/ A4 X
    #   输出:与指定用户最相邻的邻居列表: ]3 c  H. h) [& m) H
    #, G. T1 j: ?4 x0 r8 M, H& Y6 L8 Y
    def calcNearestNeighbor(userid,users_dic,item_dic):- `; R4 U5 I) l$ _3 Y9 e0 u
        neighbors=[]" `  u- ^( Q* N/ Y6 V, j4 w9 `
        #neighbors.append(userid)
    # Z; A2 G6 x$ O9 i. J    for item in users_dic[userid]:9 L1 @, G* ]4 e! i& x/ k
            for neighbor in item_dic[item[0]]:* t' M2 e* b  I/ A0 D/ h% l) U3 M2 J
                if neighbor != userid and neighbor not in neighbors: + s3 K, i/ r& W( Q; Z
                    neighbors.append(neighbor)
    ; r0 B: \% L# F, V      , s5 j( r5 Y7 t' y+ g
        neighbors_dist=[]# y& c/ j  S  f
        for neighbor in neighbors:* Z% m/ L1 b8 A1 K# G6 \; I
            dist=calcSimlaryCosDist(users_dic[userid],users_dic[neighbor])  #calcSimlaryCosDist  calcCosDist calcCosDistSpe, g6 x- ~! [: s, p% \  H  @
            neighbors_dist.append([dist,neighbor])
      q, w2 j, h5 p; c) a    neighbors_dist.sort(reverse=True). a- M( x# _" K: b
        #print neighbors_dist
    # J9 x: S0 L: t0 ]9 g    return  neighbors_dist
    ! |/ H) A- ?5 Q  L( `+ M2 S$ y- M% }  X+ T# j$ |

    3 V8 X/ W( r  A2 x9 F. S0 D#. `0 o7 c$ t) _( a3 w8 |& q7 A* C
    #   使用UserFC进行推荐
    ; `6 A9 n! k- [; X3 S& {0 b6 y; [7 v#   输入:文件名,用户ID,邻居数量
    9 Z& D8 m5 i4 I) X6 |#   输出:推荐的电影ID,输入用户的电影列表,电影对应用户的反序表,邻居列表
    5 j& R1 E& W0 L#% K6 s: z' A3 G) U) Q
    def recommendByUserFC(file_name,userid,k=5):+ U/ c3 C/ j+ P! [9 b, f
       
    7 j* P9 R! l8 m# g3 k- X    #读取文件数据
    & k4 ~5 k3 P3 h" C8 l7 A; |    test_contents=readFile(file_name)
    2 N: H$ P4 Q; G. |. j" G* c    1 T( E) Q: Q/ K$ c! T2 k& S
        #文件数据格式化成二维数组 List[[用户id,电影id,电影评分]...]
    & g; i5 O% g& K1 j0 w9 H    test_rates=getRatingInformation(test_contents)& D$ B7 Z9 p, A( z8 Q" s( E' `5 @! u
       
      x( T( j6 ?. v2 g    #格式化成字典数据 ' `+ l! l1 X, ]( m0 R
        #    1.用户字典:dic[用户id]=[(电影id,电影评分)...]' H" C8 Q- g% q' D5 S. S8 B
        #    2.电影字典:dic[电影id]=[用户id1,用户id2...]
    2 ^- {( u: ^1 I- [9 l9 J    test_dic,test_item_to_user=createUserRankDic(test_rates)+ @& z( w0 F5 f
        6 q$ S' P% Z0 x
        #寻找邻居
    3 q& @% q7 F1 r  B5 z    neighbors=calcNearestNeighbor(userid,test_dic,test_item_to_user)[:k]
    : a0 B2 f$ D  l/ X% C0 O        
    . f/ U8 f* k0 Q* b6 V    recommend_dic={}
    9 |, [2 G* L( u    for neighbor in neighbors:5 b0 p8 }7 l6 ?8 L9 R+ V
            neighbor_user_id=neighbor[1]5 w1 R/ z8 _8 }. C5 a( P
            movies=test_dic[neighbor_user_id]
    . Y  [1 q! ?5 i% {$ e8 c; d        for movie in movies:
    ; y8 m8 \1 E3 q( z# C9 F            #print movie3 h! @$ t& I+ D" `! s- i7 G
                if movie[0] not in recommend_dic:
    7 K9 C* k  N; }7 W1 P( b8 A( b+ e                recommend_dic[movie[0]]=neighbor[0]
    % Z8 |* t! f, O7 V( o& N& e            else:/ L" Z  R% b( f* ~
                    recommend_dic[movie[0]]+=neighbor[0]; c2 C$ M% g1 K3 y$ A* U
        #print len(recommend_dic), o; I1 N% T; Y9 Z
        3 }7 E$ x+ [* m1 ^5 _
        #建立推荐列表
    4 M) z6 w, K, Y9 s, N+ G, U7 {( |7 ~' ?* g    recommend_list=[]
    ) ?' u) P6 o9 ]    for key in recommend_dic:0 i9 }& @) ~  r8 @4 c
            #print key
    ( P4 z+ d8 s/ P$ Z  Y% x        recommend_list.append([recommend_dic[key],key])+ A: l$ c5 [+ f: L6 h* @
        ) F2 F+ i* [0 x' a
        4 C! j- K; f9 k' ^( O; Q
        recommend_list.sort(reverse=True)
    0 C0 F* y" O; ^+ ]1 f# U( A( U1 v    #print recommend_list
    ( m+ O3 k* t$ `    user_movies = [ i[0] for i in test_dic[userid]]) O: Q, }& ]: d- ^( Q
    ' \# [5 L) @; X7 Z
        return [i[1] for i in recommend_list],user_movies,test_item_to_user,neighbors  H8 u9 ~- }0 V  u8 `
       
    ( Y' B! U# X. g$ @6 {. i    - I  H3 V, k( y' L$ G9 ~' Z

    % ?, d! N3 S$ I6 \) N6 M* f#, _2 H- n/ r9 Z6 Q/ Q
    #7 g' w, K. O% t& G( r
    #   获取电影的列表$ P2 v& ?  N% }; X& F$ q- h& }$ U
    #
    2 L- @2 u+ s! j. ~#
    , n5 R0 e* m8 M$ s#
    5 v& n! I% |' I8 xdef getMoviesList(file_name):: j  _- S. O7 X3 B* F& B4 o
        #print sys.getdefaultencoding(). s+ j% Y3 y" W; Y( f" L: y
        movies_contents=readFile(file_name)
    1 G! S! ]* [, r8 X8 W    movies_info={}* d+ ]8 M( d+ |' P
        for movie in movies_contents:
    ' L: E. r) {. O, ?        movie_info=movie.split("|")) w# C5 Z, L9 A( s
            movies_info[int(movie_info[0])]=movie_info[1:]3 Y5 p+ v1 }% T! U. V+ W
        return movies_info
    7 H, j' F. o0 g! p2 t    ) t! J/ J9 a$ g: k7 |
        7 [4 A& S) w2 o* m
        : L8 u: y0 }% L. U
    #主程序
    $ c9 G1 A$ q# u6 i8 K3 B#输入 : 测试数据集合
    $ F$ D6 N6 [* J% Eif __name__ == '__main__':
    1 |$ t' v( E. w0 @    reload(sys)9 j- o9 X: B* r7 k
        sys.setdefaultencoding('utf-8')
    + x5 L& U6 J- _% V- s# Y: |+ }+ f    movies=getMoviesList("/Users/wuyinghao/Downloads/ml-100k/u.item")3 R4 J$ Y" ]) `  n
        recommend_list,user_movie,items_movie,neighbors=recommendByUserFC("/Users/wuyinghao/Downloads/ml-100k/u.data",179,80)7 }5 n& w1 `2 [$ Q0 U4 C
        neighbors_id=[ i[1] for i in neighbors]
    6 u) e6 f8 A. W( g. W8 z, b2 a" m+ a    table = Texttable()$ V# v0 h! _2 @* y
        table.set_deco(Texttable.HEADER)
    / J, F% {5 b  x% W# t- f3 r    table.set_cols_dtype(['t',  # text - |  V7 q$ d9 y( W. R; u9 E
                              't',  # float (decimal)/ ]9 G. J7 P9 |  S( J. S% E/ d
                              't']) # automatic
    $ p1 Y$ T0 U  k- c  x    table.set_cols_align(["l", "l", "l"])
    * O- P: f2 e9 q    rows=[]' o, T4 Z4 V' k( s/ {2 m
        rows.append([u"movie name",u"release", u"from userid"])
    $ N  [% m, O2 \7 \* i  o    for movie_id in recommend_list[:20]:
    - t# G4 M) k1 w- R9 J        from_user=[]
    1 |' N5 }, c1 G        for user_id in items_movie[movie_id]:
      Q5 n/ o1 D0 S& p4 F( |+ R( h* W/ J            if user_id in neighbors_id:7 n7 h4 Z& ^  i$ `' x& ~
                    from_user.append(user_id)
      E+ q/ ~: A1 O! z        rows.append([movies[movie_id][0],movies[movie_id][1],""])8 O1 s; Y0 j: P1 _
        table.add_rows(rows)& d! u4 _3 v9 S0 w$ A$ `: l
        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 ! f2 j, y5 D/ i* x1 F/ [5 O* M
    # -*- coding=utf-8 -*-& i/ }) M3 [' E8 h
    % ~% G3 \* O' m" C9 }
    import math
    1 g8 E# P2 p" W5 N7 E" A9 r
    这是什么语言的程序?
    # N( s; B5 Y# D. n' G/ h! ]# A
    回复

    使用道具 举报

    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-10-26 18:39 , Processed in 0.566565 second(s), 67 queries .

    回顶部