QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 5253|回复: 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
    本人在学校参加暑假培训,需要这个算法做题!求大神赐教,感激不尽
    5 _7 ^6 V" R% x+ {$ e8 X
    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 -*-2 R8 ^% C2 M5 o# D: X1 H

    ( ?2 t+ F& r: ximport math
    6 S$ r5 ^/ @# T/ Y" G# E- G) bimport sys
    ! P! o( \2 n3 X: [: K+ U3 {from texttable import Texttable5 I) C! C# m% N; `* D9 @4 D- P5 K- H* z% c
    4 `# D$ R2 B7 z" j

    ; _, e8 a' a- _9 Y+ V) Q/ y2 S#; y# ?2 l7 p" b- j' Z* O# z
    #   使用 |A&B|/sqrt(|A || B |)计算余弦距离9 D- ~" ?9 @1 Q1 o: C1 K
    #, I4 I7 d+ M1 d. f- `3 `+ h: N4 O% x6 ]
    #3 e) ~; e* d: d5 z# F8 r
    #
    3 D- p8 Q: k7 g* i7 ldef calcCosDistSpe(user1,user2):8 q5 o& x& p; ^& O
        avg_x=0.0& V; h; D8 A  \5 Y8 [! x
        avg_y=0.0+ y6 c! k0 x/ y( A
        for key in user1:
    ' [1 C2 U5 {; ^, ], G        avg_x+=key[1]" _, J( N9 E+ J0 {8 A; n
        avg_x=avg_x/len(user1)
    ! |* r7 a/ j$ \8 {: b" m    # r$ o! x$ U1 P6 u# b0 E8 E
        for key in user2:
    % F& H" _6 _( C        avg_y+=key[1]
      T2 [3 q% }4 k& j    avg_y=avg_y/len(user2)
    " h' O, Z3 o8 Q. p    8 U1 `1 e4 p- F2 f% _( r8 }
        u1_u2=0.0
    7 S: Y; k- u5 m" C2 ]# A) v# c    for key1 in user1:8 r+ m3 ~6 \: L7 {
            for key2 in user2:3 |8 f8 m, K2 y# K7 P! `
                if key1[1] > avg_x and key2[1]>avg_y and key1[0]==key2[0]:
    % k0 k4 J5 E  E; t/ d2 q; T& O5 n                u1_u2+=1
    + z# ~1 X: h. v! b: h; ~, z; V    u1u2=len(user1)*len(user2)*1.00 a+ ~/ e2 L9 L" T& U
        sx_sy=u1_u2/math.sqrt(u1u2)
    " ]% b) Q6 T$ j6 O! C% ?5 l4 T4 G    return sx_sy. W& S( \6 D. }

    5 S2 j  `' O6 Y4 s# B8 d* P* b6 Q; [* Y4 D/ \( G# I  x
    #( G7 W; k  [, O) }  `
    #   计算余弦距离
    ; y, d) ~6 h7 m" Y, U$ D#! E) b* [* C1 `* K: n) X
    #
    0 m! `; U5 u9 f6 f# Q# L. }def calcCosDist(user1,user2):
    8 i. z, j( L4 b1 B& N7 N    sum_x=0.0
    ( s+ ]% _) T3 \# N    sum_y=0.0' X) Q2 x' c. g( p9 i- h
        sum_xy=0.06 H. O2 c$ j6 i* l
        for key1 in user1:
    . Y7 A2 w' x7 w( F, r" r6 l% r        for key2 in user2:1 a0 x0 u- g/ C* n; i! ~
                if key1[0]==key2[0] :
    ; O9 |* A: `/ e! h0 o7 Z                sum_xy+=key1[1]*key2[1]  L% e3 a. b  M' l! r" `
                    sum_y+=key2[1]*key2[1]
    9 t/ Z2 R- _5 S                sum_x+=key1[1]*key1[1]
    4 q2 a5 Q. W9 x% X0 Z    6 F4 D$ W6 L8 M! |" t/ H9 x  [8 ?
        if sum_xy == 0.0 :# d4 y  K7 g- G- N+ B
            return 0
    2 n7 Q  C* }/ O) I  \" Y! D4 i5 x    sx_sy=math.sqrt(sum_x*sum_y) ; s, n, i) X% _! q+ G4 |8 v* [
        return sum_xy/sx_sy
    ; `8 k6 N3 J: r6 Q) h# X
    1 G# z  |# ^1 P$ I! u& }' @, D5 [4 u, ~2 U
    #9 ?* C7 V2 d& q! l2 {+ a" H
    #5 Z' l) z$ D6 x1 M$ F5 N
    #   相似余弦距离
    / v( D$ O) \$ c#
    / w2 A, O! H* Q: E) w, _! E#( r  k; y, \0 A# l
    #: l1 `, g0 w1 K% G  w! {9 ^& d' c
    def calcSimlaryCosDist(user1,user2):8 a  w/ ]" k5 o
        sum_x=0.0/ s* t) D  \% a6 A: [) X; Y9 k
        sum_y=0.0/ Q7 x, U9 h) {+ K' `# A
        sum_xy=0.0* H% X$ E8 _9 K& o8 q  G- \
        avg_x=0.0
    & F- Y% Y. D% a9 D    avg_y=0.0; D/ {- M! z; b
        for key in user1:
    6 `) I! P: a5 S7 S        avg_x+=key[1]
      p* y4 X6 i* T* [' B    avg_x=avg_x/len(user1)
    : C% N4 G$ j; f& H6 y    8 t5 _. F) R2 g
        for key in user2:
    ' y4 {# l- R6 ~) Y  ?+ a; W        avg_y+=key[1]
    $ [/ E0 Y  d2 C. L) ]    avg_y=avg_y/len(user2)
    - N; @$ T) k8 {$ ~   
    0 v+ B& o$ Z7 [& [8 g    for key1 in user1:) r9 s: M  @4 b  F9 u) [
            for key2 in user2:* f: A9 E" Q8 H4 Z2 b# a
                if key1[0]==key2[0] :! W  v/ t, m$ o8 v' k
                    sum_xy+=(key1[1]-avg_x)*(key2[1]-avg_y)+ Q- c1 K! Z, ?/ a' k$ r% \
                    sum_y+=(key2[1]-avg_y)*(key2[1]-avg_y)
    ; G' T2 ?7 `7 B* V3 |5 }        sum_x+=(key1[1]-avg_x)*(key1[1]-avg_x)
    $ m4 d7 H0 K' [( y& _7 {   
    * N* b. L" M7 C0 b    if sum_xy == 0.0 :, t9 R& p: w0 l8 j+ p+ p' Y
            return 0
    . s$ j$ Z+ f( }, J$ s    sx_sy=math.sqrt(sum_x*sum_y) 7 t' u9 L4 g5 ^- K+ C
        return sum_xy/sx_sy
    ( q& x4 i, \- w+ i& t    * `+ N! o. k+ e  T5 L8 z$ a

    ( S2 s$ y2 b  y5 W#
    / s5 ?4 v& l( A0 O4 z) {, ?#   读取文件
    ) }+ f% E* |" e( l3 i#0 S- `6 f6 u, n% }/ Y) {
    #7 \1 L. [! m* u5 \7 Y8 }9 v
    def readFile(file_name):
    2 S7 B4 \+ K4 B5 y: b0 f$ ]    contents_lines=[]$ T" f+ Q% p9 T  E$ x
        f=open(file_name,"r")
    ( E" `" `: H/ N& s    contents_lines=f.readlines()
    ; Q9 L4 l0 ]0 ], Y    f.close()/ R8 \2 o$ S  B- ^
        return contents_lines( j& m, {5 T! B1 x" @9 w
    ' r- n, [/ s% j  h
    . I5 ]/ ]: [' t6 D% }! [
    6 y5 `; K1 ~" O$ z' \+ x
    #
    ) i3 @: @8 ?( H/ v+ P: K#   解压rating信息,格式:用户id\t硬盘id\t用户rating\t时间
    " ~8 u. J) U' A/ z. B#   输入:数据集合
      J5 ^7 L' P2 s  c6 F  [0 f  p#   输出:已经解压的排名信息+ W/ Z6 e) u/ b& x
    #1 s9 v8 G+ \+ ~6 O) r
    def getRatingInformation(ratings):. h5 Y$ J9 m3 \4 K9 |$ r5 G+ b
        rates=[]
    1 C- t: _% |7 L; [. I    for line in ratings:
    ( E9 n% A/ \6 [0 w* }/ ]        rate=line.split("\t")/ I+ G* N+ C" O4 |+ i$ t7 ?
            rates.append([int(rate[0]),int(rate[1]),int(rate[2])])
    6 P4 k, f% R* h* R8 b    return rates! ^5 B& B* a+ j9 {
    * Z+ _0 M+ Y5 w4 \7 ]6 \( r

    2 ]. T0 K1 f8 L1 K: v#* ]. p+ [6 }( B
    #   生成用户评分的数据结构  m: P9 C1 R$ w* i) _
    #   ) E3 |& Y* q- z6 [
    #   输入:所以数据 [[2,1,5],[2,4,2]...]
    . ]+ ]0 I/ F. m- b) E0 G" e$ W#   输出:1.用户打分字典 2.电影字典
    9 g& f  [8 t: z4 ^8 D9 k#   使用字典,key是用户id,value是用户对电影的评价,8 s9 L2 H1 E: M. F9 x% q
    #   rate_dic[2]=[(1,5),(4,2)].... 表示用户2对电影1的评分是5,对电影4的评分是25 d/ p& c/ L& T
    #6 a2 x4 ]; Y* {
    def createUserRankDic(rates):
    6 R; C, I4 M5 J- z; Q2 i    user_rate_dic={}
    - |9 v. K* b& k/ j  J    item_to_user={}% o( {- j9 m5 G8 x/ F1 d& M
        for i in rates:
    ! D0 G/ x( j: Q, o        user_rank=(i[1],i[2])
    1 V- S* N) v9 u4 I+ i2 O        if i[0] in user_rate_dic:' r8 }5 _9 K) ^% E! t, P+ i2 A
                user_rate_dic[i[0]].append(user_rank)
    8 u) B: r- R' {        else:
    . n  L& w# `4 k+ f' i/ R  m            user_rate_dic[i[0]]=[user_rank]+ i9 A* O! H! O& ?- n" S  w
                
    3 `2 J1 ]0 ?/ B% v6 r" I/ o        if i[1] in item_to_user:
    4 E" N. G6 n7 y            item_to_user[i[1]].append(i[0])" L( H4 g! _" Y. Q. h9 S; h+ l5 {
            else:3 \( p1 c; U$ x! w0 Q2 X
                item_to_user[i[1]]=[i[0]]
      T: ], q# Y; o9 |7 Q            . ]! S* ]! h! p/ B: E
        return user_rate_dic,item_to_user" d* H; G1 O: @$ S
    2 \# K2 T) }3 l' E* N7 K2 [, c+ R

    - B6 s% {+ s) b7 e#  W6 h, W  P; i8 [
    #   计算与指定用户最相近的邻居
    ; w; K/ G. _1 @1 ?6 N$ {#   输入:指定用户ID,所以用户数据,所以物品数据
    9 Z( \1 s6 W1 u4 |4 m  \5 z#   输出:与指定用户最相邻的邻居列表
    4 \% `; C( A- S- u#9 m3 v6 x6 S' w  D; H0 i) H6 h( _
    def calcNearestNeighbor(userid,users_dic,item_dic):$ ^  |+ G+ j; Y5 k) P7 r3 S& J
        neighbors=[]/ X6 V7 O; n1 A# I- y
        #neighbors.append(userid)' d; Q5 W) \6 p3 `0 L) K
        for item in users_dic[userid]:
    8 Q+ ~" y+ U' G) u) q$ o3 q        for neighbor in item_dic[item[0]]:1 A& Q. L2 n3 ?% E9 {
                if neighbor != userid and neighbor not in neighbors: * Q. a3 n( k0 J9 ~+ E8 z4 {& c
                    neighbors.append(neighbor)
      Q: w: ]1 s; B      
    ' G- F7 J) X- l! y: c    neighbors_dist=[]
    4 v2 J5 X6 c: V3 w9 p/ t    for neighbor in neighbors:) k) r' J4 X  r
            dist=calcSimlaryCosDist(users_dic[userid],users_dic[neighbor])  #calcSimlaryCosDist  calcCosDist calcCosDistSpe
    - a0 Q0 u( z: [2 `; \        neighbors_dist.append([dist,neighbor])
    . M- o8 [4 m) N/ \    neighbors_dist.sort(reverse=True)' ^/ r  q/ b1 U( N; V6 T2 G
        #print neighbors_dist! r0 l: U7 U3 V2 |  a+ E8 H
        return  neighbors_dist
    ' W9 R  `1 o3 J: N9 ^" G% }! N7 l, Y! C
    8 ?, u& r! \3 |  |8 V7 t9 |" }0 l4 l( N5 k  v2 v5 y" U/ L
    #/ P7 \$ T' \7 F2 Q7 [2 w
    #   使用UserFC进行推荐
    3 t$ p  ?, v+ D7 J/ E0 }9 w% ^( B#   输入:文件名,用户ID,邻居数量/ U3 y5 ~; e5 l* t) I* y; ?3 d
    #   输出:推荐的电影ID,输入用户的电影列表,电影对应用户的反序表,邻居列表7 l2 s* E/ Z8 `( i3 c
    #, E# C# A5 B0 _  i( I
    def recommendByUserFC(file_name,userid,k=5):( u% i" `$ ?; k8 |' F4 S5 |
        6 U, J8 q+ U2 n* a& }
        #读取文件数据- a. N! j; i, |2 [5 A, `, [% \% X: i5 H
        test_contents=readFile(file_name)
    ; N. K2 a" `/ x9 t" ~  ^    ( L3 \# b' O) Z" \8 [4 M
        #文件数据格式化成二维数组 List[[用户id,电影id,电影评分]...] , L6 S3 c7 U% l9 n# u' e
        test_rates=getRatingInformation(test_contents)1 x. ?" k3 ~$ M9 f8 p, T% e
       
    % P; ]2 S8 M( x+ ^) {5 }& s    #格式化成字典数据 1 ]# j4 l4 @1 j3 s& X( m$ B( [
        #    1.用户字典:dic[用户id]=[(电影id,电影评分)...]  `) D4 I, D3 k/ X5 T. l
        #    2.电影字典:dic[电影id]=[用户id1,用户id2...]0 C- y0 w0 h; v* u- o0 k5 B; ?
        test_dic,test_item_to_user=createUserRankDic(test_rates)
      \# Y1 I& n+ j3 [4 Z! q   
    " U* R8 K! M. m2 u: e    #寻找邻居
    , H7 g7 G7 J; C    neighbors=calcNearestNeighbor(userid,test_dic,test_item_to_user)[:k]
    $ W9 S& i4 a4 A; T        
    . t( f2 j$ b( r: {& W    recommend_dic={}" |% Z5 o1 B7 o& O% a; r
        for neighbor in neighbors:
    # I, v& A" e" m4 X        neighbor_user_id=neighbor[1]& \* V3 V8 d, b/ a* v/ r
            movies=test_dic[neighbor_user_id]4 ^% l3 Y& w. a" ?: @' ]' R  C) Z8 O
            for movie in movies:
    ; f2 P$ w& S' z$ X            #print movie/ F# t6 K1 ~6 V; U2 S2 e( Q
                if movie[0] not in recommend_dic:& ]/ E; ^5 L2 e2 k: R* z* m% x0 F9 [
                    recommend_dic[movie[0]]=neighbor[0]9 h, x7 h0 j8 T, K  ?  B4 y" i9 L) J! f
                else:
    $ s0 O/ h; J6 l% Q# R- a" ]                recommend_dic[movie[0]]+=neighbor[0]. L1 C) b8 s  }6 v* s3 L/ @9 _0 L
        #print len(recommend_dic)
    & e: Z" M) g& x4 ~6 L   
    / V) Y- N  P& [  ~) _" p    #建立推荐列表; b, {7 I* v  M7 B8 `( U
        recommend_list=[]
    . |+ Z. a+ S1 y4 n8 G    for key in recommend_dic:, ]8 ?9 @3 }2 _# s
            #print key: X" v3 L' i) l
            recommend_list.append([recommend_dic[key],key]), F4 k6 N4 [; @2 T" d. N
        5 K8 _" i, i- G* s# `
        ! D/ [4 h# P/ {4 g* M" V* j/ g3 _" U
        recommend_list.sort(reverse=True)
    6 ]% a9 ]2 \" o    #print recommend_list
    + K- l0 q& v2 {: L! \    user_movies = [ i[0] for i in test_dic[userid]]
    - E! i; B9 o5 X& o8 Y# O# \: [0 a) a0 c
        return [i[1] for i in recommend_list],user_movies,test_item_to_user,neighbors
    + o" E: P6 y  m* G; c* i2 q3 i      f$ c: w' I1 d% Q' q% a* ?
       
    4 C5 a4 \1 X2 U8 E+ `
    1 Z. [8 H8 q8 \8 R' T#7 w6 V" n6 Q' q  \3 S+ q
    #; W' ], V7 |- r9 ?# k' W; E
    #   获取电影的列表! \/ u) m" @% ~( B+ Y7 {/ j  @) C
    #$ p$ y6 M0 s3 p* z
    #2 c. S0 s: z2 S0 T! Q2 z
    #
    2 z+ T3 e) S8 V1 j  C( ]def getMoviesList(file_name):3 J/ n# }: J0 E/ i& _) c6 l  a
        #print sys.getdefaultencoding()4 W  I' y2 p" U& d/ Q  m  i
        movies_contents=readFile(file_name)
    * r2 [7 ?& t: O1 X9 c    movies_info={}
    + \7 F$ d( Z$ H  ]7 n    for movie in movies_contents:
    2 K7 U" i4 U9 I, Q# r7 s# a" t3 g1 r        movie_info=movie.split("|")
    + z5 r1 ^- o- h/ o( e. o        movies_info[int(movie_info[0])]=movie_info[1:]
      S& P- Z3 _; p8 b. I. v" ]! {    return movies_info4 A8 W: G! O( {3 V- i
        ' \7 ^; g' ]. k. o7 F# N, ~
        " B7 O% f( I0 g( I5 y' v4 Z
       
    4 o% n: j% Q% ]: F" C  S9 B#主程序
    + ]% I9 b! \. w7 X( a0 {0 B2 I#输入 : 测试数据集合
    # I9 C: d+ O/ `: |" B0 w. \if __name__ == '__main__':
    & i$ h% X0 N) h7 T; s; W    reload(sys)- z& r  n/ y, f6 _
        sys.setdefaultencoding('utf-8')
    4 N9 M' W! o. G# ?# O    movies=getMoviesList("/Users/wuyinghao/Downloads/ml-100k/u.item")9 W' s5 T) a; c! B, k
        recommend_list,user_movie,items_movie,neighbors=recommendByUserFC("/Users/wuyinghao/Downloads/ml-100k/u.data",179,80)# p$ I, T& q& Q: {
        neighbors_id=[ i[1] for i in neighbors]5 k( W$ k& f$ @; @0 ]/ e1 }4 V. [
        table = Texttable()
    ) K! U* P( ^3 B$ M4 v    table.set_deco(Texttable.HEADER)
    - n3 Y4 R- N4 W4 z* I4 z/ S    table.set_cols_dtype(['t',  # text
    ! m2 M( |& y7 ^6 f2 C* b- M                          't',  # float (decimal)" S& A; J; d9 L; h& a2 {5 e  U
                              't']) # automatic
    3 v1 w% ^8 ~! e& B    table.set_cols_align(["l", "l", "l"])" e8 ~" `) j: p( I' n0 r0 G
        rows=[]
    4 q7 B' {- W' i2 D& b    rows.append([u"movie name",u"release", u"from userid"])
    0 M& d/ x# N) p% \4 z    for movie_id in recommend_list[:20]:/ ]" u) a9 a0 C
            from_user=[]
    $ w' g2 [, o  v        for user_id in items_movie[movie_id]:9 S$ I! n9 J; S5 {4 T5 A0 H" k( Y
                if user_id in neighbors_id:
    " Y' u4 ]- e' u9 J4 f                from_user.append(user_id)0 [& s5 `4 X8 F2 s, E
            rows.append([movies[movie_id][0],movies[movie_id][1],""])
    # M/ g% N* l5 |+ I( ~# G    table.add_rows(rows)" p. p# n: s. w: \; x2 L
        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
    / S6 c7 s' W" J* M# -*- coding=utf-8 -*-
    # l2 b$ _& g; N
    + O/ X9 i5 s/ V' _# ^5 Dimport math

    0 b# i" ^6 w% {/ V% D; N1 C5 G这是什么语言的程序?' L9 N( S4 d! _) k2 m/ p+ `) T6 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-16 00:11 , Processed in 0.614824 second(s), 68 queries .

    回顶部