QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 5279|回复: 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
    本人在学校参加暑假培训,需要这个算法做题!求大神赐教,感激不尽
    4 r+ [* v) J: z/ }& `# [; \1 e
    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 -*-/ i: R2 ~+ W  C7 H
    4 N# @3 @$ Q+ m4 Z$ U6 i- ^/ {+ m
    import math+ j1 \3 B; ?: ]" I8 N$ _; \' v% g
    import sys. D  `! P7 e0 E0 ?# E' y* j
    from texttable import Texttable8 v; b2 }' v8 K! Y! j4 s

    ! A. I1 V1 R! M$ ~. Q& g* q: Z; a- y  }' H
    #
    ! r: _3 ~+ |8 F7 e+ V$ y* Y#   使用 |A&B|/sqrt(|A || B |)计算余弦距离8 ~! ~* U2 F# Y# B: D2 y
    #; P) e( Y& ]! ~. F8 w0 h6 x3 [- t: V
    #  Q0 E# c, i" k2 Q' v1 E
    #
    4 h7 c7 t% P% @) Z$ s3 S- ^def calcCosDistSpe(user1,user2):/ m1 n1 H6 \/ C$ e7 K
        avg_x=0.0: B$ d3 d$ I2 e* t7 J
        avg_y=0.0. z# F) z" l; q  G
        for key in user1:* y$ U7 S" x1 P4 `2 m
            avg_x+=key[1]
    9 x6 V' k8 @0 i9 C. X! t    avg_x=avg_x/len(user1)
    - C+ A5 d9 U( ?1 P: z" e, |    5 h+ y9 J3 w" Z% y% m
        for key in user2:+ m) ]8 g& p8 _6 r  ^
            avg_y+=key[1]
    7 k2 c3 c% O8 _7 n& D    avg_y=avg_y/len(user2)
    / c. A' b$ }. x% s/ D6 h# L& ?0 C   
    : F  U6 k4 Z+ V7 n( P    u1_u2=0.02 I5 |" C* B" B3 u
        for key1 in user1:
      G+ R- h0 N3 v7 k  G, o+ Y        for key2 in user2:
    # e2 [2 g5 M6 y& W# d$ B  W2 B2 Y            if key1[1] > avg_x and key2[1]>avg_y and key1[0]==key2[0]:9 I# ^8 t. v2 U
                    u1_u2+=1
    , n$ ]- J+ [8 J  s3 x. o    u1u2=len(user1)*len(user2)*1.0* a+ S; i7 c: U3 K* A" h
        sx_sy=u1_u2/math.sqrt(u1u2); i8 X0 l" |- g. R( o" e
        return sx_sy$ g* S$ |+ m, _9 z; @

    ( b! U+ t: R6 ^6 W. Z, h$ j; T* u+ T! U4 n$ q/ S$ o
    #; I: o6 Q% r( ]2 c
    #   计算余弦距离% _, \+ l$ E) L% A! ^3 g8 ?/ p
    #
    " o# B0 G" h& {4 [  ^: b#2 o! `; {1 k. {; J% i( P& |
    def calcCosDist(user1,user2):4 o' n, i+ s1 V
        sum_x=0.0  p# f  J4 Q0 z4 |- I! s
        sum_y=0.0
    * k9 G0 a4 t0 I2 j    sum_xy=0.0+ \0 ]4 D+ o6 e( N
        for key1 in user1:, H1 ~# e# e) D; `7 w% U- w4 C4 R! I
            for key2 in user2:
    & a, G- s7 n5 p& e            if key1[0]==key2[0] :* t; Z, E  h" y: a
                    sum_xy+=key1[1]*key2[1]
    9 K; ]* S% v+ r& @. w" [                sum_y+=key2[1]*key2[1]
    : n( |% U0 k' m9 a; l3 Z8 C                sum_x+=key1[1]*key1[1]
    3 i3 i9 c0 u; H    ' K4 D2 ?4 p7 p9 u5 y
        if sum_xy == 0.0 :5 n- K0 Z2 M; y# \) S' F
            return 03 Q* X3 D: f( }2 e1 l/ L
        sx_sy=math.sqrt(sum_x*sum_y) # P8 ?" v; n" v: v+ M; j
        return sum_xy/sx_sy
    + n6 _4 P9 D! Y; e- m, |  a5 S# _6 K( i8 j% N9 m
    ; d2 ^% P- z) z1 E4 i
    #
    ( V0 _3 U" X* j2 L#
    1 |! {  g* A  l  s1 d#   相似余弦距离3 K* c3 d- X0 k3 B! q7 o
    #% H3 y1 |; K" k4 F' m6 R) e
    #' n8 \+ s# M' @3 L- e$ H3 f% {
    #
    : P; V, H( k) `# Udef calcSimlaryCosDist(user1,user2):
    & G  ^  u5 m0 I9 l6 _4 e    sum_x=0.0
    # H& [" l( V( l8 J5 ^  i8 u    sum_y=0.0
    7 W" d9 |' {2 g  S; X5 \: ~  B6 V# {    sum_xy=0.0
    2 }# c% ]7 N3 N8 {2 j8 y" u    avg_x=0.0
    , i* k( G2 Z7 `    avg_y=0.0! k. G* P2 h  ?8 s' `
        for key in user1:
    8 y0 P) g" [/ i* m$ E        avg_x+=key[1]: T& X: i! ]9 x/ O
        avg_x=avg_x/len(user1)6 O5 h$ {/ {; t- D/ a8 a, T
        * U- ?5 s, D8 x( ?
        for key in user2:
    1 j( ?: _, h5 D: ~5 k+ W/ s& |        avg_y+=key[1]
    9 @8 Z8 c$ _; `, q1 x9 }    avg_y=avg_y/len(user2)
    ( C+ M5 E% X. d' j- v* y   
    ( k" S: G  R" k0 {+ z8 j5 a    for key1 in user1:3 I0 \% X* t: N
            for key2 in user2:
    ' W$ T3 K6 a0 `8 p" r0 t1 m            if key1[0]==key2[0] :
    - m% K/ o1 H) s9 M1 x/ C5 g5 Z* ~                sum_xy+=(key1[1]-avg_x)*(key2[1]-avg_y)
    " k$ H% {" \1 |' P% \/ v                sum_y+=(key2[1]-avg_y)*(key2[1]-avg_y)
    ( v2 x" [/ O: k; ~+ A9 c        sum_x+=(key1[1]-avg_x)*(key1[1]-avg_x)
    3 e# j6 n- K, A( C9 q    ; T9 A$ w6 Q6 ~! [1 B3 M% S
        if sum_xy == 0.0 :
    # `( I; V7 u4 |+ g* f6 R- e* L5 K        return 0
    9 n3 ~8 E5 n  s! L* D    sx_sy=math.sqrt(sum_x*sum_y) & ~+ R% ^! W4 f% L/ b6 W
        return sum_xy/sx_sy
    ) B; y8 ]$ e: K    ' [9 h5 i, n+ U6 @2 _" y$ \3 l  r( s
    & \( O' N( J3 O4 ~8 q9 M
    ## F# L# p+ \0 [& G
    #   读取文件$ p! d& t" a/ H: o' O4 s% v, {
    #4 s/ \. q) \! ?
    #
    ( D0 F. ]( l9 ?" Z  F) rdef readFile(file_name):4 M' T" y0 V" x# _4 c
        contents_lines=[]' u. I0 a) c% d( i* a8 n
        f=open(file_name,"r")
    0 v* K, X) j, ]1 l: Z( D/ E    contents_lines=f.readlines()
    " \7 H/ X- p% a# ?6 o, K    f.close()" k) W* F! C4 p7 k
        return contents_lines
    / V: j4 ~  l8 X4 O
    ' x  K7 c' O3 o1 |- L. h
    . u& X8 |, l+ _) t  q2 E2 k. |$ r) V5 h5 p# R
    #4 g8 q6 M: P( H, m( ?* j& v4 D
    #   解压rating信息,格式:用户id\t硬盘id\t用户rating\t时间: T+ P: s& t4 A! I. K
    #   输入:数据集合$ I! r* ]8 C7 z7 w4 ]( s" a
    #   输出:已经解压的排名信息
    ( P4 ?+ D/ k1 V/ N" J9 ~#
    # @  j8 r' D+ g- Sdef getRatingInformation(ratings):) K- |7 J* S, c0 q9 o8 _" g
        rates=[]
    5 T) {3 [7 U8 _) m8 H    for line in ratings:4 N, ]8 S' G! b: i
            rate=line.split("\t")
    ) Z9 ^2 b/ R; _$ c        rates.append([int(rate[0]),int(rate[1]),int(rate[2])])' c. i8 ^* o  W' z! C1 m
        return rates
    6 l2 k, F. m& C! M
    # X5 J) }! j3 H8 }# y9 [8 J5 X/ F0 r. G' C, A( {% z" ]
    #
    4 \9 I/ p# U5 V" ?& h#   生成用户评分的数据结构
    7 |+ N6 T* Y3 Q0 S#   
      \# r0 A+ ]# {5 M- h5 s' K#   输入:所以数据 [[2,1,5],[2,4,2]...]
    " p5 V1 s3 Z& @# z* C#   输出:1.用户打分字典 2.电影字典# ?6 m. h3 g/ d' w- o
    #   使用字典,key是用户id,value是用户对电影的评价,
    4 v* g5 y/ g& b, b. D( _- ~: ~#   rate_dic[2]=[(1,5),(4,2)].... 表示用户2对电影1的评分是5,对电影4的评分是2
    3 t% d* n1 p) G0 Q- X! L& S#
    1 t/ R$ T( d8 E4 _- }' sdef createUserRankDic(rates):$ V: w) E1 u0 C3 k' u
        user_rate_dic={}
    ; s/ m3 A2 c) f7 Y  d% r    item_to_user={}
    / i" R7 L, q7 Y8 M+ f    for i in rates:
    0 d8 n% }; m2 N. X; e0 G        user_rank=(i[1],i[2])
    2 P; L' z5 C1 d" \        if i[0] in user_rate_dic:
    ! X; r1 O8 P& r' t' z- W0 v- Z            user_rate_dic[i[0]].append(user_rank)7 t8 J; m+ T$ S' s
            else:
    # M. M* Y' n% [, ]" R" t* p            user_rate_dic[i[0]]=[user_rank]
    1 `" M: d4 W  Y$ [            ' F$ _6 J3 M) R2 m
            if i[1] in item_to_user:- ^" Y: ?7 k  @1 g
                item_to_user[i[1]].append(i[0])
    7 V0 [0 e4 v, D& o/ G        else:; z6 {5 V; H) O3 R9 g
                item_to_user[i[1]]=[i[0]]
    9 W/ Y  ?1 R1 j% P1 D, x/ {5 B            
    7 }2 e" V. {  J2 p) q+ R    return user_rate_dic,item_to_user1 O/ O+ S) N( ]2 F- T9 _

    9 B- W6 l9 L4 L# ?, ]& |) t/ s4 b1 D0 D8 x( I
    #% l) J. @0 Y6 Z6 k0 l/ P$ X
    #   计算与指定用户最相近的邻居
    ' N0 q) y# }# g* B$ t#   输入:指定用户ID,所以用户数据,所以物品数据
    ' u" `8 o1 U1 J8 U8 L#   输出:与指定用户最相邻的邻居列表
    # N( ]1 c' n3 j) \4 w. l, e#. D. H' f1 L: I$ c
    def calcNearestNeighbor(userid,users_dic,item_dic):* U! D# B0 [6 ^+ [" p
        neighbors=[]7 u$ W5 X9 U- j# B- k4 Z/ K4 F) I7 l
        #neighbors.append(userid)# d5 V( \" G# q! H  E( c# d
        for item in users_dic[userid]:+ S7 V$ \& D2 v" c
            for neighbor in item_dic[item[0]]:
    + H0 d& a. g* E& m& f: z8 d! F            if neighbor != userid and neighbor not in neighbors: ' i+ X" W+ J2 j7 c
                    neighbors.append(neighbor)
    $ Z, p4 d6 s% A6 t' t      * w% D3 \$ _/ S+ _
        neighbors_dist=[]
    ' q1 h# g6 D+ \( H$ K3 C    for neighbor in neighbors:" s1 Z  K9 W! g  p  S; Q
            dist=calcSimlaryCosDist(users_dic[userid],users_dic[neighbor])  #calcSimlaryCosDist  calcCosDist calcCosDistSpe
      U' \" Z. \4 ~' e, o: N3 b  t        neighbors_dist.append([dist,neighbor])+ q2 ], M( |& T: h( U/ t* v3 e
        neighbors_dist.sort(reverse=True)# e5 O/ E% L, z2 N
        #print neighbors_dist
    3 x$ f- B' Y5 a# k: B% s$ e& C; H    return  neighbors_dist; |, B* l5 `3 A, z9 u( M/ ^& L

    ! K8 |" v/ ?% m1 x3 u/ p  X. s7 O% w% U# H
    #
    $ _5 ?! J" x' m#   使用UserFC进行推荐/ x  y2 |! Y/ ~& k% L; [
    #   输入:文件名,用户ID,邻居数量
    / f) B- D* T% m' a! Z( K#   输出:推荐的电影ID,输入用户的电影列表,电影对应用户的反序表,邻居列表- \. M' B, x; w4 z6 c
    #
    1 c' ]  i3 c. c" d6 W" @def recommendByUserFC(file_name,userid,k=5):
    % U5 C  \3 ~* v2 p+ |- [   
    2 g- w$ S/ T, q    #读取文件数据
    0 N, g8 ~" k3 S1 _6 x* l* D. c9 V    test_contents=readFile(file_name)
    4 z1 P  i) ~6 a% u; ~6 @! C    / C  F9 I7 h; w- A2 S
        #文件数据格式化成二维数组 List[[用户id,电影id,电影评分]...] % v( Y8 F- L2 v2 p+ t
        test_rates=getRatingInformation(test_contents)
    ( A& c0 t0 l; u   
    ; c, t1 `4 w8 N+ D5 O3 i    #格式化成字典数据
    9 g9 k& a& ]2 y4 Q    #    1.用户字典:dic[用户id]=[(电影id,电影评分)...]
    # C7 h: J. t2 ?  Y* l. d    #    2.电影字典:dic[电影id]=[用户id1,用户id2...]( [+ n0 G8 c. v& m3 f
        test_dic,test_item_to_user=createUserRankDic(test_rates)
    5 Z5 L) F3 }& O3 O/ Z( a3 p1 W! C+ V    . ]1 R7 N. z: ~- E
        #寻找邻居
    ) H4 \8 D/ ?" D& _    neighbors=calcNearestNeighbor(userid,test_dic,test_item_to_user)[:k]
    + x) X; `/ v% K0 B/ j- x        5 P9 I8 o- h- m2 V, [
        recommend_dic={}4 G- B0 o1 V" |5 Y; R' @( K; l' p
        for neighbor in neighbors:! S7 j3 X" |/ Y/ z
            neighbor_user_id=neighbor[1]
      I1 x1 ~& ]5 J- s: b/ Y% A        movies=test_dic[neighbor_user_id]
    2 f9 C& m+ S( Q# N  u        for movie in movies:* x/ C6 Z% H6 F+ o( N! |: u
                #print movie! Y$ A* |6 C9 x( `$ {
                if movie[0] not in recommend_dic:
    & F6 D/ _0 q5 l: G4 N/ h                recommend_dic[movie[0]]=neighbor[0]4 y- Y; ?9 A: A4 }
                else:  J, y7 z0 _4 Q3 |! I" u! ?
                    recommend_dic[movie[0]]+=neighbor[0]5 q3 |+ w* a8 j6 v
        #print len(recommend_dic)0 q, \) G& u$ \$ V. i3 N
       
    % a" U3 x; P" L# {    #建立推荐列表
    ; r7 j/ ]+ Z# E+ r, F0 Y& a. Z0 g6 B    recommend_list=[]4 O, y9 B9 C6 ^* c7 p
        for key in recommend_dic:
    8 x, d/ T1 {$ x2 B) U2 V$ k* `        #print key
    4 q  P0 z( H/ z1 h: q! s  ?0 E        recommend_list.append([recommend_dic[key],key])
      n5 q" O4 S* J8 k' u& f( w    . V& y0 n- Z& r% E& x2 @1 t
        9 L! T; H  R5 {' V
        recommend_list.sort(reverse=True)0 \0 W9 C3 L/ Y; d
        #print recommend_list
    $ s) ?3 L& _6 R: z/ i: x    user_movies = [ i[0] for i in test_dic[userid]]
    9 J) Q* R/ I( S! `* A5 D, K9 }% e6 K
    ' s( F$ n% _" F2 Q    return [i[1] for i in recommend_list],user_movies,test_item_to_user,neighbors
    % p: Z% h+ S4 R. ]( z   
    9 _+ D* ]2 X7 }   
    4 B; u0 y! V0 q' K( T# x. C7 n
    #
    ; h8 ~5 T: f: H8 A) b. l#, v; l# i& F* V) N
    #   获取电影的列表2 k7 F% }2 p6 {. f* I! I
    #4 S3 x* p4 T+ H* ~" @- j
    #2 S$ n5 D0 U; t
    #
    1 i/ m6 M/ ~6 Y6 O: k2 ldef getMoviesList(file_name):
    0 d- ?3 I( V8 D3 k    #print sys.getdefaultencoding()7 \* J6 O7 c, ^' X% V+ d
        movies_contents=readFile(file_name)
    : P' d. S. H" Z. B    movies_info={}* p. `) `% [6 w- F5 {  F! Y, o6 M) s
        for movie in movies_contents:
    " |, a; i( o( I( G3 P        movie_info=movie.split("|")
    & M' h6 C& t8 G/ j* p: o        movies_info[int(movie_info[0])]=movie_info[1:]
    ! ?, R+ {+ Y" u, B. V& X4 w) |0 u: e    return movies_info, h% W- K, U3 |" \' s# y8 s
       
    # z4 f' B: w7 O    4 x8 E/ h  Y/ v# ?' s2 O
       
    8 ]8 v. C& w  V. Y) v#主程序, \% N8 }3 D7 `) p( X0 m9 R
    #输入 : 测试数据集合2 K; U. f: d& y3 S% c' P- B5 K- \
    if __name__ == '__main__':, u. W1 k" f2 e% B* I
        reload(sys)
    1 G& J+ @- `! W# h1 e! ]0 ?3 i    sys.setdefaultencoding('utf-8')
    . }; `) ]+ d3 `% L- [# g# V    movies=getMoviesList("/Users/wuyinghao/Downloads/ml-100k/u.item"). h& [% [; U8 w7 c! F; u
        recommend_list,user_movie,items_movie,neighbors=recommendByUserFC("/Users/wuyinghao/Downloads/ml-100k/u.data",179,80)9 C% m9 n8 H* v
        neighbors_id=[ i[1] for i in neighbors]
      I0 `1 d1 w1 l2 z    table = Texttable()
    7 R( c6 F2 T5 t4 i8 N9 a7 M) @    table.set_deco(Texttable.HEADER). \8 a! m1 y1 a4 _9 V" @
        table.set_cols_dtype(['t',  # text
    - a- x4 q7 F# [; Y# w                          't',  # float (decimal)
    9 m: u; `. ?2 h                          't']) # automatic
    7 G2 g& L5 Z% u  R. ^5 W    table.set_cols_align(["l", "l", "l"])# x. ?! ]% p* u$ d- G9 P
        rows=[]6 L! E' G3 j8 q6 I+ \
        rows.append([u"movie name",u"release", u"from userid"])! T* G+ d  `" p! {! s1 a. U
        for movie_id in recommend_list[:20]:
    6 A3 E8 Q: A2 B) J- L, _        from_user=[]" l6 k) B4 l& Z" r5 z* X- s1 d6 C$ L
            for user_id in items_movie[movie_id]:
    . S5 R2 G! ?) V8 p/ E$ [7 R            if user_id in neighbors_id:/ w4 q/ u( V6 p" C) Z$ [) D
                    from_user.append(user_id)8 v* G% `$ n5 ?
            rows.append([movies[movie_id][0],movies[movie_id][1],""]); X: `! x4 V' K( W7 Y
        table.add_rows(rows)
    : J6 h. A% ?0 n8 k( o/ x    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
    & A' X1 f5 ^) t9 C+ p8 z  _' X$ X, x# -*- coding=utf-8 -*-% v4 J( {+ N! ^9 ^

    8 `1 e% R0 b* b7 @( Eimport math
    ( {4 H/ t* O. f4 V$ p3 c1 s! p
    这是什么语言的程序?! G+ s/ m! b* K% c3 N2 E
    回复

    使用道具 举报

    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-5-19 02:31 , Processed in 0.416490 second(s), 68 queries .

    回顶部