QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 5278|回复: 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 V0 b) h
    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 -*-
    - W" [% n5 z7 w' Q" H
    ' j3 D6 a% d5 t# Y& Yimport math
    ( l' i+ p% c6 I* W4 n2 aimport sys
    / N. W, R' z: x: I6 F* Mfrom texttable import Texttable
    5 @/ `1 p4 i- t6 `4 C
    2 d' Q' c7 C4 Q) ]7 {) W( y6 k( w, u$ s1 g; U1 b8 V
    #" m0 ^5 p6 }# u( p9 y( L2 h
    #   使用 |A&B|/sqrt(|A || B |)计算余弦距离0 k' S. }, U$ I4 _
    #: l  V: j1 G, A
    #
    , U1 j5 {5 Y7 J# I#* M/ o. j% _! _7 U% [
    def calcCosDistSpe(user1,user2):
    8 D9 p/ ^6 R+ i" E# `$ i    avg_x=0.02 y- d# O$ B4 H' E: ?4 U/ u' J% k; K
        avg_y=0.0
    ) x" r. w: [) e    for key in user1:' H5 z- k- v' d: l. X" l
            avg_x+=key[1]/ \8 \  F' Q9 f. q0 @
        avg_x=avg_x/len(user1)
    9 r9 ^2 U+ e# V3 z9 w    6 H) ?/ H! C$ ?& d
        for key in user2:' C( B& ^8 A  p8 Y. [- M+ y3 \
            avg_y+=key[1]
    $ Q- R  I9 O3 b" L7 P    avg_y=avg_y/len(user2). {4 c) z/ a% _% {6 x- Y
        ) r" @" ]/ l8 ~. i6 a, B
        u1_u2=0.09 [7 `; @4 y. d# x
        for key1 in user1:8 e' k3 w1 c* y% u  k/ c  j
            for key2 in user2:: P  F) V* }' X2 o
                if key1[1] > avg_x and key2[1]>avg_y and key1[0]==key2[0]:
    , V( L) S: u3 m                u1_u2+=15 W% J: I; \; f; M+ F4 N4 P- A& B
        u1u2=len(user1)*len(user2)*1.0
    + S3 w# U3 ~8 [2 Y: J( S$ I2 I    sx_sy=u1_u2/math.sqrt(u1u2)9 F3 d7 Y$ ~/ S5 c) K5 l
        return sx_sy) Z4 u* D' |; e: E2 n7 b. X9 i

    : I9 f( {! n: y' z* k, W$ I
    . J2 D* S$ F9 _. Z2 }#
    , n% |7 s" M) {; P( H6 j" a1 d+ p#   计算余弦距离3 F0 ?+ {0 M; A3 y% I7 f! q# `
    #6 X9 B7 C0 H; l) [  r; F0 o
    #% s& E4 l( E" d0 |! k7 F" }
    def calcCosDist(user1,user2):5 t$ W0 Y+ W. O* F' B2 |
        sum_x=0.0
    % J& Q) V5 D/ p: Z( ~    sum_y=0.0- @5 @  M4 u! K2 {4 A! H& I6 D' o
        sum_xy=0.0; ?* ~1 `2 i( c2 y2 Z. u
        for key1 in user1:1 a) E  w+ U) ^7 M9 ~. S$ p
            for key2 in user2:. h+ t" v- X* E
                if key1[0]==key2[0] :( Z; z+ ]- T6 ^& U
                    sum_xy+=key1[1]*key2[1]7 E; e# m; M: p4 R
                    sum_y+=key2[1]*key2[1]
    ) I+ w$ X% F5 Q' {                sum_x+=key1[1]*key1[1]+ I: N& G/ w+ L
        % J, I$ v( k" ]$ b, U3 b6 Y. H
        if sum_xy == 0.0 :% g) j% E. O0 j# t8 r$ Y, D4 n
            return 0
    : l3 k* v5 a# ?! _3 b    sx_sy=math.sqrt(sum_x*sum_y) , m1 i) T! |6 P5 N! i
        return sum_xy/sx_sy" z! S8 t- v, }, ^( A

      n# T0 u7 ?# G% ?/ @/ ^7 s4 u. k4 R% C+ j9 c
    #. y+ O6 a; P# ]
    #
    - [; e, |# {6 y  E% O8 S) O5 P#   相似余弦距离
    / j. T5 X. Z1 Z, {) u#
    * X4 S- M' C6 [. [; j#& o9 j/ N$ D, ~# p9 A1 ~, O/ l1 Q$ u
    #2 K6 j& Y5 i) H, g, ]
    def calcSimlaryCosDist(user1,user2):0 l9 G" E- v1 [3 ~9 s
        sum_x=0.0
    - x) G) F! n; v; X" L    sum_y=0.0
    0 D) ~: T6 ]- @- ?0 |/ p/ }    sum_xy=0.0- H; n4 o3 Y( \' |: T
        avg_x=0.08 O. l! `  K* h3 w9 Z$ v' m
        avg_y=0.0; [6 t# \: c! A  c/ I0 d0 ]
        for key in user1:* e2 z$ @# D2 a; E* R! F
            avg_x+=key[1]: y: {/ n& P% j  U
        avg_x=avg_x/len(user1)
    0 z1 i: w! b" l! Z: G6 M; d% ~   
    ( V; e- P9 F1 |( x6 I: r( X    for key in user2:
    & o. N4 T9 x& i3 N/ J6 {7 u  N9 {) r        avg_y+=key[1]8 S! y3 x! n% l$ q9 u
        avg_y=avg_y/len(user2): O7 c( n# s3 O- F
       
    $ E2 n+ ^8 A' O7 \    for key1 in user1:; |# c, h) g2 W/ T0 p1 p! F, t  ^; J  X
            for key2 in user2:: }. x" O3 M7 |+ N1 [% @( {
                if key1[0]==key2[0] :
    , V6 A, k; D( v- q) c3 U' K1 A                sum_xy+=(key1[1]-avg_x)*(key2[1]-avg_y)+ H. c7 W; f9 E/ V
                    sum_y+=(key2[1]-avg_y)*(key2[1]-avg_y)
    0 q& s. H$ T1 A9 u. Y, `+ U. Q        sum_x+=(key1[1]-avg_x)*(key1[1]-avg_x)$ H5 n. ~! P- M" e. m% u7 y
        3 c& `  S. o7 F" b; N$ r" [4 j
        if sum_xy == 0.0 :8 B3 T- Z7 p8 e# G2 v' Q
            return 0
    1 i5 K# D/ I, P  T) X    sx_sy=math.sqrt(sum_x*sum_y) - T6 k7 s/ I! r; ?
        return sum_xy/sx_sy6 o% B3 ?5 \5 D' v1 _$ g( s2 \  X
       
    ( v9 w$ {5 ~! O  @" z0 ^3 [! L5 q# F# `
    #) M4 ?" n  t- X0 n6 c& s
    #   读取文件
    : Z8 R; A  d( ]6 _* O## J6 i- p0 i6 Y) k, r: O& T+ b
    #
    2 M" ]$ Z, l1 j+ I4 ~- X- y9 T/ \- ndef readFile(file_name):
    " a9 V5 n6 T9 T5 Z+ e* P# @9 @( u7 |    contents_lines=[]0 y0 D! R- ^+ E$ n. W! ?
        f=open(file_name,"r")
    % L. J5 J! A, O    contents_lines=f.readlines()+ I7 p0 }2 j* k( i
        f.close()7 W+ h/ s' ~) @; D( ?' d  B$ I
        return contents_lines
    - a! w+ k- b: y6 @1 C
    $ O+ j+ a+ _9 g7 M
    ; o4 ]! {+ o. |- j- C$ Q* n2 N1 v1 i* B7 x, I' ^5 q5 l( l
    #
    ' ?$ M. s& z5 K  f# V; d#   解压rating信息,格式:用户id\t硬盘id\t用户rating\t时间
    " y  k' F& {! {; K% j4 ]( l" Z) d/ J3 T) |#   输入:数据集合' v. g; o0 F  p' V! n
    #   输出:已经解压的排名信息
    % b) Q% B5 \6 Q) }" M#7 @2 E; E8 N6 ]6 [& N: O
    def getRatingInformation(ratings):; `* w) v2 v1 T$ J; ^5 n
        rates=[]
    $ }: q1 z, Z9 _# @6 q' u9 r2 T( j7 c& |    for line in ratings:
    1 l7 }' J& D; k% O5 v        rate=line.split("\t"). L9 K6 Q1 ^3 p) e* T- F% |/ g8 ~. V# m
            rates.append([int(rate[0]),int(rate[1]),int(rate[2])])
    ' M& J4 G' Z: ~) M" k    return rates
    ' q; r* {- Y0 [& S0 V* F9 q9 d/ Y; \7 n; u* W

    / n$ b8 p. t2 ?( D5 |# q& I#
      o9 f3 g0 v7 S( R4 {#   生成用户评分的数据结构
    ' N0 \4 x- C& w( ^6 U0 M#   : \& c; f8 Y/ h4 f& `+ V0 [
    #   输入:所以数据 [[2,1,5],[2,4,2]...]
    % q8 ?/ }- b$ h+ _#   输出:1.用户打分字典 2.电影字典
    ( A: M6 G5 X% ?; u0 }#   使用字典,key是用户id,value是用户对电影的评价,7 ~5 h/ o  e1 Z9 M
    #   rate_dic[2]=[(1,5),(4,2)].... 表示用户2对电影1的评分是5,对电影4的评分是2
      K2 t1 W' X! g& ]  T# y$ |3 s#
    1 a( D3 W; M% a1 D3 N- O- G/ _. ^def createUserRankDic(rates):
      S7 ~5 H  `+ `+ b$ P- X    user_rate_dic={}0 g2 \4 {9 _+ w# ?6 ^5 W6 j
        item_to_user={}
      t% O7 f2 v3 j    for i in rates:
    4 l+ P) H  e$ X+ S' m4 z' F% Y  r* K        user_rank=(i[1],i[2])# y# g" l4 H2 K* z' ?# J; _
            if i[0] in user_rate_dic:( W& Y5 y# j: h( G
                user_rate_dic[i[0]].append(user_rank). e; g5 ]9 t8 R) d$ o) B
            else:
    5 G% L$ N" i. `' d8 h/ f            user_rate_dic[i[0]]=[user_rank]
    2 R$ y& b5 d! l            
    - e) X* L7 L& c5 p+ Q        if i[1] in item_to_user:9 {/ S, p8 C& k6 D% U; y( o4 t
                item_to_user[i[1]].append(i[0]); f& m4 [8 ~5 A5 Z1 L, i1 P2 q
            else:* q( c9 R7 f: m' q' B, B2 B
                item_to_user[i[1]]=[i[0]]
    - H: m8 }5 T9 B! \            
      s4 H7 i+ j* n$ I5 e" z& Q    return user_rate_dic,item_to_user4 J1 ~. H6 Q; t& F9 P
    3 @. F# B$ c- Q
    / D, k5 M- I3 `
    #
    4 M; D$ i7 U) Q3 W/ A#   计算与指定用户最相近的邻居
    0 A2 c2 X, r% Y/ q#   输入:指定用户ID,所以用户数据,所以物品数据
    & n& Q- m$ B! a, u#   输出:与指定用户最相邻的邻居列表4 S/ U$ _7 W  d. u
    #
    & i$ \0 _6 j9 ]' H+ Q4 r# {/ xdef calcNearestNeighbor(userid,users_dic,item_dic):; H+ p. W, Q! I' z9 h8 T
        neighbors=[]
    . Q2 L2 i% o& l- c. O    #neighbors.append(userid)# u3 S- `6 V1 b+ e% Q& O5 \
        for item in users_dic[userid]:
    & {0 O) a1 r; A% A& j. d! v        for neighbor in item_dic[item[0]]:; I& ]9 j2 @* r3 Y8 y: V$ }, ^+ B
                if neighbor != userid and neighbor not in neighbors: 1 u3 i! w: u7 D% T2 O% E! d
                    neighbors.append(neighbor)
    2 B: c. h. t/ F9 N6 u! g* D  W      
    9 C/ Z, T$ A' G* [0 O& k    neighbors_dist=[]
    % L& \$ C6 J3 ~1 W1 X+ _# M! C' k    for neighbor in neighbors:7 I0 N3 [. q$ _5 ]% Q) w8 ~
            dist=calcSimlaryCosDist(users_dic[userid],users_dic[neighbor])  #calcSimlaryCosDist  calcCosDist calcCosDistSpe
    ; w* U( C8 T. z3 Y8 e9 R        neighbors_dist.append([dist,neighbor])
    & e6 K: e5 N* }5 _    neighbors_dist.sort(reverse=True)" C: L7 g" Z" V. ?$ @6 S! ~& u
        #print neighbors_dist
    : l  b4 R  s, @5 R7 K    return  neighbors_dist4 Q, C: P+ q# w3 }+ L  ?* X4 D
    - o; n+ `. t8 H. K* @

    % `& U6 k! k2 d3 b5 [  J! s4 o#
    1 _4 Z& S5 Q9 ?% w; z4 r$ G#   使用UserFC进行推荐
    6 y: _, r& v- ]% D1 S#   输入:文件名,用户ID,邻居数量
    $ A: p! [$ F9 G5 P) [+ _2 i0 k) f#   输出:推荐的电影ID,输入用户的电影列表,电影对应用户的反序表,邻居列表
    . d, i. E1 r; U7 s- u& H#
    8 ~5 H* I/ B4 l8 ?- Y8 y. odef recommendByUserFC(file_name,userid,k=5):
    6 M) i, U" ?+ }& n5 m! B+ ~   
    4 M3 L6 N* F0 Y    #读取文件数据
    - L. K( M! G& ^$ e    test_contents=readFile(file_name)2 j" [; b8 D- u# b. H, c
       
    9 q  z' |0 Y, k  n    #文件数据格式化成二维数组 List[[用户id,电影id,电影评分]...]
    2 `8 }7 i1 r- \9 n' G    test_rates=getRatingInformation(test_contents)
    ( G# C# J; ~) L5 Z    ! V1 p* w8 K0 Z$ G0 g
        #格式化成字典数据 ! C. `. v& M3 h! x
        #    1.用户字典:dic[用户id]=[(电影id,电影评分)...]
    - ^! }" n+ \- T" z0 Z& K    #    2.电影字典:dic[电影id]=[用户id1,用户id2...]
    5 r' Z  c% \2 Q+ |3 x/ b9 g    test_dic,test_item_to_user=createUserRankDic(test_rates)! b4 x5 [2 N) z
       
    , `& J& h- ?. v8 X3 x; i    #寻找邻居
    4 u( u" m& L' X  q, t* e) `    neighbors=calcNearestNeighbor(userid,test_dic,test_item_to_user)[:k]
    / H, I  r" s  f6 W8 k6 b" \* A        
    0 s; ?+ M9 F9 j( Z/ k$ a    recommend_dic={}
    + O; Z2 o; c4 }7 e    for neighbor in neighbors:
    % l$ ~+ M" s" Q8 E& D        neighbor_user_id=neighbor[1]
    / c5 x  {: j' _! U( c( r* {        movies=test_dic[neighbor_user_id]
    : e4 v8 T$ f& b4 I7 G9 s; S  |# R! Q        for movie in movies:% w& O& R/ }( A$ V( N# b2 v
                #print movie+ D0 b/ ^7 V$ F
                if movie[0] not in recommend_dic:
    , R4 m6 W) a) O* F+ m, ?, W+ h                recommend_dic[movie[0]]=neighbor[0]. X" M4 w5 x* Z2 w$ {* ~
                else:
    4 a& }7 \7 X7 Q$ i                recommend_dic[movie[0]]+=neighbor[0]
    ) I: P& J, D3 ]1 K+ ?+ d( n, F* ^" p. J    #print len(recommend_dic)
      f7 |& h; h! g/ f% K9 V   
    - M7 g6 H/ I. @+ P    #建立推荐列表
    " F( \. \( S$ B4 ^0 D    recommend_list=[]+ x9 b; o0 F7 e. d& f
        for key in recommend_dic:% }# D2 _6 h7 [- f( n! ]
            #print key; ~- e) K3 I4 q& f$ t# m
            recommend_list.append([recommend_dic[key],key])
    ! Z7 G5 w0 @- o8 f# |0 m    5 ^4 f! j4 n1 v+ Q! [9 U- u/ R2 C
       
      W! J6 @8 P2 z5 z1 d    recommend_list.sort(reverse=True); l% D% i& J# M7 U. m
        #print recommend_list
    6 K1 }( `8 w$ u, ]2 t% [5 y' d    user_movies = [ i[0] for i in test_dic[userid]]$ V$ f8 l% B- l% K; x) S' O, x
    1 l, [. i1 I9 P! n0 ]( E+ S
        return [i[1] for i in recommend_list],user_movies,test_item_to_user,neighbors
    2 b+ K$ E4 H( S8 o6 t( y7 S- q% y0 Q   
    , i' `8 p" |0 F- c9 o   
    4 K% S6 m2 D8 K- U! x' J
    * N* t: V+ E# n$ ?3 S6 \5 b0 j#
    4 U2 P  a) o+ |$ J$ ^* ^' H: ?# |#' @4 |) \9 P% c' D0 p/ t% m1 |- g
    #   获取电影的列表9 K3 ^* B9 H" ^6 ^
    #* U5 B- u2 [) _( N' `
    #
    . j- K" U) ?' H  M! C#5 O$ R) c1 F7 w: v: R6 O
    def getMoviesList(file_name):
    1 r6 v  A: Z7 T# b3 J  w    #print sys.getdefaultencoding()2 o' R5 T2 p! K  C$ f' i) Z
        movies_contents=readFile(file_name)
    7 e! S) O  w7 }# o0 a" o    movies_info={}
    9 A3 E: c- H- R; V    for movie in movies_contents:1 g; u& y( s! h/ ^" N1 A3 ]
            movie_info=movie.split("|")
    . t) K7 z0 V5 A7 Z  b        movies_info[int(movie_info[0])]=movie_info[1:]+ l% `  q; N$ K9 G3 Z# p
        return movies_info
    ( K) r9 U; p/ r! a    ( H) t1 b6 {: X% Y
       
    / z( H7 k' z7 l5 c# s  S1 {  s3 B   
    4 V/ }" b; {4 k1 W2 _5 |. @3 g#主程序& \/ {4 c+ v) Z+ [/ W" d
    #输入 : 测试数据集合& |7 C$ m) x3 |# w) f% Z/ r% N" j% G
    if __name__ == '__main__':
    + H: m. [4 i& I, t; d* S    reload(sys)5 x$ p  I: j7 P: R" j! Z& m+ B
        sys.setdefaultencoding('utf-8')5 Q% F. O) _9 T& J9 \5 H
        movies=getMoviesList("/Users/wuyinghao/Downloads/ml-100k/u.item")
    " v, L7 h- Z" M" Z& O9 d. ]" p    recommend_list,user_movie,items_movie,neighbors=recommendByUserFC("/Users/wuyinghao/Downloads/ml-100k/u.data",179,80)
    7 E1 Y  A$ ^# n2 _) d5 P# Y2 L5 `    neighbors_id=[ i[1] for i in neighbors]; z2 k4 m. _' i5 b! z, f
        table = Texttable()% T, [+ [7 `; N- Z9 X' T
        table.set_deco(Texttable.HEADER); m- n. B: f. R! [
        table.set_cols_dtype(['t',  # text / J) M- D+ O, d# N6 r
                              't',  # float (decimal)
    " x8 F$ F: Q9 X& b# R9 Z                          't']) # automatic
    ) z# r$ [7 L/ T0 D    table.set_cols_align(["l", "l", "l"])
    / g; y6 L+ n5 Y2 D  C3 {8 v% W    rows=[]
    1 Z  k9 B- f- _, T2 U% H    rows.append([u"movie name",u"release", u"from userid"])
    ' k0 R, q7 D$ T( s9 g% O  r    for movie_id in recommend_list[:20]:
    7 Z- b5 Q* i8 S0 x        from_user=[]; @# x! K3 }8 k
            for user_id in items_movie[movie_id]:
    . C/ f3 f) h7 W$ k& k            if user_id in neighbors_id:
    5 s* E  }7 w; X2 n                from_user.append(user_id)
    / M* i/ Y( e$ Z4 V' [7 y        rows.append([movies[movie_id][0],movies[movie_id][1],""])
    ) Y- D% ~( _* j$ k: N. n# R    table.add_rows(rows)
    * N# c# u8 I# |$ q2 _' q" P    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 8 y6 U2 Q7 Z0 _& y2 j8 \
    # -*- coding=utf-8 -*-
    $ t8 W; Q8 T% o" @6 w/ L, j. E6 z* D# ]
    import math
    ! I7 A+ z1 a6 D3 U
    这是什么语言的程序?
    : h/ a% j8 y1 Q- z7 j
    回复

    使用道具 举报

    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-5-19 01:39 , Processed in 1.008042 second(s), 68 queries .

    回顶部