QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 5065|回复: 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
    本人在学校参加暑假培训,需要这个算法做题!求大神赐教,感激不尽; W, K6 D+ I: r& Q8 @# }- b
    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 -*-
    % S! E0 J2 Z* ~; R2 @
    5 S4 {* }( t/ Z) W3 oimport math
    9 w5 ]1 _2 A# C4 o; S9 r6 l# `: Kimport sys
    7 c2 @3 Z: c+ v- C$ \from texttable import Texttable. M! c9 l% `% m

    - T: y- |: @' |1 r, I* C! Y  e" t% H+ E0 E+ T
    #6 G& L( T6 v* K' O3 J' G# r
    #   使用 |A&B|/sqrt(|A || B |)计算余弦距离
    8 Z. l& I: Z- k2 V$ [. M#
    0 {* y- O- ?  O6 V  y2 k3 B5 Z. Y( q#! ^- Z) Y& p) l/ P& Z% E! r
    #
    9 u0 I( [  V0 k' W& i# O6 P4 ^def calcCosDistSpe(user1,user2):# I, B+ s0 d# Z5 u1 O: |
        avg_x=0.0% F6 k# C( D" z; i% ?
        avg_y=0.0
    . B+ w& v) k& i1 B; G/ x7 i% f4 Z    for key in user1:
    ! _% j1 A; H( I' k# U; ]        avg_x+=key[1]& s1 F9 F5 K+ C9 }
        avg_x=avg_x/len(user1)
    ; `6 J3 \, L7 @* B' J# ?   
    4 y8 \6 i# @$ y' U    for key in user2:
    + N# I& S) e/ y# K        avg_y+=key[1]! _: C, u% W/ p0 r
        avg_y=avg_y/len(user2): w; N) o* ~5 ~% R& v) B
       
    & l4 w; f& ]/ f4 O; J    u1_u2=0.0$ u4 V) E8 e: B% H5 u! J
        for key1 in user1:& s8 x- i" Z+ J% K! C
            for key2 in user2:
    . x) h- X' ?: l8 O' r. i+ T            if key1[1] > avg_x and key2[1]>avg_y and key1[0]==key2[0]:
    ( G0 l/ }! V/ N- C) |3 G                u1_u2+=18 ]9 l3 o9 p) T
        u1u2=len(user1)*len(user2)*1.01 V' }9 f" c3 @% o$ Q! u7 L
        sx_sy=u1_u2/math.sqrt(u1u2)! z: y$ e1 A# f4 y: n
        return sx_sy' g3 @& [" A5 Z" @, Z9 [' g

    * Z& ~* a3 N1 b2 t
    " x. f7 K( J4 r, v' t" ]#5 _; e) h& [9 l! m. D4 L- D
    #   计算余弦距离( V+ Q8 z: [$ b' @( t0 V2 [$ h
    #' f6 S& S; `8 l
    #
    : [2 q9 ?, q  w1 \def calcCosDist(user1,user2):
    $ l/ L& O. V( k9 e3 s& z' S    sum_x=0.03 s' D1 Z7 o3 T8 ^
        sum_y=0.0
    $ b, N5 {! T" J    sum_xy=0.0
    % [; O  H; o/ X) e    for key1 in user1:
    / o  e- o' U9 l, w# R- c. E7 i: h        for key2 in user2:/ Y( ~& n$ l* Z% M. V# H9 _8 n; g
                if key1[0]==key2[0] :3 E! r5 y/ I3 R' \
                    sum_xy+=key1[1]*key2[1]/ F; m; i! {2 t5 j: ]) V, \
                    sum_y+=key2[1]*key2[1]
    0 @" ?5 ?+ m6 Q2 |# M5 O                sum_x+=key1[1]*key1[1]- ]: ]5 N( A! k2 W
       
    ( ^; Z; ~8 [# ]; Z% N- ]0 W    if sum_xy == 0.0 :% s8 K: E; s, s6 q% m7 o! h; q
            return 0, t( ]2 s2 T$ K$ U' l8 h0 N
        sx_sy=math.sqrt(sum_x*sum_y) & b# _* H6 h6 R  [0 D" R& E
        return sum_xy/sx_sy6 b- |3 h$ Z8 @, a6 r
    7 b% J- _3 @) W. H3 C/ _; i
    % [0 K( o0 V8 M' Q, _) w6 y& F
    #
    : d* a- `$ k3 _% h3 z  R- F5 T#' j2 d0 a8 X3 k  O  \0 C
    #   相似余弦距离( E" K3 j+ l+ ?& n9 |+ I% g% H
    #
    - i, ~8 ?7 j3 K2 |6 X: `9 {5 ^. b#/ O$ [1 h! Q5 W* H( E& t* C- L
    #9 G2 L0 |1 U4 j  z* q$ E/ s
    def calcSimlaryCosDist(user1,user2):; @: S2 W' g" k8 o
        sum_x=0.0' e5 H2 X2 J% i2 L
        sum_y=0.0
    3 R% V6 Y- s# O1 x& r3 H    sum_xy=0.0
    ' h6 r& G# N; [    avg_x=0.0/ t+ a/ j8 z. i9 [$ b- H7 P4 N* r) h
        avg_y=0.02 b) S. g$ P7 X6 _
        for key in user1:' A- e; P) i9 y$ Z; w1 l) c& f3 H
            avg_x+=key[1]
    " x% f  a6 Y$ A) x" w! y- ?    avg_x=avg_x/len(user1)
    . @+ V) ]4 h2 `7 U   
    1 M+ e* N* B# L. i    for key in user2:4 F6 V3 ^7 V7 O" v' ^
            avg_y+=key[1]' T1 s+ C6 X4 b0 U
        avg_y=avg_y/len(user2)# f: h" r" F) U. K
       
    % D" v; c) }" w! ]    for key1 in user1:
    " c; V; B( l( q; T$ k% V; c3 ]7 ^        for key2 in user2:
    8 L0 }2 J( q/ s7 O            if key1[0]==key2[0] :$ }" }0 }  S% T
                    sum_xy+=(key1[1]-avg_x)*(key2[1]-avg_y)' V: Y3 Z8 E$ Z* E2 `
                    sum_y+=(key2[1]-avg_y)*(key2[1]-avg_y)) S+ b6 g$ u( ~1 k  K2 Q0 Y
            sum_x+=(key1[1]-avg_x)*(key1[1]-avg_x)0 Q' m% w: C4 J, O: b7 a5 D2 ?
        : s9 h6 v; A6 P1 Q
        if sum_xy == 0.0 :$ n& y. W0 d- M+ H& J- y
            return 0
    . M% f# E7 Z  f- B6 C- }    sx_sy=math.sqrt(sum_x*sum_y) + f0 B4 B* ?% {
        return sum_xy/sx_sy
    : O$ t, f5 @; T$ r   
    - \2 L, F' K) T% G7 h' {  ~( R) L" r% Z! v3 M9 `
    #
      u6 w. Q, d3 j6 ]6 a2 ^#   读取文件2 t; h' l$ C. J3 @9 ?- W4 ~
    #
    + o& k" ~$ }& n; P# z& p3 o#
    4 ]* y) o- e. X/ Qdef readFile(file_name):4 ~$ v1 P5 i+ K
        contents_lines=[]
    0 D  j7 o/ T; [* k    f=open(file_name,"r"): u9 s/ F; ]# e  t' Q! P! K
        contents_lines=f.readlines()
    1 Q3 p" ^9 T, c0 z4 |; P# [( G    f.close()
    . n6 H' b% h6 f& Q    return contents_lines
    - v0 K: H# ~5 s( {, l5 P/ }' r. o' L. j, `+ ~  p  C
    / O2 I% \- B2 C+ F- f9 O! d( V
    : a0 S; }7 [0 x2 ^1 b' D
    #
    5 \& M( b* s* e" q% R4 ?9 x+ [#   解压rating信息,格式:用户id\t硬盘id\t用户rating\t时间/ w9 V; o* h1 M8 @* E
    #   输入:数据集合
    9 n2 j5 y3 V1 N1 w0 i! B8 f% Y#   输出:已经解压的排名信息
    5 b' K* p9 C0 [. L#/ C; \# k& f  ~3 i/ [. j
    def getRatingInformation(ratings):. a5 \3 J5 _' r7 [1 v
        rates=[]
    # U; X  f* U; k2 O1 M    for line in ratings:7 a" w% Y( n+ f
            rate=line.split("\t")
    ; U/ a0 k3 o/ h8 g2 ^2 J        rates.append([int(rate[0]),int(rate[1]),int(rate[2])])
    / I- d9 v. Q! z4 O' t    return rates5 b- Q* }$ M9 V- z
    . r) `- V- J# T2 S, o6 E

    : u, p. |6 T/ ?7 Q, M- @7 ]; F$ d#
    5 ]6 a* Z: L! `3 D  h8 j#   生成用户评分的数据结构2 s0 k; a1 E. O2 R# K% V
    #   5 r# E, T# P: M
    #   输入:所以数据 [[2,1,5],[2,4,2]...]
    # E9 j+ {* I2 P) [3 q7 g0 G#   输出:1.用户打分字典 2.电影字典, d/ \3 S( k# ^, ^+ I
    #   使用字典,key是用户id,value是用户对电影的评价,0 V. G3 n3 ]# X. R. g1 B7 J
    #   rate_dic[2]=[(1,5),(4,2)].... 表示用户2对电影1的评分是5,对电影4的评分是2
    7 O/ z# ?7 m/ I1 y- m4 i; w#' `6 |+ `6 |- b& L7 Z
    def createUserRankDic(rates):
    5 t/ |2 I* |+ P    user_rate_dic={}
    " ?; Z" D/ B2 w8 R5 E    item_to_user={}
      e% q  h" B9 H5 s5 O9 k    for i in rates:5 k$ y/ S- Z4 l& q! E
            user_rank=(i[1],i[2])
    $ L4 Z( z+ D0 b        if i[0] in user_rate_dic:
    " }& m! z; g6 T            user_rate_dic[i[0]].append(user_rank)
    4 ^5 Y$ b' H5 F$ R" L        else:# X5 r* v: w! @' h9 d- ?
                user_rate_dic[i[0]]=[user_rank]
    ( M/ {# O' b- \2 Q3 ^" J              s8 `" C$ j" {9 _# t0 g8 e
            if i[1] in item_to_user:6 z5 C" V, y' X/ k& A
                item_to_user[i[1]].append(i[0]). k( ]9 m1 ^! x4 b; q4 T
            else:9 q8 a4 X9 ^$ ]7 E. G
                item_to_user[i[1]]=[i[0]]
    % c& {7 a4 s$ j4 v+ E) I            # s$ ~- H" K/ B5 E2 t* \$ {
        return user_rate_dic,item_to_user
    1 n& e2 ]* m" X# q/ ]2 F/ ^3 n) l4 B2 K6 o. L

    : c- o/ a3 v8 c/ v1 Y1 C& K#
    - R7 K6 R1 n2 w$ c#   计算与指定用户最相近的邻居/ X+ l7 |* h3 b! u
    #   输入:指定用户ID,所以用户数据,所以物品数据
    " Q; E% M% e/ A* p1 m#   输出:与指定用户最相邻的邻居列表
    7 N) z/ W7 r: A  ^1 W% T% ~#
    . V# D1 }" B* x; `def calcNearestNeighbor(userid,users_dic,item_dic):9 P& u0 o- B  a( ?9 H" z" O: V
        neighbors=[]
    ) D, P$ ]- G6 F0 ]7 C3 O    #neighbors.append(userid)6 `( v- ]' R( D( Q  G1 B3 w! e
        for item in users_dic[userid]:
    : n! y4 x4 ~$ O        for neighbor in item_dic[item[0]]:2 n. I& \" B8 G, W& {" h, Z
                if neighbor != userid and neighbor not in neighbors: % @3 R" @* D; \6 T& m* n6 g# m5 ]7 @
                    neighbors.append(neighbor)0 e6 K/ n( v6 e4 G8 C
          
    # K9 p; f7 Z4 i0 ~- s& O    neighbors_dist=[]: [  f( p! x: g5 \+ w! y
        for neighbor in neighbors:
    : H4 H( F& \" I" J0 X. D        dist=calcSimlaryCosDist(users_dic[userid],users_dic[neighbor])  #calcSimlaryCosDist  calcCosDist calcCosDistSpe& n6 n+ [' h* I  g0 ^
            neighbors_dist.append([dist,neighbor])
    - r! i% Z1 E3 x5 A; f    neighbors_dist.sort(reverse=True)9 U$ h2 _$ {; R- n7 P% i$ I7 Q
        #print neighbors_dist! k8 a% I% Q9 m1 t5 X! \
        return  neighbors_dist7 N7 |. r" [! W

    & y* R9 t, s. p( e& s7 S/ `: J4 g( K$ X- h, @: ]
    #; K% N! J) I5 p  B) S
    #   使用UserFC进行推荐9 r7 f0 I+ H! j4 R6 g1 g
    #   输入:文件名,用户ID,邻居数量: U1 L, v, Y  V/ K' K; t/ ]3 r
    #   输出:推荐的电影ID,输入用户的电影列表,电影对应用户的反序表,邻居列表" G& Z; s  S: L
    #
    + R* ]0 {" U+ s3 |def recommendByUserFC(file_name,userid,k=5):
    & S- H+ \6 Y1 E) h9 {. c# O      r  `6 a+ R* t/ h2 r+ V
        #读取文件数据
    4 K  E) [3 C7 r: S+ ^; k7 n4 c    test_contents=readFile(file_name)
    3 `; `3 u0 e# y   
    " R. n) @( g5 j0 M& T    #文件数据格式化成二维数组 List[[用户id,电影id,电影评分]...]
    . j7 F* D9 I  e5 c, a) T! \    test_rates=getRatingInformation(test_contents)
    * ]/ O5 G  O8 P    ) @7 K" u. Q" d  |, M, v
        #格式化成字典数据 3 C3 R* @; Z1 \# v
        #    1.用户字典:dic[用户id]=[(电影id,电影评分)...]
    ; O$ G4 Q4 v; x, h    #    2.电影字典:dic[电影id]=[用户id1,用户id2...]
    7 r" g& D5 ?/ ~2 D9 p! V# q    test_dic,test_item_to_user=createUserRankDic(test_rates)2 w; k+ t  l8 T& Y
       
      x; M: g9 |* n    #寻找邻居9 S" i1 Y, |0 f' r/ m1 J& e
        neighbors=calcNearestNeighbor(userid,test_dic,test_item_to_user)[:k]4 `. C1 U( R+ f5 T- g3 {+ w1 f
            
    # |! e1 R' Z. \4 I: {  Y    recommend_dic={}
    ; t' T6 e# n- F; R4 m: ?- _/ n    for neighbor in neighbors:' a% J: x9 B- H+ ?" ^
            neighbor_user_id=neighbor[1]4 t* C( I# H0 R5 \$ b  ]
            movies=test_dic[neighbor_user_id]
    5 {( N& `; ?3 F! A        for movie in movies:) D  ^$ L: H! E% n' F
                #print movie
    # }+ E" g* z- w+ C" u; e            if movie[0] not in recommend_dic:
    * ^8 E, K% j/ n0 Y9 h                recommend_dic[movie[0]]=neighbor[0]
    ) t" G, N( ~+ Y, d  g! X9 Z8 }            else:
    0 D! J4 T% y9 t8 P7 h                recommend_dic[movie[0]]+=neighbor[0]
    & P2 W% U$ Q- Z+ ~    #print len(recommend_dic)6 j1 t1 d+ }9 ~, E0 M
        9 K$ E7 c; b7 u& h, K" W, k
        #建立推荐列表# l6 S3 s, ?6 K$ A) z! ~
        recommend_list=[]& T% S: E3 q' p; S9 H
        for key in recommend_dic:% N+ ]' h& T* U, [' `2 h4 u7 i
            #print key! J  \# t5 R) a9 }
            recommend_list.append([recommend_dic[key],key]); l7 A7 K( n5 {8 P, P
        , M4 @" |7 E% ^9 g3 B! e
       
    ) Q+ x, c" y: c; b    recommend_list.sort(reverse=True)
    1 g) @) @) ?, k; R2 x2 x    #print recommend_list
    9 I( |  }6 o) k5 s, d& z7 g# A* C    user_movies = [ i[0] for i in test_dic[userid]]
    ! |2 n( r% g2 R8 m- B3 _: O3 N# ~  P! T" I2 O* l
        return [i[1] for i in recommend_list],user_movies,test_item_to_user,neighbors
    + a2 @; Z: i5 C    3 b! a& c# W, b7 r
       
    ! u+ D4 d3 m5 Q5 o& b* N5 @+ d1 _1 A8 ]5 r% g
    #
    / c2 n5 {* n5 u' g* f! W4 k, z$ E#
    4 `! `* U# m7 y#   获取电影的列表
    . f8 s; h, k  `& e8 m* O+ H#6 x& q  K- g1 o  l; M
    #
    7 [$ l" D2 Y; a: [# Q#
    6 ^' v# Z8 g5 }. zdef getMoviesList(file_name):# {6 k$ Q5 s3 y2 h5 \* [7 n
        #print sys.getdefaultencoding()3 D' u' N1 f- _4 v7 {8 t
        movies_contents=readFile(file_name)
    $ E! e  r5 g) F0 W1 b    movies_info={}
    * S4 i- v/ J5 F: Z) J( ~8 F    for movie in movies_contents:
    ; m/ S9 c" P) F4 g3 O        movie_info=movie.split("|")% s5 |' u! |' s+ J) ]4 c
            movies_info[int(movie_info[0])]=movie_info[1:]( ^" N# Y# s5 v  [1 p7 R
        return movies_info2 }/ s, M1 T) j9 ?0 q
       
    4 r' k6 y4 A  r   
    ) R5 ]2 G+ r3 P7 E& L2 F$ R   
    5 Z+ ^) L8 i* b# e8 N* C" R" c#主程序2 ?9 w$ V3 J8 n) {' z- R7 ~
    #输入 : 测试数据集合
    ) |7 f( L' N+ \+ nif __name__ == '__main__':
    2 G9 \+ E; k# c' q3 t7 E    reload(sys)7 L- F8 K# p# @5 B' ?0 b
        sys.setdefaultencoding('utf-8')0 ^; {$ }! u% w1 g$ [. m
        movies=getMoviesList("/Users/wuyinghao/Downloads/ml-100k/u.item")
    . z8 |7 O: }) r& ~    recommend_list,user_movie,items_movie,neighbors=recommendByUserFC("/Users/wuyinghao/Downloads/ml-100k/u.data",179,80)
    ! u$ M( L8 \( H    neighbors_id=[ i[1] for i in neighbors]
    5 R$ m9 u, v7 H: L# {0 C+ C: x    table = Texttable()
    . c' t7 R" J) a: }3 Y& n, B. P    table.set_deco(Texttable.HEADER)
    0 w7 Q; F1 c! x' |- \3 t: Y+ e) A* i    table.set_cols_dtype(['t',  # text
    " R9 z7 O1 ?. k$ O4 K' r/ m  ]                          't',  # float (decimal)$ d9 B! L4 }" P9 y# d: m( k* U
                              't']) # automatic
    % y# b* R" A: d( c3 F# Q4 J    table.set_cols_align(["l", "l", "l"])6 u! F1 }8 r3 q
        rows=[]
    4 N. O+ y  K- f) w) {- \    rows.append([u"movie name",u"release", u"from userid"])/ K/ T4 O4 @/ d1 y3 X
        for movie_id in recommend_list[:20]:
    & T; u, k- R5 |3 I% |        from_user=[]# T2 t8 e6 t1 O: k9 x
            for user_id in items_movie[movie_id]:3 T9 l+ y* V6 g% |# h, p1 c+ x3 F
                if user_id in neighbors_id:- y8 |4 v* G( S. ~9 `& P7 w
                    from_user.append(user_id)
    ( _# A/ B9 i3 s& Q4 i5 _        rows.append([movies[movie_id][0],movies[movie_id][1],""])# N3 Y- ^& w8 I* |& J5 ?4 ~
        table.add_rows(rows)
    " b$ _+ W& a+ F# @+ W3 i4 w    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 , P2 r  i& `* d/ U
    # -*- coding=utf-8 -*-
    0 c) P- R, N/ I
    4 }, T9 u% U  p7 a5 uimport math

    ' w* I* J$ M! C8 |; W% v这是什么语言的程序?; q9 N2 m1 S$ t
    回复

    使用道具 举报

    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-10-25 22:30 , Processed in 0.987191 second(s), 67 queries .

    回顶部