QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 5257|回复: 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
    本人在学校参加暑假培训,需要这个算法做题!求大神赐教,感激不尽" E" V' U. H2 z3 g0 P; A) ?
    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 -*-
    ) A( ]( y2 Z3 u& s5 O
    $ g1 R0 O, |( bimport math. l2 ~$ N3 o1 S! s7 U
    import sys6 w; v* g" Y1 ?) f' B+ l3 e  n8 r7 W
    from texttable import Texttable6 p' x: a0 P' \0 Y9 W* {
    7 p) ?9 ~5 S2 v
    ( i, O- K$ ~6 i; U1 ]$ T% m; x; a
    #" v% H/ v: q: E6 i/ m9 c/ S3 b, |
    #   使用 |A&B|/sqrt(|A || B |)计算余弦距离% k4 m. L6 s: a+ Y. N5 i
    #
    2 x- K& ]  r, {( O#, }+ u, y, a! ]% d
    #! \/ H/ `$ j9 M$ }, ^
    def calcCosDistSpe(user1,user2):
    ' F! v1 {. t% M, Q, A. x7 Q    avg_x=0.0
    & n2 J8 x% o1 o0 G& w/ R    avg_y=0.0
    5 e3 t( o- D' a1 K. S6 Y    for key in user1:
    8 X8 f/ _  c7 G        avg_x+=key[1]
    ! w/ c7 ^; u& J6 y0 H    avg_x=avg_x/len(user1)
    3 E( T1 G4 T4 X) r   
    2 n- v- ?2 R: b9 u7 j, I    for key in user2:- ]( Z, O* ^" f. F8 q6 F0 f
            avg_y+=key[1]' d0 x7 }# @0 h% I
        avg_y=avg_y/len(user2)/ D5 @$ ?& V/ p) H& B# [1 Q
        2 L3 L. H: N! A# n1 b! z4 B; @
        u1_u2=0.0
    , ]' V1 e# o, Y7 A    for key1 in user1:
    8 R. ~: ~& r6 D* d( W  p6 r1 S" S$ l- M        for key2 in user2:) v& q7 q5 _+ ?5 [0 g1 y
                if key1[1] > avg_x and key2[1]>avg_y and key1[0]==key2[0]:
    1 s' {: r/ B7 [8 u, `                u1_u2+=1
    ; k+ o  E3 L. _1 t& Y& U    u1u2=len(user1)*len(user2)*1.02 p0 w0 V7 I* r4 D+ \
        sx_sy=u1_u2/math.sqrt(u1u2)1 z# `, h4 Z6 G3 Q
        return sx_sy/ }# v7 I8 H: ^: |) v  o, f' j

    3 B2 y" U- D4 m+ E7 i+ i6 x7 y$ g0 U, q& t+ g6 y
    #7 A( y7 f5 o: Z* F5 {& v; o
    #   计算余弦距离
    ! B# c. C+ l. s6 }  l8 A#
    7 K/ b6 B4 R; A7 \#( D5 B: Y$ m* V# q2 X" o* o
    def calcCosDist(user1,user2):
    5 J( D2 J) m- M1 ^% L: z    sum_x=0.0
    ' n* U; `" ^8 U, G" j. M% n  e    sum_y=0.0. k+ |) ^  P) t% ^3 N! @
        sum_xy=0.0) d" g3 J" c+ F! u
        for key1 in user1:
    3 r: F# N+ e0 j7 w+ a        for key2 in user2:* u: e  R0 W! [! z' V
                if key1[0]==key2[0] :
    / j* @. u5 J3 @9 {3 W; y                sum_xy+=key1[1]*key2[1]
    6 u4 o, D, c; O0 E                sum_y+=key2[1]*key2[1]' j! |8 {5 n- }# p! A" c
                    sum_x+=key1[1]*key1[1]2 \. B6 d# X. P1 [7 l
        * l4 h% o. |, L1 C7 S( ?! H
        if sum_xy == 0.0 :
    / b, t0 B0 b* f        return 0: p3 N1 f7 G8 g6 g, _# A& x
        sx_sy=math.sqrt(sum_x*sum_y)   }) C1 n6 T0 y7 a8 w& S* A
        return sum_xy/sx_sy
      w5 R3 }! k% T0 c. A7 c" \$ ?
    ! I! t) b9 ?* p: v4 W! E' O8 Q2 r4 v
    9 v( `& g* s4 ]8 {" t( m#, i( z4 P! D% W
    #0 v' w" s# `! y4 o4 t& f! t
    #   相似余弦距离
    ; E6 [" _6 C  E#
    & F3 r+ ~4 T! g#
    3 b. o8 o3 W0 W) p7 Q# V0 F#/ |. m; X' _2 q; G
    def calcSimlaryCosDist(user1,user2):
    3 ~; S" V# o7 C: v) |) d' Q    sum_x=0.0
    ) R  ~; m( a4 L# P    sum_y=0.0. `5 {( X" G- ~# Z
        sum_xy=0.05 p, Z; p# x* h- f$ Q' ]+ Y0 B6 `
        avg_x=0.0& f: i2 z! A* U* k" q; o  c
        avg_y=0.0# r' C, H0 n$ |  S8 {- u
        for key in user1:# u1 ~' t5 @* I- ~0 Y" z
            avg_x+=key[1]
    ' w' f% F1 R* s! S8 }) p) \    avg_x=avg_x/len(user1)9 I% ?/ A- e- x; m7 M1 Z. N1 X
        0 F* ?; P6 Q5 I) K3 t% X, |2 O$ d
        for key in user2:
    6 Q: O/ {9 M! E# |0 z        avg_y+=key[1]
    8 V% x3 L; ~$ I9 `* C* Y    avg_y=avg_y/len(user2)
    , X; s7 w3 O% L* h    / G! m6 m, v2 \7 H* X' G; M* a
        for key1 in user1:: V0 e0 k/ n) [# J3 c4 O
            for key2 in user2:
    + L% g1 a; U+ O: `9 y, g. j# C            if key1[0]==key2[0] :
    2 y" R' [* y* J5 h2 N                sum_xy+=(key1[1]-avg_x)*(key2[1]-avg_y)
    * [! d( ~2 h, H9 V0 {                sum_y+=(key2[1]-avg_y)*(key2[1]-avg_y); P" S8 y$ r% K$ k# ^( ~
            sum_x+=(key1[1]-avg_x)*(key1[1]-avg_x)
    : X3 |4 \5 i# T   
    # x* K; t, I( I    if sum_xy == 0.0 :
    # ^6 @" B  ]& e        return 0# G5 j) J5 a6 h- r
        sx_sy=math.sqrt(sum_x*sum_y) ; ~) z( g4 J8 _5 `7 U& F
        return sum_xy/sx_sy
    3 [+ z: M8 V/ G) }5 ?) r8 A. Z    ) K5 q4 a& o4 }
    / r& q1 u! @6 q3 C; H3 N  A! V1 `7 T) C
    #: ]1 s3 S5 q# k( q
    #   读取文件. F1 B/ H% X9 t6 r
    #! T$ m9 N( T5 `- M; _$ l
    #
    ) W" q5 u9 C7 r  E' Z" \def readFile(file_name):
    ; F7 A& F* U7 z3 `! N" {    contents_lines=[]$ p$ X6 _- f; X0 ^) M7 T7 [
        f=open(file_name,"r"); k4 Q9 p& I( k1 I- R" I
        contents_lines=f.readlines()
    ! d9 ^  c) t7 v9 |# Z$ j  Y* P    f.close()3 H* r% F& \/ s/ j+ D4 J
        return contents_lines: k" ~1 k  i+ K8 c$ q  G

    2 g6 s9 C7 L! K0 v
    8 J2 w! U( E* n: P& O& ~3 J4 p" \6 b
    : n* d7 @2 w  e* k/ l2 B3 {#; {' Y; m/ ?0 v2 o
    #   解压rating信息,格式:用户id\t硬盘id\t用户rating\t时间5 ?' f% r$ ?% I' m7 s9 t
    #   输入:数据集合4 t9 D3 Q9 p8 @! Q9 g& y+ ~2 H1 s; B& c
    #   输出:已经解压的排名信息
    # A3 q+ q* p" e+ S& ~#
    . o6 |2 s/ a' ydef getRatingInformation(ratings):; L1 J. f4 p7 x. e9 l, X7 ?! v
        rates=[]0 ?! \# [, @( d1 z0 E$ a
        for line in ratings:
    + y( }, G8 x8 n5 W5 u        rate=line.split("\t")! O' c0 ]" B  z$ e
            rates.append([int(rate[0]),int(rate[1]),int(rate[2])])
    * w5 W4 C  D. E7 W" S. K    return rates
    , y. w8 T5 K8 ]0 Z, j+ R2 s; f* Z9 w6 t4 {! Q

    / X4 d6 f1 F: N$ ^" ]) e! U6 g' w- B#
    / R9 j: J4 n& ]% l#   生成用户评分的数据结构
    % U+ D9 d* v6 x1 l) H! Q#   7 g4 V1 F6 I! V$ _6 T( a
    #   输入:所以数据 [[2,1,5],[2,4,2]...]' i, q# |# R. Z& ~3 }
    #   输出:1.用户打分字典 2.电影字典
    9 Y( d$ S4 T- a" J2 h$ M#   使用字典,key是用户id,value是用户对电影的评价,
    # c8 j8 G* G& Q* |! P2 o& T( j#   rate_dic[2]=[(1,5),(4,2)].... 表示用户2对电影1的评分是5,对电影4的评分是2, q0 d" N5 L, l' V2 s$ J% F
    #
    6 L: d1 S; y8 {+ _3 a3 F! I/ {def createUserRankDic(rates):
    $ w4 K3 F3 x  {+ _. \6 \- y: ~    user_rate_dic={}
    ' K0 X; k3 Z& e; K: T% F    item_to_user={}
    1 d/ C6 l- w, z8 ?    for i in rates:
    : D" n, {- B5 @9 Z0 H, j! ^        user_rank=(i[1],i[2])/ ?  ^: G% l' K
            if i[0] in user_rate_dic:3 @5 ^4 Q) K- I) t
                user_rate_dic[i[0]].append(user_rank). T' f: K- m; A
            else:
    : m/ T0 W( y! e. V% D% l            user_rate_dic[i[0]]=[user_rank]5 R/ @' v+ v& M1 L. G8 h
                ( \: n* I( k1 D+ y
            if i[1] in item_to_user:
    4 R* ~! L3 D, ]( @- h            item_to_user[i[1]].append(i[0]), p, I! }7 Y; g) K3 k
            else:7 \" e- U0 Q6 }. @6 g6 G
                item_to_user[i[1]]=[i[0]], [$ I  E+ }) Y: b; s
                2 a# \0 @1 @0 n  ]. M" z+ a2 y) @
        return user_rate_dic,item_to_user3 E/ ]2 U0 \! @5 z
    - `6 e/ z; S. T! X/ c# h9 [& z
    7 v& |4 t* f/ A3 ^' q! ~9 i
    ## G1 ]! |; r. \" ^9 C
    #   计算与指定用户最相近的邻居, z/ H- x. j7 A
    #   输入:指定用户ID,所以用户数据,所以物品数据7 R2 [  W, a- i% Z0 ^
    #   输出:与指定用户最相邻的邻居列表
    7 j% n5 ~. ]8 |# T! [8 c* c% d#0 }& ?( j# u% a: k, J9 u/ m( h# u
    def calcNearestNeighbor(userid,users_dic,item_dic):
    : D) s! A$ j9 e  _6 w) x2 L9 |! z    neighbors=[]
    * l% i5 G1 v1 n+ F7 h( }    #neighbors.append(userid)
    : G% x6 ~1 d4 ^8 V    for item in users_dic[userid]:
    ; q7 s/ o  l! [# {- C        for neighbor in item_dic[item[0]]:
    9 q0 `5 A" @3 ~5 X0 b$ Q            if neighbor != userid and neighbor not in neighbors:
    * X& P& b/ ~/ c8 g                neighbors.append(neighbor)% S2 i; c2 g8 p
          2 s: n8 P( h$ R
        neighbors_dist=[]
    1 J$ q5 z8 @4 P    for neighbor in neighbors:  I2 Y" u: F# `( X
            dist=calcSimlaryCosDist(users_dic[userid],users_dic[neighbor])  #calcSimlaryCosDist  calcCosDist calcCosDistSpe3 J) N. b+ P- S
            neighbors_dist.append([dist,neighbor]): S2 L* m( P$ e$ f5 j) h
        neighbors_dist.sort(reverse=True)
    4 M* M9 x8 l  h% _    #print neighbors_dist) l( {! F% X' x# v0 X
        return  neighbors_dist* M  K' O8 u; Y, b: Z9 j) i! t* w
    ( H# ^7 ^" Y6 r3 ^$ G. q8 x
    2 b" G! s3 E6 Q" ?
    #
    4 S+ N: c% g1 A5 f# v1 M#   使用UserFC进行推荐
    3 L# m5 d$ i+ V. G7 u#   输入:文件名,用户ID,邻居数量  H7 j3 |, P2 m1 ?- h
    #   输出:推荐的电影ID,输入用户的电影列表,电影对应用户的反序表,邻居列表! p) |8 K# G8 ^: g
    #- D6 j5 ?* [* E5 A
    def recommendByUserFC(file_name,userid,k=5):9 G1 X% y! {2 L6 C* z" N) r7 a1 [
       
    - B0 k9 D+ a) |6 x1 k: S+ ?: L) z. x    #读取文件数据
    # m  X8 Y& j+ H    test_contents=readFile(file_name)
    5 m0 G& z0 y/ a$ s" T( I7 H! V    4 B; t# ?5 U- ~2 \# Z
        #文件数据格式化成二维数组 List[[用户id,电影id,电影评分]...] , k" A+ O: {  `% [! M, s+ u
        test_rates=getRatingInformation(test_contents)0 D( k) K: `: Y+ L
       
    4 q% G! H! O) \% F; [2 P; y: d    #格式化成字典数据 1 B- n% ]/ }+ a6 L% ?3 d
        #    1.用户字典:dic[用户id]=[(电影id,电影评分)...]
    9 ?8 e; U3 g0 `5 q6 c7 g8 Q    #    2.电影字典:dic[电影id]=[用户id1,用户id2...]
    9 }% ^7 J; S" Q: T# q, B    test_dic,test_item_to_user=createUserRankDic(test_rates)2 c' x; X% C5 G2 j7 m  T
       
    - v, Y' r" m; P( i6 C& R% J6 O+ N' |    #寻找邻居% {) v' E- h4 ]0 I- R
        neighbors=calcNearestNeighbor(userid,test_dic,test_item_to_user)[:k]
    + [, j7 ?, ]6 }& s2 S2 R  ^        " Y1 h& I7 m& n$ @: S  N6 l
        recommend_dic={}( S7 o1 N. h5 k2 s
        for neighbor in neighbors:- X2 R$ O6 p( j9 q
            neighbor_user_id=neighbor[1]
    0 N9 S5 z  L. U  G( `; q$ `& r- @        movies=test_dic[neighbor_user_id]
    2 J& B# w0 z3 {' j        for movie in movies:
    # }9 e! t% i4 d+ h  h            #print movie. ~& }& d$ o" q9 x% o- M
                if movie[0] not in recommend_dic:
    + j- h) I; M) H' G. t6 b6 j                recommend_dic[movie[0]]=neighbor[0]
    , S0 E- R: @- Z. N- l9 R            else:0 d. d- T0 X3 C! d$ b9 f. r
                    recommend_dic[movie[0]]+=neighbor[0]
    ( m" z* b: S+ @2 ^$ P    #print len(recommend_dic)9 F3 Q) a( P- W, P8 n* b; a( p
       
      @3 d: t6 b( Q1 b; r    #建立推荐列表
    4 p# L$ R/ M0 ~/ M    recommend_list=[]
    : S2 T' d3 w1 \    for key in recommend_dic:: L/ x5 ^1 ^( t2 i3 \
            #print key
    ; c! R/ u# R, {6 L4 m1 n; @        recommend_list.append([recommend_dic[key],key])
    % K( h: g: P" E4 a5 l2 k. R+ W9 B    " F  d; x) _# e& ~, [; b
       
    & k. X+ `! m( f* `% A* _+ u+ ?% T    recommend_list.sort(reverse=True)( E9 G1 e3 |' L
        #print recommend_list; }) f5 E. O- R0 V, X4 i
        user_movies = [ i[0] for i in test_dic[userid]]9 x! k) \! D2 w; J
    5 k5 N% Q- G6 @. r8 b9 v# [* _. ~
        return [i[1] for i in recommend_list],user_movies,test_item_to_user,neighbors4 G5 d' F6 x$ v: `! Y) V
       
    : K9 B* q% e3 q   
    * ^9 _2 S6 |% M, Q6 P( ^1 F1 d. l! S; R1 a) G- t. K9 Z+ u
    #
    , D3 [7 D1 g2 E0 S#
    1 s: b3 E7 P+ v9 I5 r) V; w! _5 X#   获取电影的列表
    4 }9 j; E+ u- L3 V: P6 x#
    ' ^5 p$ H. I8 q: A1 B#, D2 s! \" M  a, g5 K' o6 g
    #
    - G0 u) a( K. z/ O7 A5 o% Edef getMoviesList(file_name):
    : t4 y/ i2 @& V/ u1 |# D    #print sys.getdefaultencoding()
    8 q" ]: a- w* x& e: i    movies_contents=readFile(file_name)
    9 m0 G8 V. V$ e5 U. ]8 R8 x    movies_info={}" l9 S1 O1 D' C& j) W5 ^6 O1 f. S
        for movie in movies_contents:# N, ]- `9 z# j/ J2 |
            movie_info=movie.split("|")
    8 m( G1 v* C& m1 s; a- @        movies_info[int(movie_info[0])]=movie_info[1:]2 @5 F. T+ w! ~
        return movies_info4 @/ W; C( x+ Z/ l- i3 V" ~
       
      M1 \; a! e6 T0 X3 P    + f5 k, v% c; w% Z
        1 P3 b" H3 f4 r
    #主程序
    ! |0 M% |# N2 [& R2 W#输入 : 测试数据集合
    ' F5 `4 y+ E, n) Bif __name__ == '__main__':) y0 D5 q0 }: m0 |3 b4 Y8 C' ]& C! r
        reload(sys)% w+ A2 G9 W8 K' O3 P; e
        sys.setdefaultencoding('utf-8')
    / ^$ d& X! n& v    movies=getMoviesList("/Users/wuyinghao/Downloads/ml-100k/u.item")
    & t1 Y# T' X4 U/ D- L    recommend_list,user_movie,items_movie,neighbors=recommendByUserFC("/Users/wuyinghao/Downloads/ml-100k/u.data",179,80)
    / {5 `! x) d$ A" M; _. s+ H    neighbors_id=[ i[1] for i in neighbors]
    - ?3 e+ R6 a* Z. r3 R4 [    table = Texttable()
      Y  F$ @# x8 u2 u    table.set_deco(Texttable.HEADER)
    6 `  V: N5 i: O! v- c    table.set_cols_dtype(['t',  # text $ n: d+ M# h4 `4 B! g
                              't',  # float (decimal)/ f: f- P' A4 Z6 v' W/ d0 z' O% u
                              't']) # automatic
    : r# E4 y7 k3 L% I6 W! ?1 W    table.set_cols_align(["l", "l", "l"])
    ' W% W& E1 r& V2 {0 d/ }    rows=[]
    7 c* |8 s+ R" W. v/ p, i  M    rows.append([u"movie name",u"release", u"from userid"])
    ! @$ `6 V" _; U3 f3 }    for movie_id in recommend_list[:20]:/ K* }9 b" r9 F0 i8 C
            from_user=[]/ W) |4 P# g6 ~8 g2 _* w
            for user_id in items_movie[movie_id]:( A& s/ X+ {# a) x; O" G& O
                if user_id in neighbors_id:# ]5 S3 v2 d# `0 w
                    from_user.append(user_id)3 y& T' t5 H; W/ C# t2 h
            rows.append([movies[movie_id][0],movies[movie_id][1],""])
    - \, y5 p! V2 g    table.add_rows(rows)
    ) d7 V' a3 d2 B    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 " ~& ?4 t$ K8 g) b. I; M8 S2 c
    # -*- coding=utf-8 -*-
    + u; _% E* T; z+ ?9 K$ b$ S: z+ c9 m! H2 M, B: X7 Z0 ^8 p, C4 W
    import math
    ( e# c4 z! S' c+ H
    这是什么语言的程序?
    5 W! A, c% J. r; w
    回复

    使用道具 举报

    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-4-17 01:50 , Processed in 0.452284 second(s), 68 queries .

    回顶部