QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 5169|回复: 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
    本人在学校参加暑假培训,需要这个算法做题!求大神赐教,感激不尽$ J7 Q4 T; n& Y
    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 -*-
    8 @0 z0 I* y9 l8 z7 g2 L* _
    ! F1 H) O: f! S7 Y' ^import math
    : O9 O( f4 T0 \7 P) b" I& c- v7 I( ]import sys# {# k! x. ~+ i
    from texttable import Texttable
    0 C) H5 K) ]3 v* s9 o7 O
    # X' V2 M* L: s, \* G7 I# d0 ]* H
    #
    ) {1 n4 N" {% C, U6 A9 l#   使用 |A&B|/sqrt(|A || B |)计算余弦距离2 s8 \1 Z  r) Q
    #
    6 {' k# `5 r8 e1 v3 V#
    $ h: J8 n+ ~, g& J4 Y#
    ) K* R% ~4 a9 Z2 V  A( }def calcCosDistSpe(user1,user2):5 E4 G* k4 Y( k0 H4 e4 s- o+ K
        avg_x=0.0  d1 S4 l5 K, F( d0 l
        avg_y=0.0; q, H7 r% r9 W3 q
        for key in user1:' E  O" s* M$ R2 ^% i# L# A
            avg_x+=key[1]
    " h1 x9 c, y6 Z2 l    avg_x=avg_x/len(user1)
    # M7 V. \2 C* y# @* c  b9 F2 ]+ A    ; B# c; O7 \% f2 R1 u( i7 J
        for key in user2:
    . z7 [- m* `: _* L3 c        avg_y+=key[1]
    6 L, G3 E$ N- E* {( l2 k    avg_y=avg_y/len(user2)1 z5 c, W6 W2 a$ M" j6 Z, i( ~' F
        / S$ B2 O% O3 d! ?9 ~1 J0 c+ o
        u1_u2=0.0
    + p' v+ }) \6 G( }: X) D3 t* z    for key1 in user1:4 _+ ~1 M3 t6 O
            for key2 in user2:
    ! g/ i9 v# z5 y) k- {            if key1[1] > avg_x and key2[1]>avg_y and key1[0]==key2[0]:4 i. {. K: n1 ~0 C5 T: p  }
                    u1_u2+=1
    . w$ x' P- q2 _$ p5 M" V2 `/ t9 h    u1u2=len(user1)*len(user2)*1.0
    ! S, Z. ]4 J6 {3 M2 j% u    sx_sy=u1_u2/math.sqrt(u1u2)* U" q0 J- C6 O% y7 G: o. t
        return sx_sy' `6 ~" p' ~& Y( w  Y9 t

    , Z# b1 f' U% b! }1 o% A9 Y- s# d9 d7 T. x3 `: S/ ~. i
    #
    / A: }1 Z! G( b5 J#   计算余弦距离9 N0 p0 Q) K+ V0 R( e
    #  e: h; c0 L9 n( O' w% T2 r1 z
    #' ?! @" a3 P; X! S8 ^
    def calcCosDist(user1,user2):
    3 K8 c. W9 z% c5 ^: z: U    sum_x=0.0* ~+ E/ U$ ^' D/ x+ m. }; U0 k
        sum_y=0.0
    . m. g7 g# a( l/ P    sum_xy=0.0& F7 M: M5 h* P
        for key1 in user1:3 w" |. Q' [: y, }& U1 C( `. F
            for key2 in user2:* ^/ P; x1 N7 l3 g- N; g* Z2 z5 j$ S
                if key1[0]==key2[0] :% E% x5 u/ M) u
                    sum_xy+=key1[1]*key2[1]
    ) u0 b5 C. h7 T* |8 o/ I                sum_y+=key2[1]*key2[1]  a; b) A: `9 F+ @9 b
                    sum_x+=key1[1]*key1[1]
    ; F, z, v$ d3 o/ x7 J2 C: M   
    : y- {; W! R3 Y6 U    if sum_xy == 0.0 :( }$ x( s$ p- x+ l4 _% \, E! S
            return 02 L& T/ R; }- l  o7 u, w
        sx_sy=math.sqrt(sum_x*sum_y) ( v2 b$ f4 H& J" X* Q
        return sum_xy/sx_sy
    9 \8 g7 Y4 V+ S' J3 }' C' K2 G0 m# f0 O7 c! _8 g
    ( o$ c3 ^  r) s( J
    #
    # \; o+ s+ \+ r2 T3 m#2 N& M& d  k- b
    #   相似余弦距离% V5 b. n! B! W+ e
    #
    4 A- j7 R: H6 L, f% w#/ u" O% l: |3 z$ U
    #
    # q' g7 |5 C! s0 ddef calcSimlaryCosDist(user1,user2):$ X7 \; Q2 p: [
        sum_x=0.0
    # W; t3 I* K  \6 e. R; E8 v    sum_y=0.0# P3 T- H+ S" Q) B: c. d2 m3 e
        sum_xy=0.05 C0 c1 p' ?! w3 @% I0 \5 T
        avg_x=0.0# R. X& k9 w) _, S) l
        avg_y=0.0' r- f& T" P8 J, M
        for key in user1:
    % ~% K8 c- M" v" G  n( E% f- n        avg_x+=key[1]
    2 k$ l: B0 J. b; X' U: l" a    avg_x=avg_x/len(user1)$ E/ Q; S  r6 U: Z( B
        " Q3 w' {+ Q( O+ Z$ Y3 c
        for key in user2:4 h) Q1 l  a  n. t0 y. D
            avg_y+=key[1]5 Z7 x. z# G' U" @6 P$ P* e" \
        avg_y=avg_y/len(user2)% ^, X; W# r& |% h7 A0 R3 p( d' x8 k
        . P8 J4 e  j0 Z- s% g( |2 k
        for key1 in user1:
    ) f9 F* N6 Y4 F# N+ c8 F/ L        for key2 in user2:, {, b' P' _# A* l2 D/ ]6 `6 @
                if key1[0]==key2[0] :/ _5 h5 H! v9 Q+ U( u
                    sum_xy+=(key1[1]-avg_x)*(key2[1]-avg_y)
    0 A- N; m1 G5 t) @- }* s: m                sum_y+=(key2[1]-avg_y)*(key2[1]-avg_y)1 @' X/ N8 h3 a. S1 J2 m' s6 a, A
            sum_x+=(key1[1]-avg_x)*(key1[1]-avg_x)
    . V# l- n9 v' h6 A1 X8 J5 U   
    , N( V  W  O- R& U    if sum_xy == 0.0 :8 K# p9 L- K9 l' [% X
            return 0
    9 O* i2 o" h) X$ B    sx_sy=math.sqrt(sum_x*sum_y)
    9 u: T# h: i. K5 s# l- s3 o2 X    return sum_xy/sx_sy
    + ~+ g/ Q9 `. Q, a3 O- Z6 p    ) N& g9 P, ~- [0 f0 v5 }

    6 j$ t# n( Y/ g& N7 ^/ I& i#
    0 z9 a6 m2 c; O- ?) f#   读取文件
    ( R4 X* m3 J7 b0 @#7 H  |6 z& t# O! y2 R1 J% y
    #
    . W' o% [; `. }' U$ Kdef readFile(file_name):' y  b1 W0 r. \& ]: i8 n, U
        contents_lines=[]
    $ y) p: B' T' t! t2 `: u9 x9 d    f=open(file_name,"r")- A  o* u# n; x) P2 p# F
        contents_lines=f.readlines()
    0 u6 d3 p- Q( b# z    f.close()
    5 I& g+ I. l9 l  j  |% y/ J; z    return contents_lines
      Z' X* }# [! ^/ G$ Q6 \
    9 @/ {# u+ \. L, V7 {% h3 d2 t' [; R4 K

    ' E: J$ d2 W+ d8 S#9 w/ G1 |% D; |$ g
    #   解压rating信息,格式:用户id\t硬盘id\t用户rating\t时间
    5 k! D  E' A% h3 R7 G#   输入:数据集合: I) d1 _) W9 K+ K* k: O
    #   输出:已经解压的排名信息! \1 X9 f4 _' D8 R7 U+ O
    #
      D9 G4 F1 x( @, ~% O" tdef getRatingInformation(ratings):1 H: \9 k/ j) k' D# a( x7 D
        rates=[]8 f, G9 }" t1 V% U$ o% {5 W$ }
        for line in ratings:& a) }/ l- l) d! Z: f
            rate=line.split("\t")
    2 D5 {1 E8 n0 a6 b0 P) d, m" X        rates.append([int(rate[0]),int(rate[1]),int(rate[2])])8 N% h1 \9 R' s# |
        return rates0 E+ ~2 Y7 e4 k9 p* R

    ; L1 Z) O, h) y( Y% o8 i) ^
    : k% k4 F2 |1 ?6 F. y#
    6 y; q  ]9 \- w8 e7 \3 h5 T/ j#   生成用户评分的数据结构
    5 P$ d/ Z8 {% `9 ]  ?#   " j+ O/ V; S$ r  h3 p5 ^
    #   输入:所以数据 [[2,1,5],[2,4,2]...]& g" V% D% U% @& b; V) T
    #   输出:1.用户打分字典 2.电影字典
      z! V3 ]1 v5 x7 M1 Z7 ]#   使用字典,key是用户id,value是用户对电影的评价,
    ! W9 T  k3 c0 D& p, m# E2 v" [; K* W#   rate_dic[2]=[(1,5),(4,2)].... 表示用户2对电影1的评分是5,对电影4的评分是2& Q4 d( v1 l5 W# G" h
    #1 F5 x8 w+ L, m7 @) V* I* n% e8 j) W
    def createUserRankDic(rates):
    & T' }( D. S* e0 p( R% d' x    user_rate_dic={}) e" q, c  D1 f1 {! D
        item_to_user={}8 H/ i0 J4 p1 V* q6 T
        for i in rates:/ ?4 r- l8 [) z3 ^3 s% a& ]
            user_rank=(i[1],i[2])
    1 H7 Z( r# a. x# o: m        if i[0] in user_rate_dic:% A4 r# T3 l, Y" o2 z- `/ T( A
                user_rate_dic[i[0]].append(user_rank)/ x5 \& l  }8 c: w
            else:0 p4 K7 Q! f  e4 U0 Y. [" d  Y) W6 q1 n
                user_rate_dic[i[0]]=[user_rank]6 D5 Z) [6 M# R; Z
                
    : {8 k' W7 I# a# F4 W: a        if i[1] in item_to_user:
    9 L* y' b! K5 w' I            item_to_user[i[1]].append(i[0]), d) c9 B; m: T% v7 Z
            else:9 @; F0 t. a0 H
                item_to_user[i[1]]=[i[0]]
    % Q2 K* r0 x: t            4 c# i) r( Z3 ^+ p) e
        return user_rate_dic,item_to_user1 w! a. t  k5 I' O" G
    1 W) v- [% r3 L. D4 ^& p
    ' ]* H! h# v1 `6 |2 q/ G
    #
    ' @5 o: }8 J, I" w#   计算与指定用户最相近的邻居
    6 {% \9 z' u# F" H" j% U#   输入:指定用户ID,所以用户数据,所以物品数据7 k9 T' B. C2 o' i8 D) s3 x7 d( ~
    #   输出:与指定用户最相邻的邻居列表
    $ e* Q( m4 p0 z$ H7 Q# p% Q+ {#
    + G$ U* h2 r. F3 K2 Cdef calcNearestNeighbor(userid,users_dic,item_dic):
    . }: X/ Z/ r' R; r2 a" g9 l) j    neighbors=[]7 n! m1 s$ g3 ?0 O( a7 t
        #neighbors.append(userid)
    9 h0 c1 I' f; P5 F    for item in users_dic[userid]:% u  o' M8 O' y3 |
            for neighbor in item_dic[item[0]]:* Y: L4 R3 T! l7 q. E, O) A5 z7 x
                if neighbor != userid and neighbor not in neighbors:
    3 |' o1 c) R# @5 Y$ h7 f" I                neighbors.append(neighbor)& |8 F7 s7 [" l2 _) S, ~6 z4 r1 x
          ' z* B2 ]/ U; z# n
        neighbors_dist=[]% e. F  ~( j8 D7 L; e6 k
        for neighbor in neighbors:
      ^. F$ f- U8 u8 x" y5 t        dist=calcSimlaryCosDist(users_dic[userid],users_dic[neighbor])  #calcSimlaryCosDist  calcCosDist calcCosDistSpe
    $ {( \# \0 {3 {- a  f        neighbors_dist.append([dist,neighbor])' w+ E% i+ {6 _% p. V
        neighbors_dist.sort(reverse=True)/ a0 C( h; z$ V. ?- k7 a
        #print neighbors_dist7 ]& y$ }0 y9 s9 l7 J
        return  neighbors_dist
    5 O9 _; D* h2 v! V: L$ c# C: v+ ]% D) V: n- P/ l3 o
    9 L, B2 ~8 U: J5 l
    #
    % f3 O7 A8 Z  b' o$ ^#   使用UserFC进行推荐% o' s9 [& ?& e, `& ?: C
    #   输入:文件名,用户ID,邻居数量% ~+ \  H' `. o, S4 U3 ]- f. T
    #   输出:推荐的电影ID,输入用户的电影列表,电影对应用户的反序表,邻居列表
    : A/ l( v  Z: {5 e8 T  g; V#
    ' V! Y1 E6 v+ e' S: i9 Ndef recommendByUserFC(file_name,userid,k=5):
    1 Z$ J( |7 {1 z7 f0 Y9 z2 M   
    # k6 s9 k3 W7 n! A" X) {8 X    #读取文件数据  w: H3 K7 Y6 q+ g
        test_contents=readFile(file_name)1 D4 a/ i2 q5 G  M$ c2 `; @  \
       
    5 U; X, T* m9 L- Z+ j* F+ o+ ?# T! E    #文件数据格式化成二维数组 List[[用户id,电影id,电影评分]...] 9 w( C  T1 H7 T" }8 t7 n4 u0 X
        test_rates=getRatingInformation(test_contents)
    6 M6 R. t. {8 ^; Y* ?' X- p! P0 W6 {7 A    ; g: ~' q, D0 |& Y* @/ X
        #格式化成字典数据
    0 a8 B2 P( G) a4 J    #    1.用户字典:dic[用户id]=[(电影id,电影评分)...]/ C% Z  c# V7 L9 c/ r0 m9 k
        #    2.电影字典:dic[电影id]=[用户id1,用户id2...]% q0 Y7 t4 q9 y7 l9 e* L6 @
        test_dic,test_item_to_user=createUserRankDic(test_rates)/ Y+ ~4 u* k7 g  c3 b
        4 q0 U9 ?8 b6 j+ d
        #寻找邻居
    7 U$ O, E' r1 t8 h+ B  d/ O    neighbors=calcNearestNeighbor(userid,test_dic,test_item_to_user)[:k]( @! Z. A: ]- B! M6 I
            
    0 v  f- C+ Q- y( @4 c2 k    recommend_dic={}/ Q2 q  d/ b6 v$ x
        for neighbor in neighbors:
    ; C. S1 Z  `! y        neighbor_user_id=neighbor[1]1 U+ K! f, ^0 `1 w4 u
            movies=test_dic[neighbor_user_id]' N* a2 t) R  i- E% o8 |
            for movie in movies:0 O3 i, ^& H' \5 F9 T% T9 Z
                #print movie
    0 L- a4 ^3 M0 W* H( L4 j            if movie[0] not in recommend_dic:
    9 n$ n. \6 i7 P0 _, S                recommend_dic[movie[0]]=neighbor[0]6 m4 y( s# ?) j" s
                else:
    # Y5 J; y* ~  ?  U                recommend_dic[movie[0]]+=neighbor[0]# S# e0 ~3 i9 ?0 ]$ g( u3 d1 W
        #print len(recommend_dic)
    1 }& T" {# h3 F) l9 v4 Y8 m- w   
    9 y0 }3 H" q% b- R) |; L& }5 N3 I    #建立推荐列表' u. x3 }0 `+ ^
        recommend_list=[]
    # A- U+ _/ R" a% a' l    for key in recommend_dic:6 M/ Y, V1 Q& |
            #print key
    ; v" P# M: C2 U  o3 @3 Z$ ~  l4 {* u        recommend_list.append([recommend_dic[key],key])
    3 x' Y# v& j' h# E" |9 V# Y- c    + l+ h4 y9 D  P, T( s
        4 x6 Q+ C, P0 m! q2 x% Z) p
        recommend_list.sort(reverse=True)
    & c) a& w" K8 I$ P0 Q! M* ~' k    #print recommend_list2 [5 q: D: ^, N  I2 y$ v' h- @
        user_movies = [ i[0] for i in test_dic[userid]]
    5 n' Q3 l1 U/ F# \, t: O* n7 c% J; S# y  P
        return [i[1] for i in recommend_list],user_movies,test_item_to_user,neighbors
    ' o# B( _! J( J9 ]0 P3 G3 f0 A& q   
    . Z0 g8 B0 x" v/ B6 v1 D. w   
    . A, t( {1 O( s: u# C8 m0 A2 N  [8 M
    #. ?; a9 U* B( ?
    #! g  L4 C( M$ M; P5 L1 |% U1 H
    #   获取电影的列表0 s& f- l: B2 E& ~
    #
    & y# n+ ~4 r: B* p/ t; s#
    4 x. O1 e7 G* ~% a+ l4 q. Z' Y% A#& p' {' F5 G+ T' b* S' s; e3 e
    def getMoviesList(file_name):0 P8 r. E; O$ v/ I' x4 n6 Q
        #print sys.getdefaultencoding()
    % L- |& k5 s* |. _+ g    movies_contents=readFile(file_name)
    % ?6 q$ j, G' F3 I+ O; o% k. d    movies_info={}
    3 {2 P; x* l* S& @& [1 |: d, L  o    for movie in movies_contents:
    2 }: F4 H* s0 X1 `2 ]3 z/ K: T        movie_info=movie.split("|")
    5 a7 Y) [2 u4 C" O2 Q        movies_info[int(movie_info[0])]=movie_info[1:]
    . C% E& W) a' N3 z9 k& ]    return movies_info0 P: [- F6 t+ _  `3 S
        , r" \3 y! A$ H( n$ Q" }% Y
       
    ) D) x. j0 l" d   
    - g- |0 R, X- N' Q#主程序' N  }( I  t. l! s, c2 x
    #输入 : 测试数据集合
    9 H; g. M- H! Q! y; D+ `/ e+ uif __name__ == '__main__':
    $ K7 V( ]& ^& H! b( g! ?, k    reload(sys)
    ; B9 c7 W* U2 o" ?# E# b$ ^    sys.setdefaultencoding('utf-8')
    / x0 z: j% H! p5 A- s! C" U    movies=getMoviesList("/Users/wuyinghao/Downloads/ml-100k/u.item")
    7 W% L% q6 z* t    recommend_list,user_movie,items_movie,neighbors=recommendByUserFC("/Users/wuyinghao/Downloads/ml-100k/u.data",179,80)
    0 L0 z3 c, v. [: ~    neighbors_id=[ i[1] for i in neighbors]  @; _! T/ Q2 p- L' Q
        table = Texttable()
    6 R! q' e/ k* ]8 o9 Y+ q1 W2 p    table.set_deco(Texttable.HEADER)6 o2 j5 j+ [% N9 ]7 e6 ^3 F
        table.set_cols_dtype(['t',  # text
    & z: Z* }7 z  i( m+ s4 v" ~5 k                          't',  # float (decimal)5 ?$ `4 R$ C0 o  P% f
                              't']) # automatic; w& _5 Q  P+ M9 ?3 c
        table.set_cols_align(["l", "l", "l"])) e8 X6 y# ^" \- u4 d6 F- o
        rows=[]
    " f5 j, b& U" r5 f4 g" E- j" s/ {    rows.append([u"movie name",u"release", u"from userid"])* N% y/ {* [/ v+ @
        for movie_id in recommend_list[:20]:
    0 J8 y* r4 c5 }2 z1 K3 {        from_user=[]) O/ c& M) ^( P# X5 U5 F4 ]9 R4 B6 a
            for user_id in items_movie[movie_id]:2 C! y6 \+ g7 Y/ Z
                if user_id in neighbors_id:
    0 d- a5 n+ U- }( w3 O* l                from_user.append(user_id)! A# p( q: J( S$ M# B0 \0 |
            rows.append([movies[movie_id][0],movies[movie_id][1],""])! C) |. u( B6 Z, F4 E
        table.add_rows(rows)
    5 i" N% d% l/ E; }( H3 d/ Z+ n    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 , ]: n4 ^3 }: f7 E
    # -*- coding=utf-8 -*-
    ) W8 ^  J  I. a, `1 B  R
    , {6 s* j. n0 x8 G2 Cimport math

    : J. ^5 M1 C/ b$ d. R这是什么语言的程序?4 n+ p# G: |9 f! M) H* l
    回复

    使用道具 举报

    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, 2025-12-12 04:03 , Processed in 0.977371 second(s), 67 queries .

    回顶部