QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 5390|回复: 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
    本人在学校参加暑假培训,需要这个算法做题!求大神赐教,感激不尽
    . g5 f5 g, M% S: k; i2 ~% k! _
    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 -*-0 k" P$ }, M" ~8 |8 a4 n
    ; s' j) i  o; C0 I
    import math( p! R6 O/ J6 e- J
    import sys
    . ]+ I2 ~: x' Ffrom texttable import Texttable
    , s3 d6 W) p" C+ x$ f: V" X' W1 g4 e# j8 \/ _+ Q7 s" k
    " |' \* \" {3 k4 ^* S# S! f
    #
    2 K+ `0 {/ [2 p: d' u8 w3 n#   使用 |A&B|/sqrt(|A || B |)计算余弦距离& g" H3 b# j/ r5 V' P6 F
    #( e' a9 l* M8 P2 x9 _$ `# X
    #" T3 x4 O' ?* m; K
    #. Y0 O1 F( V$ d5 L' j. k
    def calcCosDistSpe(user1,user2):0 @/ W4 ~# B& R1 ?
        avg_x=0.0
    & \- ~! B: c3 \) e+ l9 k    avg_y=0.0
    7 t/ H9 ^7 j* K4 k$ A. w. H4 @    for key in user1:
    9 N8 S) x; T( S. j4 m/ X! r        avg_x+=key[1]
      R4 X  |' q( [, }+ q    avg_x=avg_x/len(user1)1 B1 u+ e! ^! x2 d' y4 _) n, f
        - d7 X/ v, u9 N( D
        for key in user2:
    ; X: m+ I) Z; T        avg_y+=key[1]" X; O  l+ v  b
        avg_y=avg_y/len(user2)& q% I# w' `8 i3 U+ p
        0 c% N$ K9 b" ^) S  w* _- G( M, a
        u1_u2=0.0
    0 i! N' z3 O  f, g* ?% `" f! ?; i! {    for key1 in user1:! u" A+ z" h2 k: k
            for key2 in user2:
    1 {" z$ ^* E+ @! a  \6 v. e            if key1[1] > avg_x and key2[1]>avg_y and key1[0]==key2[0]:
    7 K( @( F8 S0 ~5 K1 O9 e$ s. b6 p                u1_u2+=1
    3 ^1 r( a' w% L/ a    u1u2=len(user1)*len(user2)*1.01 k  o7 }* j$ T/ F; i
        sx_sy=u1_u2/math.sqrt(u1u2)2 A4 P5 Z4 v% W) T1 w+ P: n% O
        return sx_sy' O4 y9 H2 P) W" ]" Y
    ! P0 Q- b9 `) ^, @% f/ ?5 n
    5 A9 _6 S" j+ Y) a8 c" e4 W+ `
    #
    2 @1 S" f2 }8 }4 E( A. a! {#   计算余弦距离  S. O/ w/ t: V( t! Q0 \( H
    #% A, u9 \7 Q9 w8 x2 N8 b
    #8 B6 U2 d* [8 |, ]6 v, X9 T
    def calcCosDist(user1,user2):) b5 b  u  Z/ A% a5 g+ ?8 h) l, D
        sum_x=0.0; J, h8 s  j' D8 P1 D. O' V
        sum_y=0.01 T4 b1 u7 E- _1 [3 p
        sum_xy=0.09 ]9 ~0 s; ^# e( K# e% u
        for key1 in user1:" L. U5 H( L6 {- n7 L# V
            for key2 in user2:! k9 g( Y% N; F' w7 z: ^! @
                if key1[0]==key2[0] :
    / @4 C- F. M. w                sum_xy+=key1[1]*key2[1]
    4 s, r# N- k. u0 q, J- M$ B                sum_y+=key2[1]*key2[1]/ P5 C' J" T) o3 U" p
                    sum_x+=key1[1]*key1[1]
    7 J2 ]* X' W+ b  f* w" Y    * G* I7 |: y* m* y! Q8 q; w- l# ^
        if sum_xy == 0.0 :
    # R- d& L! f% N& s        return 0
    * `  r; q4 K: J. h) _/ O+ a# W0 a    sx_sy=math.sqrt(sum_x*sum_y)
    5 _; Q% k2 n% J$ ?! t    return sum_xy/sx_sy
    , j# P$ D% d& h  L/ R
    $ |! [2 D& I( r5 m) d
    9 V$ R9 d; D& H#; t8 A- }! o; O+ F: I. `+ A
    #5 O" D* V- \  I7 e
    #   相似余弦距离1 B& x, T$ ]5 W! s  r
    #
    & @/ }# O) ^% M# V, `8 Z#
    : P/ ]' y; f* g/ E#, m( X6 T0 N3 T! r# v: B( D7 D
    def calcSimlaryCosDist(user1,user2):: Y* H4 b# b2 m# K5 u5 J0 M
        sum_x=0.0
    5 r0 W; K7 u. G    sum_y=0.04 S* O9 |' \4 v& A7 }" e1 a
        sum_xy=0.0
    , |4 L% }0 e, Q% T( F" ?* I5 S    avg_x=0.0/ g  g" ~6 S, N0 }5 p  ~/ ]
        avg_y=0.0+ B0 ?  P) u1 r5 _; f( K* `/ h
        for key in user1:" [( _, B: @) N6 ~* ^! c4 ?+ q8 }
            avg_x+=key[1]
    8 C. |/ k9 I+ ~: g) {/ f( w    avg_x=avg_x/len(user1)
    9 q) t! t, E- S   
    9 ]8 d0 {) q0 G' _    for key in user2:* k& |6 T9 C' D& |6 \
            avg_y+=key[1]8 k- T! {+ X  R9 J& }) c
        avg_y=avg_y/len(user2): N- }, }" m/ \; j0 j
        / n3 d+ C* ~! Z0 x" ]5 Q5 u6 E8 E
        for key1 in user1:
    2 ~8 L& P+ u$ m: I2 n7 }        for key2 in user2:* Y- h" @  p; B5 C
                if key1[0]==key2[0] :& @& w( R0 l7 p0 \" b% v0 P
                    sum_xy+=(key1[1]-avg_x)*(key2[1]-avg_y)% @% S- w" G7 Y0 N3 W, @, y, {% z/ ]
                    sum_y+=(key2[1]-avg_y)*(key2[1]-avg_y)
    ; j/ @. o: U7 H  S( p        sum_x+=(key1[1]-avg_x)*(key1[1]-avg_x)
      \7 v  n8 [( b6 y& I: d3 ^' g    1 c# v4 }' @) @
        if sum_xy == 0.0 :
    8 E; ]2 k) q. |! g/ N; t        return 05 S% L6 ~+ i) }* C6 r% p
        sx_sy=math.sqrt(sum_x*sum_y)
    & `7 e7 X2 D  t    return sum_xy/sx_sy  J/ P4 S' q( E7 ^: b
        & O7 L' U, k  O  t+ B. C

    6 u0 J7 n( R) c7 g#6 E: B  B( c. J) ?& A4 S# s
    #   读取文件* X+ o& w- N+ i" s$ d
    #
    - y4 \4 Y# d% A# i5 J#5 z# n# U5 H. q
    def readFile(file_name):
    ) b8 K4 u" N. h' Z3 I    contents_lines=[]4 I6 l: P9 }7 `) V; }+ [8 s4 h3 q
        f=open(file_name,"r")& b* e" n+ w$ |" I; Z$ z7 L& R4 }
        contents_lines=f.readlines()
    9 l8 z  P4 B9 {8 ~) z    f.close()3 ^% {. k' K7 v% s( I( g  r% Z
        return contents_lines. Z5 p# t; R* L: i5 G; M! n

      j/ Q, p& h# ]( b5 g: O
    & O+ h, @4 e/ j
    8 |9 M# a. w% ^; l4 r- j! q#
    # G4 c2 J$ p9 m) `: @. W#   解压rating信息,格式:用户id\t硬盘id\t用户rating\t时间
    ! K% m1 @5 E9 x, p( w#   输入:数据集合1 l2 v2 l4 G2 G7 D, {# s! o
    #   输出:已经解压的排名信息# x/ J& l& T, F& P/ P* Q# N' \( ~
    #7 {/ ?: h, d$ F; ]
    def getRatingInformation(ratings):$ Q0 q  u' n. p5 m
        rates=[]. r( I9 e3 N; b
        for line in ratings:/ \$ C: {% l- |& y
            rate=line.split("\t")- Q& {( W7 Q. a+ l( H5 P- h6 z
            rates.append([int(rate[0]),int(rate[1]),int(rate[2])])+ A4 Q# n5 m9 t. ^& b) ^
        return rates  e3 D# O$ \  X( H( Q9 e, y

    $ D7 @1 x4 \' X7 b  M
    " m8 D! I# C5 ~: c( Z#
    " E7 F7 M; \$ E& E' t! s8 x#   生成用户评分的数据结构! {* c" C' V5 s  w
    #   
    ; g( ^8 Q: \: {! _#   输入:所以数据 [[2,1,5],[2,4,2]...], |4 p. h2 E$ {. }7 C' X
    #   输出:1.用户打分字典 2.电影字典
    2 A# [- Z" L: N* |- r#   使用字典,key是用户id,value是用户对电影的评价,
    $ Y: Z; U8 R! Z- x8 O#   rate_dic[2]=[(1,5),(4,2)].... 表示用户2对电影1的评分是5,对电影4的评分是2' @2 ]( h1 D' J0 {  Y# C
    #2 z, X% ^7 {7 [) E8 g
    def createUserRankDic(rates):
    , U! ~$ O6 L' n- d    user_rate_dic={}+ Z; b6 d( L' V3 u" i% ?# U
        item_to_user={}
    & F5 ?1 l& A  K    for i in rates:- p' [5 u* M0 }
            user_rank=(i[1],i[2])
    : \8 ?5 H2 }2 G1 c  e; E" l* M        if i[0] in user_rate_dic:
    9 A. m, _: j8 ?6 X! k' a            user_rate_dic[i[0]].append(user_rank)
    9 k: t+ R5 o  M* G        else:
    6 Y3 H* H+ m! y; A! @            user_rate_dic[i[0]]=[user_rank]0 M: h" ^) D0 w$ V4 `; L
                
    ; j8 f. q: u" C& }5 E% _6 x# E: \        if i[1] in item_to_user:
    ; t7 G0 ?  c0 l& B  \- \            item_to_user[i[1]].append(i[0])
    8 S* A8 ]% A% R2 z; k        else:) s4 u3 _; Z# ]6 p
                item_to_user[i[1]]=[i[0]]. R: S# F+ C) f+ [8 j
                ( a# K" I( S: o% t, {- O
        return user_rate_dic,item_to_user
    # a/ Q" j# ]$ x
    ; z& \8 M4 g; j9 [) B0 {$ H( ~1 @4 g
    : s4 x' o$ S& {8 }#/ n4 i+ R( n, G+ ^8 ]0 l" d4 w6 @5 o
    #   计算与指定用户最相近的邻居
    ' ^( q3 E$ E) ^; y#   输入:指定用户ID,所以用户数据,所以物品数据' z( k/ g8 w! g) t, {- d
    #   输出:与指定用户最相邻的邻居列表- S- Y) b$ v/ [0 g
    #
    * Z& ?; F) A6 j9 Qdef calcNearestNeighbor(userid,users_dic,item_dic):
    5 y# F; I. g! D    neighbors=[]% t% K3 Y- k/ r( P9 O! ~
        #neighbors.append(userid)+ c. ^2 a& p9 H
        for item in users_dic[userid]:
    6 ?3 M' ?, H; W6 B) O/ p        for neighbor in item_dic[item[0]]:
    1 s" b% z6 L% w; m7 A5 j- z            if neighbor != userid and neighbor not in neighbors:
    ) z: s9 g  F8 I4 s+ B4 Q                neighbors.append(neighbor)
    ' r- n' N+ s' P# F/ w2 l      . S7 h5 l* l) c/ P
        neighbors_dist=[]8 s1 h3 M2 f8 ^3 Q
        for neighbor in neighbors:' h7 M/ }1 i. }
            dist=calcSimlaryCosDist(users_dic[userid],users_dic[neighbor])  #calcSimlaryCosDist  calcCosDist calcCosDistSpe* L+ k9 T0 _4 C* I: c( ^
            neighbors_dist.append([dist,neighbor])
    ) e8 C% I5 J, \" n1 `% s) p    neighbors_dist.sort(reverse=True)  A9 Q5 P' e5 I" b/ J- M5 J
        #print neighbors_dist
    9 f5 d+ h9 |# B' a9 Q( l1 m, v    return  neighbors_dist/ t9 E/ S' N' R5 P' }$ A; m- |) }

    $ y7 ]) f6 y$ G, k6 y5 \' k* e  U* J; }+ e1 Y
    #
    % K% A4 p0 N! V* m#   使用UserFC进行推荐; v4 g. x) {9 r% B
    #   输入:文件名,用户ID,邻居数量
    $ K* K! b: A. T2 q#   输出:推荐的电影ID,输入用户的电影列表,电影对应用户的反序表,邻居列表+ f" e/ E2 P. N
    #
    * F2 ~, q9 O4 vdef recommendByUserFC(file_name,userid,k=5):
    7 u% u* r- g& X7 w( [    8 s' f- B2 t: E7 |: |' G2 e$ [" |
        #读取文件数据
      U! r# Q4 Q6 {0 t. i3 {    test_contents=readFile(file_name)
    2 P  X6 V4 b( W7 f9 h      d1 o9 e5 `6 r, h( w/ J6 S
        #文件数据格式化成二维数组 List[[用户id,电影id,电影评分]...]   w# D" X: T& d, O( @$ t! s4 M: D" U" |
        test_rates=getRatingInformation(test_contents)) i3 i2 h& `3 X, E/ a2 H) S
       
    / s9 H. l- U+ e; _$ J    #格式化成字典数据
    2 X9 {( E6 v/ J* s$ m) S    #    1.用户字典:dic[用户id]=[(电影id,电影评分)...]
    5 A( f* y7 [* {+ N+ X1 O! V9 f8 N! e    #    2.电影字典:dic[电影id]=[用户id1,用户id2...]
    ) n- N4 r8 a, w# v  f- s* U9 {    test_dic,test_item_to_user=createUserRankDic(test_rates)( n( }) C" d9 ~% C; i
       
    5 {' i7 d2 [# J, p    #寻找邻居1 H1 U5 j: f9 D( ?4 Q6 i* m
        neighbors=calcNearestNeighbor(userid,test_dic,test_item_to_user)[:k]
    9 h2 Q( k: E8 K) @9 ^% w        " K' F! j. m; s; F3 g* N$ C7 h
        recommend_dic={}
      t3 J1 W! S$ [: J    for neighbor in neighbors:
    4 r; A9 a- C: l- M2 T/ c" x        neighbor_user_id=neighbor[1]9 D! f$ d6 S0 g; A6 I
            movies=test_dic[neighbor_user_id]# A) A& i3 l2 U! N  c; H" N4 R
            for movie in movies:5 [0 K2 q, g0 b
                #print movie
    0 @0 d) H- q% r            if movie[0] not in recommend_dic:
    & c8 M0 s" {9 I8 \) f9 d; i                recommend_dic[movie[0]]=neighbor[0]2 A- b4 L: x* J( k
                else:
    # z, d6 m+ m0 A* c' j$ G9 P                recommend_dic[movie[0]]+=neighbor[0]; b+ O3 ^( _( d
        #print len(recommend_dic)9 p% z) o: f; H
       
    " l3 ?5 ?) T2 B; V    #建立推荐列表
    " `; a5 F) @) ~$ h" }% ]    recommend_list=[]6 }, E! D5 l/ \* y
        for key in recommend_dic:
    1 A2 L, b& a# ~5 I3 @' w9 N! Q        #print key
    " i8 I) y) J% r4 g        recommend_list.append([recommend_dic[key],key])
    - u0 k! m# _3 j8 V: \3 P! W    0 Q( l9 E6 F& W2 ~8 z2 W4 @
        - C* K% e$ }6 b, `
        recommend_list.sort(reverse=True)' z$ O% s# h/ }8 y. G6 y/ v
        #print recommend_list5 z# u( l+ Z) s/ e/ a% _( {$ ?. L
        user_movies = [ i[0] for i in test_dic[userid]]: A0 Z! `& ]9 d. x4 W" L: b
    % b$ t/ v* b  Q
        return [i[1] for i in recommend_list],user_movies,test_item_to_user,neighbors
    ! H' T/ B7 s8 Y4 Z( P   
    1 m1 c) L4 f( ~3 d$ M  u    5 j4 |1 q4 V  h7 |% C
    8 d& E3 s% X# C! O( q2 q7 H
    #
    . x& b' a6 r( U. ]$ W. K$ p#( O9 G* e& c4 j8 g, d
    #   获取电影的列表
    , v) G. Y  r6 p! f- Q- S+ d#2 }. g" ^% Z  B! G
    ## ]& N  c  p. {( r) c
    #
    4 \$ k+ M% J4 b2 \/ D/ B# Adef getMoviesList(file_name):
    # Z0 s4 d' B. ]$ l( P' f# s) N& t) \    #print sys.getdefaultencoding()
    8 q* F4 e9 a! J* L2 ^* z& _    movies_contents=readFile(file_name): J# e. z0 t; v9 A2 Y1 f# Z
        movies_info={}6 C5 `0 U& J. \; V& U3 [
        for movie in movies_contents:8 B/ s! s3 w. u( y( L
            movie_info=movie.split("|")( j$ h6 b- x1 b6 ~& ~% A
            movies_info[int(movie_info[0])]=movie_info[1:]: R- S4 L6 Y7 [6 B
        return movies_info
    2 [" S1 `; y1 T- q- K8 {2 h9 z    & L: D9 j5 S* \! e, q
        % u8 G' K$ L; e( n+ s! d
       
    1 D1 S, f) i& x#主程序
    5 l1 \; ~0 L; I2 w3 J" J#输入 : 测试数据集合
    7 Y) V8 \2 {0 Y, Tif __name__ == '__main__':! |& _8 `4 s" S- l
        reload(sys)6 p7 d8 ~$ H% {8 G
        sys.setdefaultencoding('utf-8')
    ' Q. d" N4 y* J: K7 X9 F2 g    movies=getMoviesList("/Users/wuyinghao/Downloads/ml-100k/u.item")* l5 G- p5 Y. d; {6 R8 \* Z
        recommend_list,user_movie,items_movie,neighbors=recommendByUserFC("/Users/wuyinghao/Downloads/ml-100k/u.data",179,80)/ j% }, l/ L- T( U. q- j: Q
        neighbors_id=[ i[1] for i in neighbors]
    ! d4 O/ v5 {1 i4 a- D& x8 \5 G    table = Texttable()
    # {2 c, d3 _3 C1 a' d& [4 V7 w    table.set_deco(Texttable.HEADER)
    ; X; k9 p. [; O$ {- M& m    table.set_cols_dtype(['t',  # text : d8 `. x& b% c- o/ G/ b
                              't',  # float (decimal)
    3 {* ~" \! I- I& @# }' A                          't']) # automatic
    . K: o5 f  i8 p" G; X  |6 O    table.set_cols_align(["l", "l", "l"])
    4 e5 V* p: ]5 v" L' m* j( c    rows=[]% ?  `' b- O% Y* j! A1 U
        rows.append([u"movie name",u"release", u"from userid"])
    . m: q/ B0 T1 D# y# A# w    for movie_id in recommend_list[:20]:7 S+ h; m( `+ i0 [0 y# v4 e; P
            from_user=[]" v' t" _0 E& ^9 Q
            for user_id in items_movie[movie_id]:
    8 S% S9 N3 y7 e' O- e/ V* ?+ L6 z            if user_id in neighbors_id:
    $ u$ c8 V9 `& j8 j                from_user.append(user_id)
    : E' ~4 q: v3 w: B* \+ L2 D' G9 g) q        rows.append([movies[movie_id][0],movies[movie_id][1],""])
    8 X' \& [- z- ?" B: x# O    table.add_rows(rows)! U( ?& c7 n1 H* T# 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
    " \5 n& x$ _* d# a+ P/ Q# -*- coding=utf-8 -*-
    $ o4 c% ?: `' d) j" k) W6 E: E9 u& q6 |9 H! m; e1 R7 `8 k
    import math

    9 t1 n9 y0 [: ^/ [' r这是什么语言的程序?( ]" N: K+ h" 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, 2026-9-16 18:19 , Processed in 0.433819 second(s), 67 queries .

    回顶部