QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 5167|回复: 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
    本人在学校参加暑假培训,需要这个算法做题!求大神赐教,感激不尽
    ! }4 b- E. k) H! f0 k3 O
    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 -*-& b; m2 Q/ n% M/ e
    & X: {: b- p5 t6 j
    import math' l- m: R7 {% I2 |; S+ S: |
    import sys  _: g4 V1 c% H% W5 W+ }
    from texttable import Texttable* D& f0 L2 J+ L4 G2 e
    6 [7 ^+ `1 b/ a) D# U. R

    2 a  N, W0 }& `- [( Y; }#  d& f( o6 E, d: L9 {* ~* Y
    #   使用 |A&B|/sqrt(|A || B |)计算余弦距离5 f. ~( y( U, E; T7 l
    #
    : W6 e- x3 C3 p- r#5 R5 ^# J8 Z( d' }2 Z8 Q) L
    #3 W; I- a" J6 I. F& L: V
    def calcCosDistSpe(user1,user2):. V2 k5 C" d$ w/ g# ]4 A
        avg_x=0.07 x6 U" w; c; g4 {
        avg_y=0.0
    % Q2 F" |) Y0 f8 ]+ U+ i: r6 \6 N% ^    for key in user1:% @- B  ~# _; |1 P5 E* {
            avg_x+=key[1]: ?: {5 t9 `0 i1 a9 K
        avg_x=avg_x/len(user1)2 G4 \5 g/ N: S7 Y$ m* k! G  i2 b
        9 c7 i$ n7 \* K* k
        for key in user2:
    - f& g6 S' _4 V. w! L- k' A7 M, e; h( J        avg_y+=key[1]
    8 }8 w+ j3 s  B0 c; f7 z. c2 O& G4 i    avg_y=avg_y/len(user2)
    7 W- v+ \& b" t+ ?) V   
    ; G0 X6 l6 L1 I' ^" Q! o    u1_u2=0.09 r, X" J8 \* D# {# @4 A5 ?. t) n
        for key1 in user1:+ e! k2 v* f: O* f# n
            for key2 in user2:' H3 C* C! f* R: p
                if key1[1] > avg_x and key2[1]>avg_y and key1[0]==key2[0]:
    8 {. X- S; P; d4 ?" r! v5 V8 a3 a                u1_u2+=16 ?' ~' r, Q6 ~
        u1u2=len(user1)*len(user2)*1.0
    # k; y5 i3 W3 K: {2 O4 u9 A    sx_sy=u1_u2/math.sqrt(u1u2)
    3 `7 c8 V7 b7 _2 A    return sx_sy: i4 I2 h( ], Q; I$ a
    , M  n0 h8 A: V6 E1 ?9 W4 V8 r
    & B& X2 ?2 A2 {1 }
    #
    9 \* K! K+ j& y3 P#   计算余弦距离5 P9 O/ \/ Y$ X: u$ c, R
    #$ i) G4 l* Z  L3 ?
    #
    ' Q% a. r% c! I+ Xdef calcCosDist(user1,user2):. X8 j  A3 S; x. Q/ j6 P
        sum_x=0.0+ E* o: n6 |9 [7 O
        sum_y=0.0- w: C8 I/ w/ n% N- G: R# {
        sum_xy=0.0
    " u2 T: E2 M8 B- ^1 C    for key1 in user1:& ~9 K4 S; c2 u8 `7 @
            for key2 in user2:, f. W2 V5 j* W# E, z6 w* H0 q, ~
                if key1[0]==key2[0] :
    - {# d0 |7 \6 G. A, h                sum_xy+=key1[1]*key2[1]& c) {' T$ M+ C
                    sum_y+=key2[1]*key2[1]: J; E+ |( R4 i: ?* n
                    sum_x+=key1[1]*key1[1]! A# d' G2 h  q
        2 s4 p% |2 B# s8 N
        if sum_xy == 0.0 :0 p' a! F3 ^) ]" ^
            return 0
    7 g5 a- w/ n- V    sx_sy=math.sqrt(sum_x*sum_y)
    ' }5 p. H0 W& e( Q    return sum_xy/sx_sy* ?& R9 j9 {( f
    ! P! M0 D& b! D7 Q$ p
      ^, j% b  a2 L' G
    #
    ) b' V( e) {6 W# W) y4 W, S#$ ?5 q# o! y7 ~; j5 g, f* q2 i' A
    #   相似余弦距离
    # }8 ^5 D+ d# y. T9 o4 d* |9 T#4 U4 m. U' U& K6 i3 V  K
    #. Z3 [  W5 w4 q; X7 T
    #
    # w+ l* r% _  ~6 D% ?+ Ydef calcSimlaryCosDist(user1,user2):, v) u% B8 p5 u8 X/ J0 S- a  F/ b
        sum_x=0.08 l( x. ]7 F" [' r" f9 q7 }
        sum_y=0.0
    : P6 X2 ^6 X2 L1 |9 r) P2 M/ I9 K* u" A    sum_xy=0.06 [( V0 K6 _2 @
        avg_x=0.08 V  R: h; C  t
        avg_y=0.0- n8 H3 N' T" D2 _4 G# D7 \! x1 h
        for key in user1:* ^$ d& o$ q) p- k; h1 K
            avg_x+=key[1]% D9 T$ Y' U4 S3 w# h
        avg_x=avg_x/len(user1)# \2 s3 E0 u5 W% ]  n
       
    3 Y$ N/ e- u, R0 q3 o6 g    for key in user2:
    ! @, a% k3 w# d$ G        avg_y+=key[1]) r: A2 S( q( |7 f, W
        avg_y=avg_y/len(user2)
      d% @! u' z. `5 `& G0 [% D& u$ x+ s0 b   
    0 r7 M/ Z7 V9 Q3 j8 r) S* ^0 u    for key1 in user1:# R6 x; J  A# U6 v, D
            for key2 in user2:
    " g! B( C! p; I+ r0 P  i            if key1[0]==key2[0] :
    0 w# Y+ ~/ v' \3 P( r* j9 Q4 \+ S                sum_xy+=(key1[1]-avg_x)*(key2[1]-avg_y)
    8 F7 P$ ^# A8 a. v  v! t5 i3 q; D                sum_y+=(key2[1]-avg_y)*(key2[1]-avg_y)4 I  ]$ Y7 B' n" Y8 [8 e& D7 W* _
            sum_x+=(key1[1]-avg_x)*(key1[1]-avg_x)1 |! x6 T+ i+ G" R. ?
        & M% d8 R& K( D# T; @. R5 q7 S
        if sum_xy == 0.0 :
    & L7 B* Y2 o1 t        return 06 s& T" F6 y6 p  O' |+ ^4 q
        sx_sy=math.sqrt(sum_x*sum_y)
    6 x5 k5 W$ B( _% q- B  R    return sum_xy/sx_sy
    9 }% V& Y* c' N    * y% B" V+ s) K8 O) c8 G- s# E

    0 N% Z; l7 r+ V& M: H#+ j$ G  V/ W; v# c3 ~
    #   读取文件3 x5 E+ n( ]" \8 o) z7 a. J
    #5 E+ d. C6 o9 y$ ]9 @
    #3 o3 B5 I' K  p2 y3 B; R* i. d
    def readFile(file_name):
    ' Z4 }$ Y6 q2 B0 u3 b    contents_lines=[]
    3 \/ L$ m' t% t! |/ z' `    f=open(file_name,"r")
    $ o2 q: A6 I3 a5 T% y$ K4 J    contents_lines=f.readlines()9 P" ]- ~3 K/ p  C, w, ^9 G
        f.close()
    5 I; J, u/ l: L! J$ a+ ~    return contents_lines
    6 S* @$ k$ g: {, ^2 L9 v- i
    - W3 s% c  d: `
    + Y/ C, U7 ~% r2 Q+ A* G
    1 I4 d+ b* E- A) ~5 W- a& s/ K#+ P4 |9 i/ h. d
    #   解压rating信息,格式:用户id\t硬盘id\t用户rating\t时间
    & u6 d* L/ G' ?; \#   输入:数据集合
    2 ^. q; x3 I* C, X/ x/ I#   输出:已经解压的排名信息
    2 Q" k8 A- U% f8 m#
    5 f: k! Z! @% c3 L! d1 gdef getRatingInformation(ratings):0 v* J$ s% s8 w; U5 p% N
        rates=[]! B5 i; ]- k7 J3 l5 u8 Z
        for line in ratings:/ X/ r; X4 a# J1 U. U1 _- W
            rate=line.split("\t")  h/ l8 y5 g& E7 P6 i' Z
            rates.append([int(rate[0]),int(rate[1]),int(rate[2])])
    ; a2 c1 j5 j. b4 Y) B3 R+ e, q" m2 D    return rates
    0 P6 u) S! J- v7 r: w9 ^
    7 D, I& I0 R( L: y! k( _8 a' L; B; F; ?# q3 C( r
    #
    5 ~2 i: i" c9 q#   生成用户评分的数据结构
    9 s& R  ~3 K0 C* e$ A& G#   
    6 h/ ?4 k+ T2 u  o- f; i5 e#   输入:所以数据 [[2,1,5],[2,4,2]...]
    ! |$ Y) w2 F3 ?* B, `% e' U#   输出:1.用户打分字典 2.电影字典, A- ?0 W# Q, P- ]9 m" T
    #   使用字典,key是用户id,value是用户对电影的评价,1 Y+ J& I' ~6 B+ v+ Y, p, e
    #   rate_dic[2]=[(1,5),(4,2)].... 表示用户2对电影1的评分是5,对电影4的评分是2$ j8 C/ I0 [8 A. q% o& f% {
    #$ J+ r, r# q2 ~
    def createUserRankDic(rates):! {* J) |0 D5 H/ b# p# J
        user_rate_dic={}1 a7 B8 u: e' Z
        item_to_user={}
    8 `9 y" o( N& |* u- }& P    for i in rates:
    ! m4 v: y5 n" ^        user_rank=(i[1],i[2])2 t6 {7 {/ K$ q: a# j& F% n" n
            if i[0] in user_rate_dic:7 e+ X% i% ]$ c$ H7 y
                user_rate_dic[i[0]].append(user_rank)% U  ?$ h. U! l
            else:& }0 S' X- R3 N, o
                user_rate_dic[i[0]]=[user_rank]/ g" h7 W: q" ^8 p' X
                9 l5 Z3 V; ~- H+ l/ ]
            if i[1] in item_to_user:/ I& T0 F4 J; t& r) s% H7 Z
                item_to_user[i[1]].append(i[0]). I4 _* ?5 J7 B( X  |' L
            else:9 x& E0 S! A8 M- i
                item_to_user[i[1]]=[i[0]]6 q% \8 M+ U6 E) N
                  ^  g- u0 R" {7 [( n8 F3 K
        return user_rate_dic,item_to_user
    9 m  e2 W9 y2 ~, Q+ z' ~
    ( ~* j# i7 r- n( c/ N8 ?7 F
    / _6 |7 |0 |- X#
    5 G& j! p! s6 }' e7 E# p  L+ r, ]#   计算与指定用户最相近的邻居
    - ^  R3 p/ Q! Z9 r3 m" Q3 O#   输入:指定用户ID,所以用户数据,所以物品数据  j: c- D; |, x0 d4 A& i' ]( B
    #   输出:与指定用户最相邻的邻居列表
      Y- Y8 _1 H& R/ O#, m9 E8 [9 I& r" q/ I$ J- P# z
    def calcNearestNeighbor(userid,users_dic,item_dic):& C( M9 I9 |" H7 L
        neighbors=[]
    0 B+ j1 i/ F! K  G. _    #neighbors.append(userid)
    , {6 q' \, h' p4 w    for item in users_dic[userid]:
    + q& e! V* T3 Y2 Q        for neighbor in item_dic[item[0]]:
    # ^/ ]; k; t. w( q            if neighbor != userid and neighbor not in neighbors: : F' _: G5 H0 r! Q) B( [0 s( S
                    neighbors.append(neighbor): U9 T0 B4 ]4 o% B
          
    + z0 H% i6 J1 C4 F' ?; o  P& p    neighbors_dist=[]
    8 \$ b4 ^4 V) Z. G    for neighbor in neighbors:
    4 r3 i2 X, N' z! ^8 L  V        dist=calcSimlaryCosDist(users_dic[userid],users_dic[neighbor])  #calcSimlaryCosDist  calcCosDist calcCosDistSpe/ D! E* i2 x2 I" _' j) M  \3 i. K
            neighbors_dist.append([dist,neighbor])& D* T) e7 V+ C( y4 M
        neighbors_dist.sort(reverse=True)
    3 t, c1 i9 f5 j& k3 t* L    #print neighbors_dist8 U; a( \$ V7 ~9 j6 }% b
        return  neighbors_dist
    8 c7 \- e( ?( d8 G# A# ~$ k. ^; C- c' i6 A! j8 e: W
    $ Z  E1 R3 }) ~' B
    #4 X3 c; s! {  V' P: N
    #   使用UserFC进行推荐! h4 ?. b9 b: b
    #   输入:文件名,用户ID,邻居数量
    6 z3 @& x6 a# ?; o9 A6 ^" ?#   输出:推荐的电影ID,输入用户的电影列表,电影对应用户的反序表,邻居列表4 `# P( W' q( U$ O
    #  m: L. D# c$ t5 v' Q
    def recommendByUserFC(file_name,userid,k=5):
    ; e% f. I' S- ?: ~1 W, A+ V   
    # s8 H. W9 N2 X9 N    #读取文件数据" Q! ]2 A. |6 R8 I
        test_contents=readFile(file_name)
    0 P9 E% n2 Y+ ]- Z" }4 f   
    5 k  ^, ?$ [: b7 k& o6 Z    #文件数据格式化成二维数组 List[[用户id,电影id,电影评分]...] 1 L; @8 v! o1 T! ]4 G$ T3 {2 d+ y1 [
        test_rates=getRatingInformation(test_contents), @" J4 i! o; p5 z; [- \6 P
       
    * r3 z' H% l+ M0 Z3 X6 ]    #格式化成字典数据 / K. L# L& O- u$ J
        #    1.用户字典:dic[用户id]=[(电影id,电影评分)...]
    5 I; ~+ X; o" I( ^- E    #    2.电影字典:dic[电影id]=[用户id1,用户id2...]( r9 }2 q2 e( A5 r; A) q5 S! ?
        test_dic,test_item_to_user=createUserRankDic(test_rates)! W( b' i0 Q" D& M6 M0 s
       
    $ g, G; z$ c  p5 f! q    #寻找邻居# [. k4 D4 G& t/ q0 C$ P- B% E; Z7 A1 m
        neighbors=calcNearestNeighbor(userid,test_dic,test_item_to_user)[:k]
    0 ~! h2 x: n! a' g2 e1 t- K' P& a        
    . _8 n2 X: p) ?: S    recommend_dic={}
    $ r. r! m1 ], i9 V% E  K4 S( t, ^( h! l" Z    for neighbor in neighbors:3 B. q. s5 W$ s! Q# K; v, ?) s, s4 r( B
            neighbor_user_id=neighbor[1]$ z1 ]8 t3 z! t
            movies=test_dic[neighbor_user_id]
    2 a2 @( S* h  k5 D        for movie in movies:
    2 W; u, }9 Y% J$ \            #print movie: a4 h1 q% L& I& u. U5 ?; q+ V# B
                if movie[0] not in recommend_dic:
    6 r6 |# _9 ^+ N" ]! r/ V                recommend_dic[movie[0]]=neighbor[0]
    - v% B5 D1 C  e$ C- s0 i  D1 z% p! g            else:9 Q1 o! o! u; I+ ]. ^& H
                    recommend_dic[movie[0]]+=neighbor[0]
    % z2 {7 d) ^' t& z7 I    #print len(recommend_dic)& T7 T9 S4 Y- B2 M
        7 b! D; H/ n+ O4 s$ ~+ b3 L+ |
        #建立推荐列表
    " G3 Z! S1 b0 t. e, p5 X' s    recommend_list=[]
    % ~  ~1 Q0 G9 s1 Y  x$ v6 J    for key in recommend_dic:; {* O6 y% O/ G( H7 }; S5 r
            #print key4 \8 v" A2 w$ w8 R3 z2 D
            recommend_list.append([recommend_dic[key],key])+ Z' j  f' R) k8 X+ c- y
       
    , g: B& M+ T5 L  \8 x7 _% r3 _    : M0 A3 m( q2 g" z3 V8 U
        recommend_list.sort(reverse=True)) n8 B( g# {: O) }
        #print recommend_list
    6 X  V  e& q! T3 q2 B( R    user_movies = [ i[0] for i in test_dic[userid]]
    ! A( N) d# d! L2 T6 H- N
    . @( L* ^; g3 W: g: f. d    return [i[1] for i in recommend_list],user_movies,test_item_to_user,neighbors
    1 i4 s- ?9 q* W  K8 I+ T" V9 Y& e. ^    . q( B7 |) q% V; b* O
        1 ^7 J' e* C9 v3 T

    1 ?' U7 G( p# v! M" Q#
    2 G# v. m' R& C, n2 B- g/ a" r2 b#% {$ j% O! ]! w# d. `+ M
    #   获取电影的列表4 j* q: m: I) T4 ^8 Q7 `) _
    #
    2 J3 s7 |+ n) h8 {#
    $ |4 q8 [6 c* F1 `7 K#
    0 V( }; P/ o- y  o3 I, T3 H$ Wdef getMoviesList(file_name):% o# a4 o/ k4 O/ Q3 G! s* J
        #print sys.getdefaultencoding()! `5 C7 b+ `5 F' e& N1 Z$ ^
        movies_contents=readFile(file_name)
    ! q8 O2 P: W/ D% c. E! e    movies_info={}
    . U0 R* P" J. r3 X! y% W    for movie in movies_contents:
    ) H& Z; P( T8 l9 B: Q" O        movie_info=movie.split("|")
    ( J$ F9 e1 @+ C% j# m7 ^: L( P& P        movies_info[int(movie_info[0])]=movie_info[1:]) w3 `" z% S9 u2 v
        return movies_info
    5 p4 p/ I, ~7 `0 Q    - _6 m2 l: l, l  ?
        : I3 E) P" G  @
       
    ) s8 E1 V% P( D#主程序, V7 \- v: a! v# u. ~
    #输入 : 测试数据集合
    7 t) P5 I: O. I- d; G" ^% _2 r7 S/ Cif __name__ == '__main__':
    & J% Z" n9 S( o4 t3 m3 R    reload(sys)
    % O  }: Q) W" z/ L4 k: |    sys.setdefaultencoding('utf-8')
      s' U$ b6 [* z- x3 Q3 h' j    movies=getMoviesList("/Users/wuyinghao/Downloads/ml-100k/u.item"): n8 B  a8 P) \$ T& q* t8 u
        recommend_list,user_movie,items_movie,neighbors=recommendByUserFC("/Users/wuyinghao/Downloads/ml-100k/u.data",179,80)
    , e1 A4 S* C, k6 l' z' A    neighbors_id=[ i[1] for i in neighbors]0 G: m; y! [6 ?! [8 x! _
        table = Texttable()
    - {% `' ~7 A1 D, G    table.set_deco(Texttable.HEADER)+ p, }3 u' j1 y: f5 L) h
        table.set_cols_dtype(['t',  # text 4 \$ ]0 }9 y# A2 g# j# {
                              't',  # float (decimal)8 m- a! |% |- l+ ?& \
                              't']) # automatic6 A5 |* ^* Z/ f# v! ^- d
        table.set_cols_align(["l", "l", "l"]), b7 Q  e, }! F& ]# R" w' x  }
        rows=[]6 ]8 S4 T" y2 Z! [( P
        rows.append([u"movie name",u"release", u"from userid"])
    7 E% q% Y8 A8 {' K    for movie_id in recommend_list[:20]:5 r* G' ~) z) f1 u3 g# M
            from_user=[]
    - ~5 A& W9 T* ~  X; L  r        for user_id in items_movie[movie_id]:  @9 J2 [: T. s% ~- W
                if user_id in neighbors_id:9 \# i1 Z: s5 k$ j9 h. i
                    from_user.append(user_id)& r) {0 M& Z/ ]$ s. {1 q* w
            rows.append([movies[movie_id][0],movies[movie_id][1],""])
    5 s  W* x  N* L, g    table.add_rows(rows)6 u# R( M0 G% N4 p% u; V% E( k
        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 N/ l0 Y$ Z, r2 b# -*- coding=utf-8 -*-9 o2 g6 |8 K5 y3 W/ B
    8 F  H4 t4 h, K1 z. V
    import math
    : @* d- ~; c% C6 i' b8 Y  u6 u
    这是什么语言的程序?
    : p0 W! O1 Q, t& o
    回复

    使用道具 举报

    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-11 04:39 , Processed in 0.542924 second(s), 69 queries .

    回顶部