QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 5391|回复: 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 I& R' W5 E/ t0 Q( O
    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 -*-- Z1 m0 j8 j; u6 G
    $ B0 b, X8 [( b' B  Y
    import math5 k, C0 E$ |+ `; [/ {
    import sys
    * g+ T# x4 g' {from texttable import Texttable# W0 L- \) P' j5 o

      b  V! _# U$ y$ ^: \* S; L  u- a8 {" n! d
    #
    ; D3 G% {* X# e7 i. h% D#   使用 |A&B|/sqrt(|A || B |)计算余弦距离
    4 S; K1 g  w, P9 r0 z5 ^#
    8 X) E, H; D; I#6 M( x* B0 V" e
    #
    + i! b7 y/ v+ ~+ Q0 ldef calcCosDistSpe(user1,user2):
    : z% \, O$ s2 e, ^    avg_x=0.0& g/ K1 h/ Y$ G" o* ^% t% R: o
        avg_y=0.0
    $ r2 F6 W" |, S  w8 b, C" w    for key in user1:
    & V+ j9 L7 N1 U! H/ n8 q7 g        avg_x+=key[1]
    ' \' E% O+ m  B7 Z1 @    avg_x=avg_x/len(user1)
    0 l  }. c$ _( G/ d    0 W) D9 J" |7 y/ m' y4 c' z
        for key in user2:& }# d8 c3 Q; [5 `- }+ M
            avg_y+=key[1]8 N1 z- ?, h& A  H: p1 T& l' e& T
        avg_y=avg_y/len(user2)3 \1 {4 N7 S3 u- a1 U
       
    0 R& ?. g% u1 }, l- i, E    u1_u2=0.0  U* _4 e, }2 d/ k1 P; W! J
        for key1 in user1:
    6 R. }$ F6 w/ y+ Y9 b  h        for key2 in user2:
    * @  Q- o! Z8 D3 c% I4 p            if key1[1] > avg_x and key2[1]>avg_y and key1[0]==key2[0]:; e1 f4 v9 Q. H/ O# C( d
                    u1_u2+=16 `- O& W3 ^" }
        u1u2=len(user1)*len(user2)*1.0
    1 O; L4 e6 U: y2 s3 i0 J# O) y    sx_sy=u1_u2/math.sqrt(u1u2)
    " \+ I( n( p5 `3 e    return sx_sy; E) M+ E% Q; X+ S+ X
    7 n1 P" W0 E5 k' o+ q' c6 [1 U
    % f5 p" X# Z) V# \6 J; x( c* F
    #2 t5 \5 [- r( O) J4 a8 y& t; t
    #   计算余弦距离3 A) b6 z2 a  a
    #& W  @$ x& E9 r' I& R% H) L4 O
    #" u' y4 I( [3 W, `* J8 w1 @8 H
    def calcCosDist(user1,user2):
    2 |6 j: T) w8 X+ O    sum_x=0.0
    * Z7 S5 x: W% W) W) U    sum_y=0.0
    ( V  Y) Y" R/ C# z+ L5 a0 B& w    sum_xy=0.0
    1 P$ r+ P" z0 `4 `$ p    for key1 in user1:
    + E* Y9 q3 a& J        for key2 in user2:
    ; N2 y0 {  X2 K/ m. g- J* q            if key1[0]==key2[0] :5 p# `- a# `! i, ?  @& f3 V4 g
                    sum_xy+=key1[1]*key2[1]4 y0 L! [7 C8 z; H  n" V
                    sum_y+=key2[1]*key2[1]0 ~" f! K9 `9 ~% k/ O
                    sum_x+=key1[1]*key1[1]2 e8 `# H) O4 j, z* l
       
    8 f9 N2 ]) r) y: q- f( s, K    if sum_xy == 0.0 :
    / H5 o" w, `. x# ^- v" q4 I* x# E  \        return 0
    # m) y$ O8 u* L! b$ f+ V; J    sx_sy=math.sqrt(sum_x*sum_y) % v) X/ H5 j8 H# f
        return sum_xy/sx_sy1 B! k1 T* \1 |2 t. \* g

    6 A4 V- ?0 `% x9 R& o" Q* Q- Z; n; k4 B- L# [
    #: \: w1 F. N7 \% L; z. Z) f
    #
    0 a; P0 L* j6 b& r" c#   相似余弦距离* D' |9 Q# ~6 H) ?  U& D% V
    #
    1 V; j( o# P; x7 ], S% c3 r; `- W: V2 G#
    8 Y/ q+ ~- I3 \. {$ I- {* ~( z#0 ^. G0 E6 @1 t/ I2 ~5 h0 b
    def calcSimlaryCosDist(user1,user2):5 {- W# z7 G; Q+ _; A
        sum_x=0.05 O, h+ h6 u  I3 f6 h! k
        sum_y=0.0
    . n, S+ E( e  E+ B! u& S    sum_xy=0.0/ \! [2 a: D. m4 ^
        avg_x=0.0
    ; {( d0 Q- E6 e) z" f& f    avg_y=0.0! I0 h4 P# e  Z& C- r; a, j! P
        for key in user1:
    3 r0 }, I) B* l# g% o        avg_x+=key[1]5 L  o0 X, [- M6 s
        avg_x=avg_x/len(user1)
    7 c; ?5 u8 `* q) ?* V: G' N   
    / C# O6 h. c  ~/ [5 H2 B- ]* k4 L    for key in user2:8 a  N/ w, R% B0 l. J' ^
            avg_y+=key[1]7 @8 c6 u) k( u8 g
        avg_y=avg_y/len(user2)
    % r! N+ ?7 H9 x: ?   
    1 C& v2 A  u7 V5 |; T8 X    for key1 in user1:
    8 ^( K2 [% w" J& B- {' r4 O" n        for key2 in user2:; L. d0 z$ L$ P# C& D! O) K
                if key1[0]==key2[0] :
    + \6 M* L: O% h! w; Y8 d                sum_xy+=(key1[1]-avg_x)*(key2[1]-avg_y)
    1 f$ U' S0 w9 c+ `                sum_y+=(key2[1]-avg_y)*(key2[1]-avg_y), u! d: v/ ^% Q5 `
            sum_x+=(key1[1]-avg_x)*(key1[1]-avg_x)
    & Y4 r5 y+ g' ^5 }$ J2 e    ; F  {  B* t& z& W- ]# ]
        if sum_xy == 0.0 :
    # ^" k# Z: A1 ^        return 0
    3 l, z% {4 i" U, o    sx_sy=math.sqrt(sum_x*sum_y) , E+ l2 d/ v  M1 f- q5 i+ q9 |( Y, h
        return sum_xy/sx_sy7 C8 r- p( t/ c
        2 l' s! f% B7 M& e+ _( }4 c

    # E: }% k) r- b& R2 [: N#
    . w4 ~2 [: P! f#   读取文件; o8 ]8 `3 V3 `3 l9 `
    #; C. b- `6 t% U! K( |
    #
    ' ?; t8 ~  L! p' L# ^% b3 Hdef readFile(file_name):
    ' Q  u# {1 n) |+ _$ E4 {    contents_lines=[]
    7 a9 g% q' u& i) S) h8 q    f=open(file_name,"r")
    ! y+ p! c" s7 a    contents_lines=f.readlines()
    2 G6 x: l, s+ q5 o; I% v" {    f.close()
    ; Z3 p( O4 b! Q( B    return contents_lines" g( V% j- h: D$ P/ F

    * _: {3 _& i- Z% E0 I
    1 b3 B& z$ N5 l; u6 C) B- @! O- f/ K
    #
    - k  q7 N" M& D8 T#   解压rating信息,格式:用户id\t硬盘id\t用户rating\t时间
    ( s6 c9 j7 R1 A) @#   输入:数据集合  ]2 Q8 V. Z% i( V  h
    #   输出:已经解压的排名信息2 `1 h- |( o3 l3 u5 r0 Q
    #
    5 ~4 z5 e$ R0 Idef getRatingInformation(ratings):
    ! c. H9 l' |9 P! W: @  p    rates=[]
      G- O) D+ Z+ x  v5 c8 ^    for line in ratings:
    ' s" z7 T- X" B9 S4 ?. p, n+ V        rate=line.split("\t")$ j! |& y. W* ^4 n% L9 L
            rates.append([int(rate[0]),int(rate[1]),int(rate[2])])% b# U0 m7 {' `/ k* t' r' U
        return rates
    , O& g, n; {' r- @5 `7 Y+ Z; t: i$ L- _! Q

    # K. P- Y+ _* _/ L" g: ~2 ^* O# o#
    5 U% ^  U5 Z* N: t3 f- f#   生成用户评分的数据结构8 P  z5 B. m0 z% l* T/ x  S' X
    #   
    2 g! ]! i7 @% k#   输入:所以数据 [[2,1,5],[2,4,2]...]
    4 [* X4 ?$ I, W0 v$ S  x#   输出:1.用户打分字典 2.电影字典
    , N! {" A+ J; E#   使用字典,key是用户id,value是用户对电影的评价,$ g: y9 }; ?4 K$ R+ U; S& D3 u
    #   rate_dic[2]=[(1,5),(4,2)].... 表示用户2对电影1的评分是5,对电影4的评分是2
    ! a$ _: K5 ?! i! r1 _* i/ q4 h#
    8 F" b. z9 v% S- z, E! Idef createUserRankDic(rates):* J  `) X' ~& k) F, a
        user_rate_dic={}& K) _# y' C+ z  @0 z
        item_to_user={}1 W" K/ Z; J- q% W  s7 X' Z: ~, Y
        for i in rates:
    $ l1 R; v  m8 n8 p7 M% Z0 t+ `        user_rank=(i[1],i[2])
    8 J: z+ `% N" d. e        if i[0] in user_rate_dic:3 ~4 U  F  |; S% h3 W
                user_rate_dic[i[0]].append(user_rank)
    " c4 a1 |* Z& J5 a) q        else:# G1 B' J# U( i1 v
                user_rate_dic[i[0]]=[user_rank]& [4 G8 o; N% l8 @  Q1 N) \
                ( v* g/ W: l2 b
            if i[1] in item_to_user:
      M# n2 ~  \$ o+ S: c            item_to_user[i[1]].append(i[0])! B; S+ ?0 r- H# `3 _
            else:' H9 M: j7 d6 L* x1 q6 ~
                item_to_user[i[1]]=[i[0]]9 n3 k0 ?# |4 Q1 b1 c0 a) X( l
                3 n) u3 y  @! i1 b$ B
        return user_rate_dic,item_to_user( N: n+ ]9 e: y2 C, }

    * q5 H% _$ m, U9 x9 C* b4 {% f4 X0 ^. D8 p3 }. P
    #3 z5 f+ U) A3 O) k! V" w
    #   计算与指定用户最相近的邻居; s$ Z, u: q% f4 @0 ]. v- h: s
    #   输入:指定用户ID,所以用户数据,所以物品数据/ N% E. Q% K8 }/ ]. X
    #   输出:与指定用户最相邻的邻居列表
    . n6 V/ L6 _! A, b7 G* c#
    8 r" w0 m+ f2 @( bdef calcNearestNeighbor(userid,users_dic,item_dic):
    , |+ t$ C1 Q2 r! h( K    neighbors=[]
    0 C6 e: |. v. c% w; w    #neighbors.append(userid)
    ) W! C2 x8 K4 _& Y) K: r' j- Y+ A    for item in users_dic[userid]:9 f& q! i; H! W7 L$ B
            for neighbor in item_dic[item[0]]:
    - @: X; e; }1 {; n  }  h            if neighbor != userid and neighbor not in neighbors:
    2 f* o( J, s, r; R8 |/ c5 X* Z                neighbors.append(neighbor)
    . E5 }- y. _2 d3 b      $ ]' q6 S" ]. l+ e3 ]! U
        neighbors_dist=[]
    ( @5 f/ a2 D' x- f7 Z4 ^- V    for neighbor in neighbors:
    & r  ~. K( f! Z, E        dist=calcSimlaryCosDist(users_dic[userid],users_dic[neighbor])  #calcSimlaryCosDist  calcCosDist calcCosDistSpe9 r0 ]9 z& {) w+ `
            neighbors_dist.append([dist,neighbor])
    + ?+ ]9 ~$ L; U( t; N0 E) c& O' Z* g    neighbors_dist.sort(reverse=True)" p. E5 K; m1 P$ x% @% a  R; w& k
        #print neighbors_dist
    2 r1 P7 F" h4 S  C    return  neighbors_dist
      O# g: h2 p' ?4 f% Y7 k0 W9 N& {, G0 C: H& k* N

    # b" h" e- R% p- P0 L/ Q2 D% a#+ u8 x1 i" h5 S1 H
    #   使用UserFC进行推荐5 I4 M) p$ v/ w
    #   输入:文件名,用户ID,邻居数量
    ' T( E+ E3 t" Q; n& D#   输出:推荐的电影ID,输入用户的电影列表,电影对应用户的反序表,邻居列表
    7 q/ f+ ?* T1 H2 J9 ~#3 V$ C1 l8 y9 _0 X+ j) v
    def recommendByUserFC(file_name,userid,k=5):
    . B7 j2 p  [+ Q2 K1 z$ [   
    - p0 T7 `: [; }+ T) R    #读取文件数据
    5 @6 g. Z# a( j7 c- z3 y$ R& I* R    test_contents=readFile(file_name)
    9 O) H# E' H" J9 N& x' e  r( q   
    1 X3 i3 k* n2 C' B# m    #文件数据格式化成二维数组 List[[用户id,电影id,电影评分]...] $ F/ f. O" J% g" {3 j
        test_rates=getRatingInformation(test_contents)
    6 \5 E/ l' {# \, h- s5 v9 g$ W6 O* n   
    3 g* h. E# a( {+ q. x, g: X( w  V    #格式化成字典数据 / L& A6 u9 l4 G" V- T
        #    1.用户字典:dic[用户id]=[(电影id,电影评分)...]
    % O8 Z5 Y5 }5 h4 V0 }1 P    #    2.电影字典:dic[电影id]=[用户id1,用户id2...]
    : u  r+ a  d9 U$ I$ \5 h- B    test_dic,test_item_to_user=createUserRankDic(test_rates)
    . G2 \/ z* f# t! X- ]9 M2 o   
    $ h) G. _, z8 Z* ?: X4 u. f* r6 b    #寻找邻居
    . F5 V$ Q) I" L" j  R    neighbors=calcNearestNeighbor(userid,test_dic,test_item_to_user)[:k]
    6 e* A& q! _# M        
    - X: J0 @* I) F% I) H  m: [( Q8 [    recommend_dic={}$ l0 n. p" P. C# D! \- V0 g+ {
        for neighbor in neighbors:5 g' a8 Q1 w- G1 }0 y# X: [, O6 C
            neighbor_user_id=neighbor[1]/ H- t# ~; h3 L0 y: Z0 E
            movies=test_dic[neighbor_user_id]
    ' H+ M  m, l( L; Y3 U& n        for movie in movies:
    $ _* e7 j" d9 J1 p7 K            #print movie" \( q) m- D* D& C0 p- P# ]6 p
                if movie[0] not in recommend_dic:3 Q3 m2 b2 G3 W2 r5 P
                    recommend_dic[movie[0]]=neighbor[0]
    * B: n# o4 Q3 \3 {5 I; d$ ~3 @. ^+ o            else:
    ( i  r  u  ~5 H" M                recommend_dic[movie[0]]+=neighbor[0]5 Q0 l% h0 E6 A( Z2 t
        #print len(recommend_dic)
    4 L$ ]# m1 g1 b    + O, {! m& M7 V+ p( [( X0 U
        #建立推荐列表
    : [2 z3 r0 J0 E( b7 w0 \& d    recommend_list=[]3 p* q  O2 [9 {1 E# U& f1 k( v6 ]0 F. K
        for key in recommend_dic:
    0 O$ e+ C0 A1 F        #print key' [' x7 _& p) f
            recommend_list.append([recommend_dic[key],key])# u5 t: ~5 I* Y/ |% W& b& }
        : K& L0 B9 {8 m7 H" [( I) D0 V- ~
        " ]+ R+ l3 p6 {" t
        recommend_list.sort(reverse=True)
    3 B  B  [6 h# G1 X6 C" M    #print recommend_list
    7 E5 a' u$ m9 p3 e+ l% C8 X1 R    user_movies = [ i[0] for i in test_dic[userid]]
    2 Q4 ~* ?) g9 ]& @4 m, {+ O
    3 c. C5 X8 B: R8 i4 U# L% e    return [i[1] for i in recommend_list],user_movies,test_item_to_user,neighbors
    0 X' @8 U* c7 f1 v   
    : R3 e8 a+ Y0 x, E9 `8 u7 G    : {, _, R7 s5 H% j; M+ q

    6 @5 }0 Z& K# }$ p) c! f2 C#
    - H- f) A: D3 X6 `#+ \5 y* E2 A# u) a
    #   获取电影的列表9 H% l2 x7 u! _( j
    #
    - a+ P- B+ J+ x: n( C( m& R  a#% a: l9 ?  @- e  ^2 z% Z
    #
    " n5 a5 r& y( Xdef getMoviesList(file_name):
    7 B7 [: z& ?/ f7 ~% L  |7 l0 l    #print sys.getdefaultencoding()
    - W: m# l  f6 s9 D6 I1 T9 f    movies_contents=readFile(file_name)
    - G/ b! e& n3 @9 X    movies_info={}* a3 Q# J. h& @. b2 p9 O
        for movie in movies_contents:0 w) X+ L1 Q$ e- ~: _
            movie_info=movie.split("|")* [; }& ]2 u' X& D# G4 i
            movies_info[int(movie_info[0])]=movie_info[1:]
    : r: C: h- S3 n7 @. A    return movies_info' z' m: G/ J; {$ v1 d) O3 _
       
    - V+ @) N, w' h& M6 y   
    8 {$ x. R( t  k    5 [% g" u' w+ o
    #主程序+ E/ G( s, u* Y$ M- m/ N
    #输入 : 测试数据集合6 }; L4 N8 o/ f0 R2 W$ B% `
    if __name__ == '__main__':3 z7 G. k: f$ e1 M8 x7 r( z5 N/ O
        reload(sys)7 U! {2 x: [: S0 s' _5 m
        sys.setdefaultencoding('utf-8')
    6 P' E$ ?6 P3 {. r) R    movies=getMoviesList("/Users/wuyinghao/Downloads/ml-100k/u.item")
    * a8 u  G8 n2 Y9 W3 f' Y    recommend_list,user_movie,items_movie,neighbors=recommendByUserFC("/Users/wuyinghao/Downloads/ml-100k/u.data",179,80)
    8 h9 j4 @$ r' n7 d    neighbors_id=[ i[1] for i in neighbors]$ p1 Y% X1 r) G' ^
        table = Texttable()
    $ j# ~( h, \+ X0 I    table.set_deco(Texttable.HEADER)$ u  X3 T9 o) m0 M
        table.set_cols_dtype(['t',  # text ) x2 _! H& t* W2 g$ I
                              't',  # float (decimal)
      b8 L  Z0 l7 b2 i* P. R                          't']) # automatic6 q7 K" H. F. Y2 b, m/ k
        table.set_cols_align(["l", "l", "l"])& Y1 m# a; ^/ R5 ^0 H9 Z/ ~9 k6 S
        rows=[]% J! {, O6 F5 E9 B4 @+ K
        rows.append([u"movie name",u"release", u"from userid"])7 m- w& `6 ]6 l3 M6 u5 ^
        for movie_id in recommend_list[:20]:
    ) d1 E6 D0 T# n        from_user=[]2 i$ V/ r/ u4 t0 D# G( x
            for user_id in items_movie[movie_id]:
    & L$ F4 h  M* D7 w! v4 `% {1 y1 I            if user_id in neighbors_id:
    1 p3 T3 i% c+ s0 m2 x) _, E                from_user.append(user_id); C* Q% o3 @- k' e5 J
            rows.append([movies[movie_id][0],movies[movie_id][1],""])3 g& R5 ]. m/ o- `
        table.add_rows(rows)( _. N+ I+ k+ }  Z9 ]
        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" R( n; B  L9 q" t* I
    # -*- coding=utf-8 -*-
    & ^4 a$ ^: K5 m/ q/ h& f' a
    1 U0 S# m* O9 E7 n9 mimport math

    5 s# w6 n0 d8 R6 R3 X' E4 p这是什么语言的程序?
    0 M5 e3 U! x6 D
    回复

    使用道具 举报

    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 19:21 , Processed in 0.464656 second(s), 68 queries .

    回顶部