QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 5312|回复: 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 J) I- [  Y' `) 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 -*-
    ) H) F2 I" N( z% l7 y1 f, E) J4 P/ i: I6 E
    import math
    0 n) N# W- E+ K# w' P. simport sys
    + M9 `) N* z! i4 Q' v" ifrom texttable import Texttable
    . o' U$ r- Y/ F) E. T: n& E
    + [: Y% }2 w: o1 W3 q0 M2 H
    6 L* S1 x* k! @! ?- S# O7 ~5 Y#: H% Y! ]/ k3 H7 Y( c+ u! v! N
    #   使用 |A&B|/sqrt(|A || B |)计算余弦距离
    ) @  M3 U  u0 U5 ?* o! Z1 O## \4 R% U, ^0 y: x  a6 u. ]& s
    #% Z' y$ D) C: q$ A7 |: m2 i, [
    #
      f; _- B  \+ R- @% U8 p, c3 mdef calcCosDistSpe(user1,user2):, d- q4 S% W7 X  f: Q
        avg_x=0.0
    & z. C  y* Z3 d! k/ {% t/ |    avg_y=0.0. F' N3 c1 j( Y, M+ Y; N5 X
        for key in user1:; ?* Z5 C1 o* y: w  U" t6 R5 p( \  W3 V' g
            avg_x+=key[1]8 E3 f& b; f3 r5 h; R
        avg_x=avg_x/len(user1)
    , B2 ?3 I2 G( S+ v$ K    + @4 A+ j5 P7 g9 f* w9 v- ^
        for key in user2:
    $ i# ~# [( S& m2 u! c8 [4 T: {7 T        avg_y+=key[1]6 _1 N1 r/ o; X( L
        avg_y=avg_y/len(user2)( l# E3 H% Q1 S7 v) @
        ) m  \6 O. X+ ]& p- {- Q% ?
        u1_u2=0.0! E  i, E4 r/ o9 Z, w' {" h/ x" z; \
        for key1 in user1:
    / N+ _( W) l- @, u( y3 W) a        for key2 in user2:" h7 `8 \. z2 {* c6 w. V
                if key1[1] > avg_x and key2[1]>avg_y and key1[0]==key2[0]:5 d# M3 L' D1 d6 M
                    u1_u2+=1, f/ M+ Y$ r/ o
        u1u2=len(user1)*len(user2)*1.0
    * l  b: k4 ?$ I9 ?5 D5 R    sx_sy=u1_u2/math.sqrt(u1u2)* p; J9 o2 M- z
        return sx_sy- [) h' }* }4 N

    ! g' }6 `; h. S9 U+ \. o7 h% \! {- K' T/ d3 Y
    #4 }3 `7 D8 W% ]1 F
    #   计算余弦距离
    7 S3 E( @: Q1 s% g# l/ r#
    $ G4 n" D$ ^3 ]5 ^#
    # [, q0 W# n- a) N) Ndef calcCosDist(user1,user2):
    0 c1 ~" u8 D5 F7 x    sum_x=0.0
    - R: Z2 x4 K' o7 |  a6 p: N7 N    sum_y=0.0
    ' a% W. v4 A% ^$ c: }: ~    sum_xy=0.0
    ) {  K  z0 o; p& y4 ^    for key1 in user1:
    7 S7 l& D7 E* A% E, ~- U$ J2 G        for key2 in user2:
    / @3 R$ S& n* y* @. }            if key1[0]==key2[0] :
    2 Q8 n- m: E* r# O* b* ^+ x                sum_xy+=key1[1]*key2[1]
    . x2 R+ i, z# ^9 L1 D( M8 C4 D  q                sum_y+=key2[1]*key2[1]
    . u' g' c) I$ |& P                sum_x+=key1[1]*key1[1]1 @, B* ?3 m5 s/ {6 [$ o2 h$ m
       
    ( L3 X3 p0 D, B& F! l+ [) Z, R    if sum_xy == 0.0 :
    & i0 Z( c/ R/ Y+ T+ A4 f% r6 n        return 0
      i0 l9 R# e) V# R( m& A    sx_sy=math.sqrt(sum_x*sum_y)
    4 \7 @: p) _1 T, D5 ^4 g- R    return sum_xy/sx_sy
    $ q. d$ p0 g: i! m4 d
      v7 @3 \- |* `6 k& v3 s7 y2 x' P+ L
    #
    2 p4 A3 I3 B, f1 L- v#4 [& M$ R7 }5 C9 S
    #   相似余弦距离( k: W* \# f1 {% O# n$ h
    #2 u+ p$ ?4 j4 Q6 q4 d3 d! U! |5 w! O
    #
    5 k! D/ Y5 X* N0 |) b! ^) j4 C#
    1 d& v% [! @4 ?& w# \, {: M! pdef calcSimlaryCosDist(user1,user2):8 j5 a( v) \7 t0 K0 j0 P! c
        sum_x=0.0( u8 }' ]8 K% a) l
        sum_y=0.0
      [6 y" l7 M6 t+ z  T    sum_xy=0.07 g7 w' ^. V- v' A  Y9 F
        avg_x=0.0, |: Z3 {# B  l( }
        avg_y=0.0
    2 J. Z* C: y" `& X- _    for key in user1:
    - @5 `3 f4 T& [  y4 J. j, [5 |        avg_x+=key[1]
    * \% X, U/ X0 n1 y( x! x9 ^    avg_x=avg_x/len(user1)
    1 D7 \& p. U; u/ d# F3 ~    5 f3 X6 l6 |( E3 Y/ z
        for key in user2:
      _5 R+ E# O5 |3 B' d        avg_y+=key[1]
    . {. A( U; g4 f9 n, n& X, I    avg_y=avg_y/len(user2)) U6 ]0 N# j  @( U" j  Q! [
        + r, k! [2 U8 m4 ^5 b6 v
        for key1 in user1:
    ' v" H# d5 Q7 K$ p        for key2 in user2:
    / b4 J' q. X/ G& v7 j9 Q            if key1[0]==key2[0] :( t7 M1 h6 s5 M6 y9 l- f# n& {
                    sum_xy+=(key1[1]-avg_x)*(key2[1]-avg_y)
    + {2 r; }0 ?1 H' h" d! Y                sum_y+=(key2[1]-avg_y)*(key2[1]-avg_y)
    2 @* e9 D! y- p+ e, g        sum_x+=(key1[1]-avg_x)*(key1[1]-avg_x)
    - ^; }8 A- F0 v* x) F% j4 G8 a1 x7 f    # g4 Y1 C" q& W# Q0 _7 [
        if sum_xy == 0.0 :
    % q$ w8 O  U, x6 N9 L, K9 K        return 01 N) i, n& J4 X2 E4 q3 E1 D$ j
        sx_sy=math.sqrt(sum_x*sum_y)
    ( k; K# s: T/ H# K7 `    return sum_xy/sx_sy5 g0 Z* G1 i) e
        0 r3 Q! [0 z% D9 J& U9 N7 g

    + d3 E' G: @  v6 L2 K. P#" M: O; O* q  @% Y: c% f4 }$ v% ?; ]
    #   读取文件( {7 @. k6 g" J
    #6 S2 M& _. |' L, O: M3 n$ j5 I
    #
    " j( w# [0 I8 s* {8 Wdef readFile(file_name):
    2 u- C# A" M, {8 e/ Q# m    contents_lines=[]1 e6 p0 _% x1 I
        f=open(file_name,"r")
    7 G; Y5 c9 {% h' @    contents_lines=f.readlines()) w: A* k0 f& p1 t: A: Q; j2 n
        f.close()0 Z, S. Y& W) g0 E6 o
        return contents_lines% u2 `- S( c0 a' E
    * |" E6 o3 t, V; V8 V

    2 A5 G1 D4 y! C: ~! H* N( \1 b; m+ C/ R0 v$ e
    #6 o+ L$ a+ S$ X1 I6 V
    #   解压rating信息,格式:用户id\t硬盘id\t用户rating\t时间# d+ b" _* X% K* P5 q# `  G. C
    #   输入:数据集合
    , q: A# W( ^+ l+ {9 z#   输出:已经解压的排名信息7 ]; e8 N% ^- U' p+ A& f
    #  x4 {# k* |9 `# M& f  ?
    def getRatingInformation(ratings):& C) b! O1 N# Y6 W9 z
        rates=[]
    ! p9 p1 {4 i  @. M3 W: ~. R    for line in ratings:; i  m- V  {  i2 ?$ z' G5 g
            rate=line.split("\t")0 C9 ~0 }: t# ^+ a5 r7 M
            rates.append([int(rate[0]),int(rate[1]),int(rate[2])])9 L! r& V4 D1 B3 q* j6 f6 M
        return rates9 y% F: U& t% G8 q( U- ]5 m
    3 p5 x+ D$ l4 ~9 g
    0 r0 I% ~7 p" Q5 F% X
    #  U( _1 T9 ?" m) w: D
    #   生成用户评分的数据结构
    , S4 }6 T: I1 n* c4 l1 R0 ?5 t: G#   
    9 X; Y; @& J2 a) G2 C: u3 a4 Y, p: f#   输入:所以数据 [[2,1,5],[2,4,2]...]
    & m% O; A' |* v! P#   输出:1.用户打分字典 2.电影字典
    3 x/ T1 V: n& e#   使用字典,key是用户id,value是用户对电影的评价,
    ! D% C1 e" s2 L' ~#   rate_dic[2]=[(1,5),(4,2)].... 表示用户2对电影1的评分是5,对电影4的评分是2
    ; y: P4 e6 B' J+ W$ [#' p' q; H0 c$ {9 p( p
    def createUserRankDic(rates):
    7 Y' R8 t+ I! Q* A! N6 z! r0 G4 d    user_rate_dic={}
    8 P7 t3 X. o& f    item_to_user={}5 u( e/ x# n" f! ~- J
        for i in rates:0 ?0 `- l! _. o4 R
            user_rank=(i[1],i[2])
    3 ?4 u5 ]7 T4 c5 F7 s        if i[0] in user_rate_dic:
    % e: X* K2 M" n" ]& j- [% A; C; t7 W, L            user_rate_dic[i[0]].append(user_rank): `4 T2 R8 k0 g. ^9 s
            else:
    7 E* g& t( X' _" {            user_rate_dic[i[0]]=[user_rank]- j/ O7 L* ?* p5 @
                8 H( J% |$ H8 ]& I7 P2 Q
            if i[1] in item_to_user:
    - N" N# B* n; ~8 q            item_to_user[i[1]].append(i[0])
    4 c* h  B2 j% f& F        else:% ^) c8 E6 G; H* h/ f5 c7 q% N
                item_to_user[i[1]]=[i[0]]
    " a1 D; G$ @% }: X6 @* j3 f            
    3 b  S: g& v% ~+ H. S& ]    return user_rate_dic,item_to_user
    ' y* `, F9 n5 P$ s$ A! d4 f& o& G4 p# K5 V1 y$ O, M

      i) J3 [) f2 V! [3 d3 B6 P' c#
    0 H3 Y+ x* N/ n- Z( D5 }#   计算与指定用户最相近的邻居
    , Z- I2 G- P; l$ ^0 K# V#   输入:指定用户ID,所以用户数据,所以物品数据9 _* B/ g& A4 T" @0 x4 J
    #   输出:与指定用户最相邻的邻居列表
    $ k: k2 Y% @. ?" p5 m3 [#, [8 Y. ~7 K. d( B. ?# m& F
    def calcNearestNeighbor(userid,users_dic,item_dic):
    ( \  Q' C$ @" @6 e4 R# M8 Y    neighbors=[]: D# T2 |8 e+ y/ U" H9 y
        #neighbors.append(userid)
    3 l) L4 Q4 N9 R* _7 L    for item in users_dic[userid]:) `9 @. x& _0 B/ ?, V
            for neighbor in item_dic[item[0]]:/ A1 ~) P' H! f  r% f/ i$ j
                if neighbor != userid and neighbor not in neighbors: & ^( q# P+ r; e& E* Y
                    neighbors.append(neighbor)9 v6 x# f" ]9 w2 h3 z# V$ }
          3 a* i9 f0 r  i. s. J
        neighbors_dist=[]; F' N7 D5 ]3 A5 I7 u
        for neighbor in neighbors:0 R5 R0 D$ {7 C2 y9 q
            dist=calcSimlaryCosDist(users_dic[userid],users_dic[neighbor])  #calcSimlaryCosDist  calcCosDist calcCosDistSpe
    " b$ t. D. l8 Z3 p        neighbors_dist.append([dist,neighbor])( j+ R% C+ W2 E2 a) c" D& [  b
        neighbors_dist.sort(reverse=True)
    5 b# \# x- f1 d/ m2 C' a! m    #print neighbors_dist* v; M( k/ `' M% E$ p3 Z  _0 g% K8 Y
        return  neighbors_dist
    & S9 G  a7 F* _. O% H, s9 g8 G% ~: |) M; `4 y, h: R
    1 O, G0 t9 \- \, f
    #
    , t5 M1 G) q5 u9 K4 G  S+ ]#   使用UserFC进行推荐6 @5 F5 B/ Y) Q8 i& u  L  D
    #   输入:文件名,用户ID,邻居数量
    2 Z) z/ w4 }% P, y6 ]7 L#   输出:推荐的电影ID,输入用户的电影列表,电影对应用户的反序表,邻居列表1 I9 |" ?. F2 ?; o- l' k
    #
    7 @+ Q$ L$ z. h, ddef recommendByUserFC(file_name,userid,k=5):& G# h! U  S# P
       
    ! i) T) U3 G: E; C    #读取文件数据
    $ f5 N1 G6 a, o    test_contents=readFile(file_name)! M9 H% d5 A9 U" {6 D( J
        / {6 f( G8 S& x0 D# U' F
        #文件数据格式化成二维数组 List[[用户id,电影id,电影评分]...] , S% u( I8 \2 O, ?- a0 C1 U& ]* P
        test_rates=getRatingInformation(test_contents)
    ' T. y1 y% C/ p) ?   
    3 j$ D, H, G* `( x    #格式化成字典数据
    4 v* \3 h( m/ m$ k* `    #    1.用户字典:dic[用户id]=[(电影id,电影评分)...]
    - X/ i2 z! J, s6 Y% i4 h    #    2.电影字典:dic[电影id]=[用户id1,用户id2...]& B; A( _1 m' n+ X+ ~
        test_dic,test_item_to_user=createUserRankDic(test_rates)* s7 |, X' b3 F
        7 c4 M0 t0 [% I+ d& f- d: z
        #寻找邻居, ]" c, }5 ^0 ]  k
        neighbors=calcNearestNeighbor(userid,test_dic,test_item_to_user)[:k]0 y% e5 Y0 n1 D
            
    9 T7 J, e/ D; M6 v6 ^# `    recommend_dic={}( P  P1 p+ |3 {0 I/ y6 w
        for neighbor in neighbors:
    # e* J& ~, s1 l7 V, E        neighbor_user_id=neighbor[1]
    9 q' ^, c- W. |, K        movies=test_dic[neighbor_user_id]. B/ U0 k% R5 O8 W1 A' i0 s
            for movie in movies:5 a1 l, k. @+ Y" ~8 `
                #print movie% I9 Z+ p9 N1 N
                if movie[0] not in recommend_dic:
    $ l; I3 V& S7 r) |  B3 x5 o                recommend_dic[movie[0]]=neighbor[0]
    $ g! r) N3 O# |- q4 E! _            else:+ d% j( b2 Y3 z  u+ V8 h9 A
                    recommend_dic[movie[0]]+=neighbor[0]! `4 Q; O- G$ g! n0 y0 O1 a/ H
        #print len(recommend_dic)# B% b: ]1 G9 U6 m- n4 R
        " f. F5 K6 h$ s& r( O, _) \
        #建立推荐列表
    3 Q; I# S% }7 Q3 X) }  V. x    recommend_list=[]+ L# z9 {! D2 c: V# l" ]3 w
        for key in recommend_dic:
    ! S5 W2 \& b6 x8 |6 o) b9 d9 z/ W' ^        #print key
    9 n* h! a6 a# X# C; A/ h        recommend_list.append([recommend_dic[key],key])
    2 e; @, v  G: @* M    ( ~* w( Z1 e" [
        : [4 d- M& ^9 Y" E
        recommend_list.sort(reverse=True); v( m, C0 e3 W5 ]
        #print recommend_list! y' n  |$ a5 F# o
        user_movies = [ i[0] for i in test_dic[userid]]1 b2 ]; \9 \, Q! g& o

    ( y8 g; Y  h0 a& K8 f0 a5 L    return [i[1] for i in recommend_list],user_movies,test_item_to_user,neighbors8 |8 K7 J8 F2 a. T
       
    % D- I1 x  Z) E8 p    5 `. i% n2 \; D2 c# T7 R8 K3 `7 _5 Z* Z

    % R  j6 k$ O2 D6 t" D5 P5 C! F( l: N#
    ' c: W3 A1 ~' n  r9 k#$ T- e7 o) Z; e; y
    #   获取电影的列表4 x. V5 e5 k, S4 @
    #" K6 L! C* n1 C/ n4 i5 N
    #
    , O: ]' w! \" l3 }#
    ' p% N3 S8 k7 t6 L, v3 sdef getMoviesList(file_name):
    9 T7 i1 o+ ~( [& [$ M9 z    #print sys.getdefaultencoding()
    1 @8 U' V( k/ `0 U: t" R    movies_contents=readFile(file_name)
    4 X: g- V, G+ L' x    movies_info={}
    % k/ Q6 @! \' ?' ]0 b' {( g$ w: s4 L    for movie in movies_contents:
    & H4 b  [. ]( Q) m        movie_info=movie.split("|")" d- `% ~' X# A" A5 N6 w# {9 J# Q
            movies_info[int(movie_info[0])]=movie_info[1:]
    1 ^* k# p. E. {. w1 [    return movies_info5 y, P- V) \. Y8 A; c  B6 N* _
        % C5 A7 G  ^. n0 C3 e
        ! b1 n  w- u6 A" ~0 [4 x  h6 D4 N" f5 V
        6 b- @, G! m5 V6 _
    #主程序
    1 p: v/ \& M2 y#输入 : 测试数据集合6 [. G  r8 {5 l# i0 t& G
    if __name__ == '__main__':. ]# i1 @" }2 n' v5 Q0 v$ D  _, w
        reload(sys)
    & e- e+ O8 W. o  g' C    sys.setdefaultencoding('utf-8')
    / R7 Z1 h9 m0 J7 i- T& Z    movies=getMoviesList("/Users/wuyinghao/Downloads/ml-100k/u.item")3 o  b$ o3 k8 o6 e5 B0 Q  n' _. v* z
        recommend_list,user_movie,items_movie,neighbors=recommendByUserFC("/Users/wuyinghao/Downloads/ml-100k/u.data",179,80)" ]/ P1 {! Z! }4 x! B+ J
        neighbors_id=[ i[1] for i in neighbors]
    " W( C' y/ j; J6 u* q1 j; K    table = Texttable()& K+ N0 F6 ?0 r4 f! `' h( c
        table.set_deco(Texttable.HEADER)
    * r5 B3 w+ K' G* L2 X    table.set_cols_dtype(['t',  # text ) `0 @, ^( w5 [! l* U: g$ v
                              't',  # float (decimal)
    ) @2 ~8 ^8 x1 ^+ i                          't']) # automatic6 c8 ~7 d2 [  f' V% o5 ?% z
        table.set_cols_align(["l", "l", "l"])
    ) L4 p/ P( z+ ^/ Y  e/ t& G    rows=[]+ p5 [) @1 W! I" b1 p/ O# h  V
        rows.append([u"movie name",u"release", u"from userid"])
    ) ]8 A3 {* V4 i' G- ~    for movie_id in recommend_list[:20]:4 ]" P. r$ _; B( G
            from_user=[]" o/ b/ }5 M: T7 }4 c
            for user_id in items_movie[movie_id]:6 x+ ?8 ^- b  D" E
                if user_id in neighbors_id:. f% J( A7 L5 t7 D6 c+ G8 X$ ?
                    from_user.append(user_id)% [0 t2 C0 I: F( r! X
            rows.append([movies[movie_id][0],movies[movie_id][1],""])
    7 p" I; B- Q0 X3 ~/ l    table.add_rows(rows)! X  `2 J+ I  d! _, N4 P9 v
        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 & V( U- t0 X! p$ X, Y7 r' Y% d
    # -*- coding=utf-8 -*-& D6 A- P* O' o+ S

    ) l' M! a' g. f; vimport math

    3 e! N9 _7 p' _/ S5 V  m) k这是什么语言的程序?
    * b4 I0 v% Q: R7 y1 e) C
    回复

    使用道具 举报

    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-7-17 09:54 , Processed in 0.476160 second(s), 68 queries .

    回顶部