QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 5363|回复: 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
    本人在学校参加暑假培训,需要这个算法做题!求大神赐教,感激不尽, W7 S6 ~( ]' I5 c
    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 -*-
    7 P; d3 C; j& f' I! S2 E. b) C2 ~: A# g7 G
    import math  n" ^# G" a8 z# Q! h
    import sys
    , s. E" b$ \" G2 m! v  R: K. Mfrom texttable import Texttable  P0 X3 v+ z* ~+ n/ l
    3 t( p; K* \6 d* `8 W

    ) Y$ }( E3 h2 s9 X5 Z#
    ! }! o4 {1 ?( k: |, x#   使用 |A&B|/sqrt(|A || B |)计算余弦距离
    " c# b% w3 F2 q: E0 u4 W4 I% U* K2 [: U#
    # S1 o7 o* L' w: S#. T" ~, W( c2 I2 r" G
    #& O& w% T) K" `3 {, i- T8 _
    def calcCosDistSpe(user1,user2):) |7 ~: Q0 e! J# `
        avg_x=0.0
    4 [; M% i0 n! N% @( ]    avg_y=0.07 A  Q4 x& N, T  F
        for key in user1:9 L. w. J) ]2 u) T4 F9 R6 I
            avg_x+=key[1]* l# _. D" k. f; n( r1 _
        avg_x=avg_x/len(user1). t, N" G0 \6 Z. ]3 ?# _
        1 ~# f) U1 G8 [- j. C, |
        for key in user2:4 J- E5 h& T8 i2 j, M5 D
            avg_y+=key[1]) k  L1 c6 L  f8 e
        avg_y=avg_y/len(user2)
    + e8 q' ^# j5 f6 j1 H   
    % F" c/ b7 J* K. s4 h    u1_u2=0.0
    9 p& Y! @4 s4 e/ L3 w( w    for key1 in user1:4 H) h2 C( T( v; k8 I
            for key2 in user2:) h/ O4 V+ I) T5 Y
                if key1[1] > avg_x and key2[1]>avg_y and key1[0]==key2[0]:
    - Y9 D0 J' Y1 x1 l( Q% v: t+ ^                u1_u2+=1
    ' X2 H' q) m" e' w2 f3 c* I    u1u2=len(user1)*len(user2)*1.0+ L/ i2 ^( U8 Y/ h" d) M
        sx_sy=u1_u2/math.sqrt(u1u2), K! [  q) E! ^6 P4 m
        return sx_sy
    8 Y7 u* g1 x% F# V4 F; G+ t$ h4 |' T4 S5 v. ?. D/ s

    * z& w: J& D: @#. O# m$ W! }0 h) _
    #   计算余弦距离1 D, D' g8 W+ z: T. {& O
    #) i7 C, m& s2 j
    #
    7 E0 G6 S$ @/ N2 h+ rdef calcCosDist(user1,user2):7 n2 L5 ?) D/ c7 r/ C; }$ v) [5 C
        sum_x=0.0" N, v: Q; H/ O& I
        sum_y=0.05 Y4 k) i1 U8 G, b1 B* k2 {, m
        sum_xy=0.0
    ! ]4 y- v$ I: w! H6 l2 B& M  n" M. E+ ?+ J0 l    for key1 in user1:" h$ R+ ?# J: u; l) \
            for key2 in user2:
    & A' W' G0 o( b8 D- D* M2 M7 Q            if key1[0]==key2[0] :0 D( n8 L% n  F9 A2 m
                    sum_xy+=key1[1]*key2[1]9 }' [! D) [# J8 G* P
                    sum_y+=key2[1]*key2[1]3 S2 M) w1 V) q" [1 a; s% p. S
                    sum_x+=key1[1]*key1[1]" D* E9 T) c/ f4 B. Q* g1 p' b
       
      K0 [  b  k' A, b9 ]  J    if sum_xy == 0.0 :: J! u- p6 H# N9 T8 [
            return 0' ^) ]* u0 n$ b5 x
        sx_sy=math.sqrt(sum_x*sum_y) 8 E" P) o  o2 H! b- }
        return sum_xy/sx_sy- Y! N1 h& \- M" w

    ' ^7 |+ e7 V! I$ {! F* l+ w! |
    : D) g4 j: i; T) m+ R5 q#( C- c3 I$ B  @" d
    #
    ) W* A! r% `0 U# Q#   相似余弦距离
    * v6 @, G" H( J1 w( p% o+ h1 H#' [5 |$ f$ i& |0 Y- T0 z( P
    #$ s5 f- {& X, E9 u% B: T/ n* n
    #
    7 k: g4 B4 @- p% M8 |def calcSimlaryCosDist(user1,user2):6 b" j0 X' A3 O7 ~' i& l. S6 V0 D
        sum_x=0.0( ~& F# X' Y* Y8 ^! f4 i
        sum_y=0.0
    * S$ p3 Q' V, F% j4 f    sum_xy=0.0" c7 Z  l- |6 L+ u& q
        avg_x=0.0, Y" ^) R6 c1 L# j! O- ]( {4 v
        avg_y=0.0
    1 U8 ~$ ?- T0 ]. H$ @+ q7 V( i    for key in user1:
    ) g  {1 a4 s# W3 n; E( T        avg_x+=key[1], _; A2 q0 t, h3 |
        avg_x=avg_x/len(user1)9 l' V  W/ P- T- n; q* k/ f) p6 l
        7 }" h. O" h4 [* w/ j- R
        for key in user2:% A1 n& g( ]# l' {! z& _  R; n
            avg_y+=key[1]
    ( I/ I) x. Y- w5 c- l    avg_y=avg_y/len(user2)
    & h+ C6 T0 }1 u  c& _    : ~% o* W; t. A8 }. |5 S; o
        for key1 in user1:# e6 w; P- ?% Q6 s
            for key2 in user2:# a, P' _3 X5 ~$ i9 l6 h$ N: f+ U
                if key1[0]==key2[0] :
    % V; V" f  c: Q; b% C) ]: N                sum_xy+=(key1[1]-avg_x)*(key2[1]-avg_y)2 U' V" o/ A6 W; D% x
                    sum_y+=(key2[1]-avg_y)*(key2[1]-avg_y)% w5 h4 y- a2 O8 Y, w- b/ \. p" V/ [
            sum_x+=(key1[1]-avg_x)*(key1[1]-avg_x)
    * ?0 c0 s% o) Y  A$ ?   
      m0 K$ ^1 P: l$ T; n# \2 Q    if sum_xy == 0.0 :
    ! w# C+ U6 O- n$ l, J        return 0  C, q8 k$ m/ k) T2 g& y8 g
        sx_sy=math.sqrt(sum_x*sum_y)
    1 z# m5 R% w& f; h; b2 Z    return sum_xy/sx_sy
    ; e1 j% x; F' K6 S0 m   
    8 I* A& w4 }- P
    & G; L) C6 `2 W2 e- L' \6 h#
    ! f0 c% {, K( |' m, P9 u# \% B#   读取文件
    / b: i9 }0 Q" F% u, G: L4 z2 |## `6 Z/ K6 ~% y( Y5 v" s) @
    #/ h7 P4 _, e& ~" }6 W: g& f
    def readFile(file_name):
    6 I1 s  E" j/ ?6 f0 J+ v1 T2 R9 [    contents_lines=[]+ f8 V; q, s+ w) ~
        f=open(file_name,"r")
    ' D6 a0 U8 ~7 }! [    contents_lines=f.readlines()* `% g; m4 E2 {/ p4 r
        f.close()8 q& c3 C' c9 U9 P6 ?
        return contents_lines
    ; X3 d+ R3 _7 q" T8 R5 T; i6 o2 z5 |

    . Y* Z8 [8 I( h" o3 `% X- b; e. n9 e' ?
    #
    + V9 ^! d2 T9 p9 \/ Y# F#   解压rating信息,格式:用户id\t硬盘id\t用户rating\t时间. x0 Z/ _+ A# ?
    #   输入:数据集合' U3 z( l, `4 r$ z; N
    #   输出:已经解压的排名信息% F# g' O' l! Q  [
    #& m' r( P5 F* J" i, y' c; ]
    def getRatingInformation(ratings):5 f& c3 ^2 R4 l+ ^: s
        rates=[]4 [! C& S6 E7 P- \% f; d
        for line in ratings:
    : {" }8 A4 i# G0 @        rate=line.split("\t")5 ^" o6 \+ \; X0 K' H# B
            rates.append([int(rate[0]),int(rate[1]),int(rate[2])])0 e3 O1 \% B6 I
        return rates' w7 l6 `3 y6 L/ r3 Z, l

    " J$ M5 r* z) m: I) u9 I( d9 C7 W0 z7 n5 G. y, b% w+ b
    #
    * H4 i# V, K5 Y: A1 T8 ?1 E* _) K#   生成用户评分的数据结构5 x; L; H( ^! a
    #   ) w$ t/ B3 Y4 Q$ b- e; i
    #   输入:所以数据 [[2,1,5],[2,4,2]...]  O; A% F6 n4 U* j5 A
    #   输出:1.用户打分字典 2.电影字典: X( S. K) Q: h% V
    #   使用字典,key是用户id,value是用户对电影的评价,' I$ N' ]3 m+ l! y; d
    #   rate_dic[2]=[(1,5),(4,2)].... 表示用户2对电影1的评分是5,对电影4的评分是2' `. s6 P# |3 N' Y7 Y
    #
    : ^& m# d; n" B6 s  Zdef createUserRankDic(rates):+ r: X$ ^! o7 [9 Y! b2 ?9 ?
        user_rate_dic={}
    ! H2 |' M  x1 L    item_to_user={}
    4 c0 R" W9 O; l. {1 s: W    for i in rates:' _: T$ d) u5 V2 F$ e
            user_rank=(i[1],i[2])  y9 Y$ K5 d7 C6 `
            if i[0] in user_rate_dic:
    # U2 G* S9 b- s8 Y$ s; [- C            user_rate_dic[i[0]].append(user_rank)! l! ]; v0 n3 {  M! b+ a. n- E- G1 M
            else:
    , O: _$ ^) W' {% Z" `- I            user_rate_dic[i[0]]=[user_rank]5 G/ R8 [0 ]( K3 |; M5 `
                * b7 I  n4 U% ^( |1 j
            if i[1] in item_to_user:
    & g7 l- Q: u/ Q6 w6 G            item_to_user[i[1]].append(i[0])$ ~8 W9 Q! J* x# B* T
            else:- T- v' I5 @0 ~, w; k: ]
                item_to_user[i[1]]=[i[0]]
    9 v6 I0 ~2 @4 a0 D            
    ; B* ^) O# [  b    return user_rate_dic,item_to_user% p0 g4 @- ]! y, T4 @
    2 v+ G2 I/ x2 f' A, O1 l, e! @7 A
    ( C3 y# }5 p5 k8 w% u) g: E$ l
    #
    + B% X# `- j3 \6 Y) R, K- Y% j: s#   计算与指定用户最相近的邻居! s- E5 Y# ~4 a/ X% c( _1 N8 u
    #   输入:指定用户ID,所以用户数据,所以物品数据
    9 t# L0 j  O* Y& `* `, w0 A' p#   输出:与指定用户最相邻的邻居列表; j6 y: s9 C' F
    #
    4 z- L& x' D5 w3 Hdef calcNearestNeighbor(userid,users_dic,item_dic):
    ( W$ N4 V" V- T. c  E    neighbors=[]# q4 N. b" P8 a1 i
        #neighbors.append(userid): Y. |2 N1 |% y; E9 ~- X- ~
        for item in users_dic[userid]:  `: b* y2 G, Q9 C3 {$ h, [0 l
            for neighbor in item_dic[item[0]]:
    + W$ w% _0 u6 U' @            if neighbor != userid and neighbor not in neighbors:
    7 R+ f; v) l: e                neighbors.append(neighbor)
    ) v+ R2 q4 f, E! W8 l6 T: M      
    9 j  P/ \; I! |1 e+ A) m" @    neighbors_dist=[]3 W$ S# w7 ~6 |: u" H1 G2 Q
        for neighbor in neighbors:
    9 A$ |  M5 ^+ u: g( d        dist=calcSimlaryCosDist(users_dic[userid],users_dic[neighbor])  #calcSimlaryCosDist  calcCosDist calcCosDistSpe
    + r, c$ q& x/ k1 G8 b: P$ m( r        neighbors_dist.append([dist,neighbor]); _7 ?( l. f, ?4 _
        neighbors_dist.sort(reverse=True)
    % H! ~; V+ H- k3 `7 W) t# g7 F  s" Z/ I    #print neighbors_dist, _. J+ {% b2 N) @4 {
        return  neighbors_dist- g1 i, o) L7 t( k  P4 I3 u

    - R  b, m' ~( p) \  K9 e8 c& I: p" }' t" o) [4 o8 {( V/ A
    #
    - Q1 W3 g/ s! b, o7 @! H  P# Z#   使用UserFC进行推荐2 P0 J  T, n: d0 ?# A/ ]6 \' d
    #   输入:文件名,用户ID,邻居数量
    7 p" B8 v. ~! E8 h! p$ Q) }#   输出:推荐的电影ID,输入用户的电影列表,电影对应用户的反序表,邻居列表. o) s3 y) |7 A
    #
    " M7 h$ P$ |8 A5 P; Z% T  `9 Udef recommendByUserFC(file_name,userid,k=5):- X. \7 g5 j0 Z
        9 F! Y8 Q8 G; i* `: E  k  o
        #读取文件数据# E0 o; @  a+ Z- S' B( b2 {
        test_contents=readFile(file_name)
    & I1 a+ V; J, ^' i& O& ~5 J   
    & S4 B& d4 b, B* r3 m$ R+ w9 \2 m1 t    #文件数据格式化成二维数组 List[[用户id,电影id,电影评分]...]
    4 Z  P4 d- J  L/ b: `( n    test_rates=getRatingInformation(test_contents)- k$ E  m+ X4 C
          E& y( |1 j' k9 p" v. }1 C: h- R
        #格式化成字典数据
    ! G! e* Q: T+ n- ~    #    1.用户字典:dic[用户id]=[(电影id,电影评分)...]
    ' m( ?: F2 f2 J, `* I( k8 M7 l9 Q    #    2.电影字典:dic[电影id]=[用户id1,用户id2...]
    - @! q( A. ?9 X. p    test_dic,test_item_to_user=createUserRankDic(test_rates)6 A# f9 J2 q1 C2 M1 _
        6 I% O- l) B* P9 w- H
        #寻找邻居. B  _, @" g8 H
        neighbors=calcNearestNeighbor(userid,test_dic,test_item_to_user)[:k]
    3 L9 U7 L' D+ ?( Z  Y        4 M) j$ \, a& Z: T% v- r
        recommend_dic={}5 D; B5 M: P( A1 T, i
        for neighbor in neighbors:
    7 i  V; v+ i" v6 d        neighbor_user_id=neighbor[1]
    2 C! h$ U; P3 x) s        movies=test_dic[neighbor_user_id]7 n/ ]7 p; b! N: S, J
            for movie in movies:7 n8 w) I! ?5 T" S; ^: `& m
                #print movie
    # @3 c# r2 m  b5 V2 ~+ b0 E7 b: W* {            if movie[0] not in recommend_dic:$ E; ]  T( `# c* d
                    recommend_dic[movie[0]]=neighbor[0]7 S& D1 h( C' C. W8 t, A' t
                else:9 |1 X, ~- L9 J
                    recommend_dic[movie[0]]+=neighbor[0]/ d) z$ F2 R; |' \8 U9 {7 F
        #print len(recommend_dic)
    * S1 N6 A( Q( K. q3 W    4 X+ K8 H; E6 q4 R8 d9 x
        #建立推荐列表
    0 \# y; s4 x/ W! G    recommend_list=[]$ j/ }9 W1 b; e* f( f2 f
        for key in recommend_dic:' v! ?; |0 ]' C9 g( R9 G2 ^
            #print key
    0 z; g% f0 \- C0 h) ]        recommend_list.append([recommend_dic[key],key])
    ( I& W) E3 z  u& M  ]- c* w   
    / j- X0 W% c3 P; t    ' O/ h+ h+ ?2 [: R
        recommend_list.sort(reverse=True)' X8 g- n+ }% d  V
        #print recommend_list
    3 \/ X" p5 _# N" c    user_movies = [ i[0] for i in test_dic[userid]]; ]4 E- O, `( n0 O

    4 w5 _1 O) n) ~* J0 c    return [i[1] for i in recommend_list],user_movies,test_item_to_user,neighbors7 l# B/ l0 t8 |
        / i1 ~* A0 e3 I2 I6 B; W
       
    $ W% F2 T! J7 L+ O+ B* v8 j  h3 q; E; q9 u
    #0 D9 R* y; w. h2 o/ q, ^- h
    #
    . U, T( w+ m9 \' w! |% G& [2 R#   获取电影的列表
    / ?3 U+ H) V/ b#
    5 e3 ^# n4 h7 ]& b#
    - o. s7 e* m$ Q  B* b  w2 e3 T#
    1 @! J1 d* |! R) @def getMoviesList(file_name):
    : ^6 q2 ?6 ?: a/ \    #print sys.getdefaultencoding()1 ~3 t$ f9 C$ E0 x2 c
        movies_contents=readFile(file_name)9 v4 m! N  X+ _
        movies_info={}% G- ~, p( l$ ]9 l
        for movie in movies_contents:
    ( @- D5 ~0 I2 h4 R, `        movie_info=movie.split("|")) @+ i, X& B/ r. B4 p4 Z
            movies_info[int(movie_info[0])]=movie_info[1:]- l9 A- c3 L; }+ {/ c
        return movies_info$ S4 C* s8 C# B3 p0 A
        2 B% X1 a+ ]  Y, _5 i% y7 W
       
    $ C) H( E( \6 R7 r$ t- p" @2 Q5 a    # w. M3 @- J, }( s
    #主程序: u1 \3 P5 n9 n3 P! a7 {
    #输入 : 测试数据集合
    $ J* e1 n. V. T* @if __name__ == '__main__':
    7 H; Q0 f8 U8 ~7 a    reload(sys)
    0 Y$ h5 w  a0 h% Z    sys.setdefaultencoding('utf-8')" p) V" D! ^2 h6 O- \
        movies=getMoviesList("/Users/wuyinghao/Downloads/ml-100k/u.item")( E' F3 l! r3 I% _
        recommend_list,user_movie,items_movie,neighbors=recommendByUserFC("/Users/wuyinghao/Downloads/ml-100k/u.data",179,80)! o- }  C0 w! H$ U" N4 q& c& l5 O
        neighbors_id=[ i[1] for i in neighbors]4 ]( Z) R/ @9 C, B2 t
        table = Texttable()
      [+ I4 U$ \  a$ w; e* ^    table.set_deco(Texttable.HEADER), F8 I& g! H4 L$ ^% ~4 i
        table.set_cols_dtype(['t',  # text ; {/ _4 p* N4 b& @
                              't',  # float (decimal)
    6 X6 |8 b6 n+ \, R# v2 v: k. z                          't']) # automatic( P4 i# l5 ?# A- n- \: L
        table.set_cols_align(["l", "l", "l"])$ |9 d, Y1 m9 ]
        rows=[]
    , f1 _, X/ }8 k: `    rows.append([u"movie name",u"release", u"from userid"])
      H3 h$ s& @1 }' ?& [( v! Z: Q    for movie_id in recommend_list[:20]:8 q* l( t/ e1 i. z3 f3 w
            from_user=[]
    2 y% q6 `* U: |- F- D- S        for user_id in items_movie[movie_id]:( [: O* A8 C' l
                if user_id in neighbors_id:$ w* S- d! e. [4 y8 V
                    from_user.append(user_id)
    2 R# p  q& D8 `; Q; {6 k4 J, s        rows.append([movies[movie_id][0],movies[movie_id][1],""])5 ~4 f3 x* }4 K* i8 g  Q
        table.add_rows(rows)2 ~! ^' _) o9 p' g7 U) ]9 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
    . k# ~+ ]& t* J+ Y2 A0 I/ i9 N6 i# -*- coding=utf-8 -*-
    : N/ |. T% X) ~! S, r) s2 r: x- a# {  E# @; _/ k
    import math
    " [" l# Z5 L; K6 L* `
    这是什么语言的程序?
    ( {6 a3 o: q& S: o
    回复

    使用道具 举报

    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-3 09:01 , Processed in 0.460258 second(s), 68 queries .

    回顶部