QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 5287|回复: 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
    本人在学校参加暑假培训,需要这个算法做题!求大神赐教,感激不尽
    9 v& k& R& L% ~% a0 U
    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& s0 k1 F( L, Z" ^5 v( x3 m2 q

    3 G2 x: t6 i' P3 t% vimport math8 m) ^# P' J: R+ i% S
    import sys' d# V. i; {3 n- A
    from texttable import Texttable9 x: H6 Q; z6 l6 [/ b2 z6 A' x

    # ~# f, u# a3 R! \! A& G% _2 j# b  i" H4 Y
    #
    4 M7 k+ K. Z0 P5 m* {#   使用 |A&B|/sqrt(|A || B |)计算余弦距离
    9 Y8 j( U0 n7 Q* n; P6 T8 A; d#0 B7 j% j2 j# {0 w: ~
    #! l5 |& S+ t; m
    #
    5 p2 P+ @2 j5 z  jdef calcCosDistSpe(user1,user2):4 V* }( q( d: ^9 ~  p) ?' L
        avg_x=0.0
    8 z" j$ U2 X' Z' _    avg_y=0.0
    7 V/ V+ N" J! J6 H, r    for key in user1:
    ) A- l0 w. k6 S  m$ _$ f        avg_x+=key[1]
    & O' X2 n- D) F" \  [, }' j    avg_x=avg_x/len(user1), N' A. e* y% q
       
    4 w1 R" t- N6 m* p    for key in user2:. [+ q# n0 Z! ^" [6 D6 G: U
            avg_y+=key[1], _2 A, H/ \& L  z. v7 z; B
        avg_y=avg_y/len(user2)
    5 f1 i) I' l1 X5 j1 |0 m6 m    ) E$ L. L6 L( d2 T+ E
        u1_u2=0.0
    7 K3 Y% i9 ]+ ]; |    for key1 in user1:
    " x/ m. i) j+ \        for key2 in user2:
    3 E( K2 e$ \4 O: ~0 p, [! u            if key1[1] > avg_x and key2[1]>avg_y and key1[0]==key2[0]:
    ! Z6 Y  Q2 p% l                u1_u2+=1
    ' G% X9 U- I# f9 a; t5 S& i( {0 j    u1u2=len(user1)*len(user2)*1.0
    / w9 M+ r$ t4 T  c7 |* k    sx_sy=u1_u2/math.sqrt(u1u2)
    6 G4 N! w5 R7 h    return sx_sy; N0 l, b4 _: d+ F7 ~3 M$ \
    " f& _) H: ^& ~4 B! F

    & s7 h: {& T9 |: u# b( L#0 c( J1 J& @+ ~
    #   计算余弦距离: A- a8 N, g$ v4 H! x9 b8 t- G
    #8 x8 u+ c3 B  e! J5 c  P/ _
    #
    4 v$ H7 h9 a. f0 s# o0 [- o) Ldef calcCosDist(user1,user2):
    3 s% @( m! m3 e5 E, B' k! ]    sum_x=0.0
    * p; g( y( F' c' y, z, M    sum_y=0.0
    # a- [5 X0 Y; m; l' ~    sum_xy=0.0
    2 G# S& m$ r3 L) h1 ?8 D    for key1 in user1:' K& F) G7 E1 C# i5 W2 k
            for key2 in user2:
    8 M5 S6 i" |# |0 k* G9 q! j1 j0 H            if key1[0]==key2[0] :
    ! k8 S1 V; r: e3 s/ T$ N" f                sum_xy+=key1[1]*key2[1]4 X& W* {7 H6 @3 F& G
                    sum_y+=key2[1]*key2[1]! ^' s/ `( @$ A9 x+ m5 {6 \
                    sum_x+=key1[1]*key1[1]+ _- y# B4 k$ J2 ~) N
        ( @% |+ X; n4 K5 Q
        if sum_xy == 0.0 :( Z& m+ ]( H. l* s$ f. X' d: {
            return 0, Z" T& b6 Z, C; u' I9 I0 H% F
        sx_sy=math.sqrt(sum_x*sum_y)
    4 [) e8 p& O- `7 S# v( E9 Y# O    return sum_xy/sx_sy# X% A% @# y3 M

    ) \; M: K% i6 @9 V. x7 e- |- p0 w7 g& o8 M
    #
    - s) R' z9 o6 T8 b" W' h0 Y#- Z4 l1 i' Y  N% {% y  [, o. D
    #   相似余弦距离1 s) R( {! ^9 B; s
    #
    1 }( d5 d, E+ c# x#
    , v4 a6 ?- Z5 i, }: S#
    ! ?; ~0 |4 s1 n% z" @def calcSimlaryCosDist(user1,user2):
    ( e, i5 A7 L+ \* \  u! n% N! N    sum_x=0.0
    , x2 l; i$ f. @4 q$ ^    sum_y=0.06 Y- G4 D3 N+ r# |! l& A9 S
        sum_xy=0.0
    : Y0 _! S, g" m2 v" {& U    avg_x=0.0
    0 P7 \! d; `3 w) u- u    avg_y=0.0
    ( C( o$ M0 l* }    for key in user1:
    8 o/ f2 ]8 T# ?" T2 K* [! K" y        avg_x+=key[1]5 F& w0 o) K2 u6 z
        avg_x=avg_x/len(user1): O3 ^# W" L" [2 t" `6 |( q& ~
        7 r/ ^7 e. I( f. x
        for key in user2:
    6 R: T2 `5 e9 X        avg_y+=key[1]9 V9 {$ X1 ]' C
        avg_y=avg_y/len(user2)
    9 b5 B- t: S" E3 ]: i    $ I# ~5 M$ a, _$ f
        for key1 in user1:
    5 |5 {$ Y( g; y" C        for key2 in user2:" N3 O6 @, D! E
                if key1[0]==key2[0] :6 I3 U* ~  p2 C4 n1 _/ g
                    sum_xy+=(key1[1]-avg_x)*(key2[1]-avg_y)0 u# g. E7 p3 ?7 z( j# ]: S
                    sum_y+=(key2[1]-avg_y)*(key2[1]-avg_y)
    . _1 [1 V0 w4 v) e, I        sum_x+=(key1[1]-avg_x)*(key1[1]-avg_x)1 M3 Z! Z8 y" z& Z; N5 A* O! }
       
    # O/ i- s  d/ z$ U: R8 I    if sum_xy == 0.0 :
      r$ I& l. h' i        return 0
    2 c; a' q: o/ `" @# |  W1 l0 ?" |    sx_sy=math.sqrt(sum_x*sum_y)
    % ?  z# I; K9 _0 x# @7 j. b7 x    return sum_xy/sx_sy& b2 j/ J) c. a+ p
       
    $ Z" h1 x. g1 w0 F* S" c+ R
    ) t# d, I5 i7 B. C+ m" ?/ E  T#0 c' V/ j6 ?7 X( S4 R1 }
    #   读取文件2 n5 x6 i& o0 B( y$ t2 E9 r
    #% _0 V% ~3 W6 G4 P0 v# d
    #! I6 W! Q3 t, K5 [7 P3 x
    def readFile(file_name):3 a& Z) L) ^% d. g  s( G
        contents_lines=[]
    . W9 Z. i# Z* h9 V& d7 P3 x6 {    f=open(file_name,"r")
    * O! V* A# i4 B: p3 q* @    contents_lines=f.readlines()- g0 I3 S4 G4 U% G: o/ l9 S
        f.close(); k% ?. b' m  l: A* `9 g
        return contents_lines. ?! y2 a5 Q% U( q7 Y$ y
    2 |1 Q3 l5 `3 q' L. A& s6 I' M" K
    ( ]0 i* R8 m7 s' z" }& o: d
    % X/ y) m. D( Z5 d( d
    #: p# s' T3 t% e
    #   解压rating信息,格式:用户id\t硬盘id\t用户rating\t时间
    & g6 @" w  y) W0 ^4 X#   输入:数据集合$ V9 F+ `4 }: [
    #   输出:已经解压的排名信息/ Y( A$ c) L$ D" j
    #$ P4 v# k: }& p3 A6 |6 R
    def getRatingInformation(ratings):( e. x4 i: W% |
        rates=[]
    0 j" @2 H; P9 Y, W9 Q7 L    for line in ratings:
    7 s4 \/ U6 p8 H' [( }        rate=line.split("\t")
    % w0 R5 @$ Z8 L4 e2 U        rates.append([int(rate[0]),int(rate[1]),int(rate[2])])
    1 h) ^8 t' s) A$ m    return rates  `3 y$ ?# W9 G2 ?4 u: l
    $ F4 q' Y/ s. d$ t+ A
    - O4 i/ u, h' b
    #2 Q3 ^- B  z! j; Y4 ?" S- _
    #   生成用户评分的数据结构; `5 O% [" M7 o& c* C
    #   
      y) b5 x: d8 R' ?' v8 ~% a#   输入:所以数据 [[2,1,5],[2,4,2]...]
    , x+ J) c0 }+ F% t#   输出:1.用户打分字典 2.电影字典% E1 I$ H, d8 g) B* {& L
    #   使用字典,key是用户id,value是用户对电影的评价,
    % r' y1 [( r7 I6 ?. {  Q( X: D* z#   rate_dic[2]=[(1,5),(4,2)].... 表示用户2对电影1的评分是5,对电影4的评分是2
    $ b6 Z+ e/ ]4 b0 \8 m& j7 \#6 K' v% Y2 G+ [6 u" o; \
    def createUserRankDic(rates):
    ) [) ?! U4 a' a" b) j- X    user_rate_dic={}
    * V  @% @/ A/ Q% Z    item_to_user={}0 P5 y3 L2 W* n: z/ c$ e
        for i in rates:8 G( K& q$ [* z. I  T; o
            user_rank=(i[1],i[2])! j3 Z' U! j" |9 {( ~
            if i[0] in user_rate_dic:
    # d1 P3 X6 R4 L            user_rate_dic[i[0]].append(user_rank)
    9 ]: h( Z% F/ e        else:8 B  P- E* q- V5 ~7 u3 w; X+ Q) f" u
                user_rate_dic[i[0]]=[user_rank]
    . O3 `; s9 f; {9 \            ) f5 W$ O: C4 S! B* j6 J1 N! f
            if i[1] in item_to_user:
    " ^# V9 Z6 G0 q$ t) t            item_to_user[i[1]].append(i[0])+ j! |2 U. \$ `% w, Y! {
            else:, _7 N. g3 [+ ?) P2 R5 Q
                item_to_user[i[1]]=[i[0]]
    . q! I1 z3 O# L& X3 S1 ]4 t            
    $ ], T- {: g+ \    return user_rate_dic,item_to_user
    8 C8 N  S9 g) Z0 ]! O! U
    % P& `) B$ I7 L; R( L& `$ t9 |8 t/ o7 N) r4 s, U6 y
    #
    6 H3 Q3 g# w; w! ^) Z#   计算与指定用户最相近的邻居
    4 j  ?% {. [) z5 F#   输入:指定用户ID,所以用户数据,所以物品数据' Q, q. b- Q; C$ A' H3 F: K9 K
    #   输出:与指定用户最相邻的邻居列表
      d, v$ p' L1 G* z$ R/ Z#
    7 |! V9 l6 d, y3 N3 Udef calcNearestNeighbor(userid,users_dic,item_dic):& g& x4 ~1 \7 N, b0 f' l
        neighbors=[]/ r7 R' O4 t% @1 w6 f4 U
        #neighbors.append(userid)8 @" i2 Y/ q6 _) a7 y
        for item in users_dic[userid]:
    8 l1 d/ f+ S0 D& x5 G! k        for neighbor in item_dic[item[0]]:
    8 h4 M" a1 b& C' T) B            if neighbor != userid and neighbor not in neighbors:
    / n. H6 N# }& W; Z8 D# M" k                neighbors.append(neighbor)
    9 j% M$ {" k5 b      
    ' p- ?5 m; [8 i5 W    neighbors_dist=[]
    0 }* G, p) O: K3 d0 Y9 g    for neighbor in neighbors:& a0 j" G( L$ B4 y' W# x1 [
            dist=calcSimlaryCosDist(users_dic[userid],users_dic[neighbor])  #calcSimlaryCosDist  calcCosDist calcCosDistSpe0 c- q6 D7 {! ]  G! t! ?0 C
            neighbors_dist.append([dist,neighbor])3 G4 L; u' q- `' o1 p: O
        neighbors_dist.sort(reverse=True)5 m- }6 ?8 |1 n9 o
        #print neighbors_dist% m) f/ d+ Z7 S& Q5 P
        return  neighbors_dist
    ) c% Y) Y/ ?( |$ P5 n3 r3 k/ ?# U8 E0 K% B3 [! Q6 V2 n/ n6 j7 t

    ; Y2 i& c% m0 o9 H' T+ J#
    1 ]% f) B9 n! o: X! W. A. A! @0 F% e# N#   使用UserFC进行推荐& ?; e$ Z- i, N5 |# o5 @7 P$ B6 n
    #   输入:文件名,用户ID,邻居数量
    9 K! X0 G* K& T) A! |9 x#   输出:推荐的电影ID,输入用户的电影列表,电影对应用户的反序表,邻居列表- f5 h  p6 `# S) Y
    #4 s3 R, k! q1 D: }, F
    def recommendByUserFC(file_name,userid,k=5):; i5 a( _4 c9 V$ `3 g4 z8 z
       
    7 [7 W6 F7 H/ x9 k. Z& l    #读取文件数据
    " l0 I7 z* C3 s' C8 e    test_contents=readFile(file_name)8 U4 F# t# S! d, L( f7 i+ X* v7 S
        . v& a  L/ _# Z- l/ p9 g- A/ N2 i
        #文件数据格式化成二维数组 List[[用户id,电影id,电影评分]...] ' A+ a  s) S* z  H
        test_rates=getRatingInformation(test_contents)
    , _& `/ T& @  k4 N   
    - z7 K. n- U: j' y* Z    #格式化成字典数据 % K4 i8 B9 O: ?9 {# n8 p; @
        #    1.用户字典:dic[用户id]=[(电影id,电影评分)...]
    + W. v( m* O7 G+ J. z    #    2.电影字典:dic[电影id]=[用户id1,用户id2...]: X6 X% _" U2 f- {, a9 f
        test_dic,test_item_to_user=createUserRankDic(test_rates)$ ^/ j! j$ F: _+ ~& u+ n) d
        - b9 Z4 W) H+ |. I$ x
        #寻找邻居6 ?2 |3 J# ^+ J0 \1 R: \( r, ?
        neighbors=calcNearestNeighbor(userid,test_dic,test_item_to_user)[:k]1 e+ R: p+ f. v( w) w
            : C' p6 A( @9 B# m7 c& Q8 T
        recommend_dic={}
    + h+ o, C* s2 o5 @) U    for neighbor in neighbors:
    6 j7 @. a; b0 d* M' u! P& w        neighbor_user_id=neighbor[1]
    + W/ T* r6 Z: X9 B# g" k0 B        movies=test_dic[neighbor_user_id]
    1 ?6 m. T9 d  P9 O6 r: M        for movie in movies:9 X0 f+ U) h0 X  ^& f1 y
                #print movie% \3 g  H, N* q1 ]6 ^+ Z5 ^5 `
                if movie[0] not in recommend_dic:: O, I- m" [" h2 ~
                    recommend_dic[movie[0]]=neighbor[0]3 T  L5 ?6 {& ]- D
                else:
    & w3 o7 s6 @5 i3 b9 K                recommend_dic[movie[0]]+=neighbor[0]
    ! Q3 x! C- J9 p* _7 L    #print len(recommend_dic)
    9 f" b" V9 R" p+ a   
    7 W4 [# C1 F4 `2 h& J6 [" Y    #建立推荐列表
    2 s4 M. |: M4 M0 [6 s    recommend_list=[]5 V1 `+ q& A1 X7 w' g# G# [3 t
        for key in recommend_dic:* Z& E* h9 a) i
            #print key% ]2 `5 U  K! M' f, A9 s
            recommend_list.append([recommend_dic[key],key])
    # d4 H5 Q0 B( M   
    8 j) e4 p1 D9 [; H    " L$ Q" H; c+ S5 f4 t
        recommend_list.sort(reverse=True)
    . F9 `/ ]3 k  n$ W    #print recommend_list
    % Q4 P) l) M. O2 s3 L    user_movies = [ i[0] for i in test_dic[userid]]: K; \$ `. Y. S0 w; F4 T4 Q

    0 C1 ~  I2 ~6 ~! M9 w    return [i[1] for i in recommend_list],user_movies,test_item_to_user,neighbors
    . e! O' |  M$ Y8 d! h. I  \    + X: u2 e# O1 T8 N; I) `, n
        ' I7 L& f" m  C% U$ r0 M7 Q

    * _/ J  ]& ?) v) c#: }: b/ W% y& [4 G
    #3 O% [$ I: R. ^' k* `, U2 s% K
    #   获取电影的列表
    . j0 Y* i8 I+ Z## R/ i& n7 o' E1 A
    #
    1 g1 F0 |6 e5 g* U; [#
    * }3 C' W' J- F9 c" Adef getMoviesList(file_name):
    9 O) V2 k/ ]  S) {8 \9 T    #print sys.getdefaultencoding()3 h& `' @0 W$ ^$ [$ w: ^
        movies_contents=readFile(file_name)8 r4 O' Y) t( d% @5 i% D
        movies_info={}' K! w) C# l1 u, {
        for movie in movies_contents:2 d& o; q( L2 n1 k
            movie_info=movie.split("|")
    8 M: _9 h0 O6 G        movies_info[int(movie_info[0])]=movie_info[1:]
    / J+ d4 U. @$ ]    return movies_info8 m8 H: Q3 {# u9 Y- Q6 `
        & I+ d2 G7 }8 N0 R  N
       
    # A9 K4 s7 m' {9 j   
    1 }' R2 F* `7 ]3 e* o: N% P#主程序  ^  J8 h5 \- Y" E6 t8 Q  e# M
    #输入 : 测试数据集合+ H( Q. \: T7 ~1 ]! j
    if __name__ == '__main__':3 a/ V; e  U- T3 }$ ^8 R1 Y
        reload(sys)3 [* X7 I' ]6 K4 v. C; g
        sys.setdefaultencoding('utf-8')! ~$ T' O* g- {! W' k
        movies=getMoviesList("/Users/wuyinghao/Downloads/ml-100k/u.item")' r" D; v" Z9 q7 o7 U6 u+ h
        recommend_list,user_movie,items_movie,neighbors=recommendByUserFC("/Users/wuyinghao/Downloads/ml-100k/u.data",179,80)1 l- w; x+ i! N" }. |( G
        neighbors_id=[ i[1] for i in neighbors]
    ( A. R6 t. e" _    table = Texttable()
    + T- b- M( G  Z) t: O    table.set_deco(Texttable.HEADER)
    , t0 ~. v. O/ ]    table.set_cols_dtype(['t',  # text 1 v: m8 j( a2 @( m7 }: e$ X
                              't',  # float (decimal)
    ! m- I# ]5 R  G, ^' h, f% x/ s# A                          't']) # automatic, ?7 @# X# V) E* v" b- p
        table.set_cols_align(["l", "l", "l"])* i0 i3 ^- v* m/ l' T# u
        rows=[]! D. p& a5 W$ d# y( R+ L* W, x
        rows.append([u"movie name",u"release", u"from userid"])1 ]3 c+ I7 i& ~, |3 ?, J
        for movie_id in recommend_list[:20]:
    & `. W3 J) u3 F+ A" g4 E7 l        from_user=[]
    9 D  M9 c% ~4 W        for user_id in items_movie[movie_id]:9 B3 p+ N8 ]6 x& c+ u
                if user_id in neighbors_id:
    ( `* @4 L1 _3 |$ Z                from_user.append(user_id). d- o7 U- C  }+ Q1 P
            rows.append([movies[movie_id][0],movies[movie_id][1],""]). M: x1 G% B5 g& A" E
        table.add_rows(rows). W! q! y. T( |9 g+ g* R
        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
    9 t- T4 d; z) U' @8 W# V2 o3 Y: G# -*- coding=utf-8 -*-" o" h) B4 z8 R" j

    3 \% H! o/ N2 b8 }* M2 ximport math
    , B2 Q6 y+ i4 r8 `( F( K
    这是什么语言的程序?7 P( w& w4 x/ [/ W% v
    回复

    使用道具 举报

    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-6-3 05:34 , Processed in 0.473087 second(s), 68 queries .

    回顶部