QQ登录

只需要一步,快速开始

 注册地址  找回密码
查看: 5313|回复: 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
    本人在学校参加暑假培训,需要这个算法做题!求大神赐教,感激不尽
    ! a! z, x2 k+ G  z8 @3 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 -*-1 `% z* `) V# c8 s0 H( {

    % Q. H4 ~$ ~1 Q' x9 K- fimport math
    9 t0 a0 n0 w0 q8 j5 U/ F/ zimport sys' h5 b% p* D, [* t/ q
    from texttable import Texttable# [# y$ n: D0 q2 D
    & U: |8 Z8 @  K# r! u: r3 ]

    ( D; L: ~% m3 H5 R8 N+ a#
    2 _8 H8 Z) `4 g9 N* ]& T4 m" L2 x#   使用 |A&B|/sqrt(|A || B |)计算余弦距离
    : n) g0 p- S) e; d: w. c#0 ?" }; C0 b* I2 t1 [. }0 s
    #' s& E' h! L% d' U+ L3 G
    #
    1 t0 t- n/ h% m8 Cdef calcCosDistSpe(user1,user2):$ G4 W0 _* c$ R; r& N" _
        avg_x=0.03 H$ d% N, z( V
        avg_y=0.0# C* C5 P5 I$ p8 R& y$ [& _
        for key in user1:) ?, l' w' B% B9 m
            avg_x+=key[1]
    * O! Z1 k" j# u0 a2 ^( E. k    avg_x=avg_x/len(user1)
    ( _2 ]/ J8 W8 s+ P9 E0 W9 }    - s# @, [  C0 J& o
        for key in user2:
    . j) Q+ Z. C8 V9 ], @+ Q0 o        avg_y+=key[1]
    + m9 R, p$ w. m    avg_y=avg_y/len(user2)
    5 F0 S0 F  o/ k9 y/ `    : A, o; N7 h5 l9 e5 r
        u1_u2=0.0
    * {/ l+ |% e" I/ H5 R    for key1 in user1:
    & z0 D& {6 J/ w( n% q# }        for key2 in user2:) O, ?0 ~) {" j  v0 F4 L
                if key1[1] > avg_x and key2[1]>avg_y and key1[0]==key2[0]:
    & y# V- t, Y/ U( g0 I                u1_u2+=1
    3 n) F& Z) @, o+ Y+ j    u1u2=len(user1)*len(user2)*1.0+ [7 P, `- u9 I1 W
        sx_sy=u1_u2/math.sqrt(u1u2)
    * |; s& X0 L( F& ]% c4 J) l9 z/ Z5 Q/ K    return sx_sy+ p( ?$ S) y( v+ h

    $ o7 K( S4 f' }  e: S3 D9 c) [3 Q: X! z1 ~: v. M
    #% ?# Z1 |0 N% m: U% O' c
    #   计算余弦距离
    , F* Z* p9 u0 f, J5 t. P#" g5 C' B9 u; L8 L! q, M' l
    #1 N; m- u3 K" `& G/ G
    def calcCosDist(user1,user2):
    ) [. K# Y2 T7 X8 t( A+ c8 Q    sum_x=0.00 C( f- a& U5 B% m2 V" e* V- U( V
        sum_y=0.0
    4 q8 t/ B0 _# G- v    sum_xy=0.07 V& S; S. P9 g) q7 W
        for key1 in user1:% C* `' t* |( o0 ^
            for key2 in user2:
    " q( V4 K! m% O; Q0 s            if key1[0]==key2[0] :& N1 G' G: |& T! D+ w- k. z
                    sum_xy+=key1[1]*key2[1]
      G% O( k3 S3 _& ^# p$ p0 m; S                sum_y+=key2[1]*key2[1]
    ) T$ T1 z3 e7 V                sum_x+=key1[1]*key1[1]# v& U0 k8 K1 u3 \$ F& U; N. Q$ u+ B
        8 ~% s  I0 ]# g
        if sum_xy == 0.0 :
    7 d% f' i' o! ?- q1 n        return 0
    $ V- i9 U0 t; }: Q8 Y9 P5 a    sx_sy=math.sqrt(sum_x*sum_y) 7 I" N  ~. z" A7 Q4 t6 V
        return sum_xy/sx_sy
    1 J" e9 l& c+ }2 i) Q9 w7 g0 l7 |" X! s
    ' S0 {! P$ P' p1 [, t
    #
    : J# @% G' |, J" q( u( M#8 ]6 x8 P+ }2 W0 r$ ]4 z( Z
    #   相似余弦距离% k' _; z( G  h) d1 _) u5 \2 v& k
    #7 }3 m; c4 O6 b
    #
    - M) {3 x7 ?8 w#2 f$ u) U9 L6 W0 I; @) l
    def calcSimlaryCosDist(user1,user2):5 |5 W  i% }! a" E- y6 s- F
        sum_x=0.05 Y. u; P4 u8 N/ K- I! x
        sum_y=0.0
    ; h  K) a- h7 M# z5 Q    sum_xy=0.0+ P' Q9 A3 m! D6 G6 t
        avg_x=0.0+ d. O9 y7 z& m
        avg_y=0.09 k6 X+ \8 ~' n$ w  @9 q0 t
        for key in user1:3 X: N6 P, t6 ~
            avg_x+=key[1]
    0 e! Z* `. E) Z% H( G    avg_x=avg_x/len(user1)& V* I3 k( ?/ Y% b# z
        5 z$ S) a3 _; R: y  W2 E
        for key in user2:
    * P$ `5 k" r' s' C2 `9 `) ?        avg_y+=key[1]
    ( Q! X2 d# B4 P: V' `$ d! n    avg_y=avg_y/len(user2)
    3 p- ?+ P( \3 m! P/ k    & I0 S& C0 a" s/ m! x
        for key1 in user1:
    1 R" x. a$ c* R8 w: ]6 `1 C        for key2 in user2:
    " {, \5 H9 ]( D" n/ |            if key1[0]==key2[0] :
    8 B" l( N5 F+ k                sum_xy+=(key1[1]-avg_x)*(key2[1]-avg_y), j( r$ l" q- b+ U2 c
                    sum_y+=(key2[1]-avg_y)*(key2[1]-avg_y)0 {0 O# l( x/ S/ B' L
            sum_x+=(key1[1]-avg_x)*(key1[1]-avg_x): r9 v; F2 l. X# Z- K& d% J% q  {
       
    + y+ w! J7 S/ B8 X% ]    if sum_xy == 0.0 :, K4 n6 `, b( W3 K' d+ K
            return 0
    ( [7 [2 s* }" K    sx_sy=math.sqrt(sum_x*sum_y)
    3 B, c- p/ P4 U" g    return sum_xy/sx_sy
    * z! O, z! j* ~& c0 T   
    3 ]" H: L% t4 E: W7 g; T, I' ~0 ~) w$ O% B
    #) E& H: k* y6 u+ q( c, L% J5 v/ w
    #   读取文件
    ! `) \) ]! k0 r2 c; ~  I#
    ; T3 U9 u8 q+ G1 z" }9 D6 c% T#; p+ s6 `: ~5 L) ]7 q2 ?
    def readFile(file_name):: o/ ]/ K6 y/ k# A0 D9 N
        contents_lines=[]
    + C+ Q- Z8 _, `    f=open(file_name,"r")
    ; _* `4 ]$ E6 N: f) }5 X    contents_lines=f.readlines()
    ) [  E# R& L( i2 v    f.close()  E3 a+ }: @- H# s% O
        return contents_lines
    , V, t, |- q' U9 I; X; j
    5 R7 K8 N  s' ]
    8 Y3 e1 s$ h" h/ n& X6 b' i7 R9 k( R/ p# |- @
    #
    1 h/ O* Z2 z. X% m0 i#   解压rating信息,格式:用户id\t硬盘id\t用户rating\t时间1 o7 n3 D# s+ Z6 `& u, V
    #   输入:数据集合- f& e+ I8 X( S  s! i9 d
    #   输出:已经解压的排名信息
    5 s8 G+ R, [7 O#; ~9 |" o4 m3 a- I1 \& l- G
    def getRatingInformation(ratings):
    9 e/ Q7 L% ?! O& X# W    rates=[]6 g5 I3 B1 W8 ^3 z
        for line in ratings:
      J" B( j( n. L! W. o        rate=line.split("\t")
    / X6 S' i3 A; F0 @9 j        rates.append([int(rate[0]),int(rate[1]),int(rate[2])])
    5 ^- [# h1 O3 M6 Z( {5 u    return rates$ y$ ^+ }9 [1 X  n

    & R6 ~  L1 F# N! A9 H, ?  h! q# h0 I, }1 ?- O# }7 j6 \8 y; Q
    #1 j( p4 O9 _$ k  L* L- f2 h1 m
    #   生成用户评分的数据结构
    % G9 w8 V, T5 b* P; M( |4 T#   
    ) E1 g9 E1 \( s# P7 c: M* |9 ^#   输入:所以数据 [[2,1,5],[2,4,2]...]
    " a- R2 j" m5 M1 e( q- n#   输出:1.用户打分字典 2.电影字典% T; ~$ F- t( l% d& A- Q/ E
    #   使用字典,key是用户id,value是用户对电影的评价,
    - M1 X) a$ [, n0 m. r' q#   rate_dic[2]=[(1,5),(4,2)].... 表示用户2对电影1的评分是5,对电影4的评分是2
    0 y1 g. s9 \) i/ [#9 b) L( i# {5 w" K( b$ M6 n
    def createUserRankDic(rates):4 n, e% E! b2 ~, o0 e6 K+ p
        user_rate_dic={}
    # ~( N2 s& \& A0 N6 a8 r    item_to_user={}3 _7 h2 C4 e1 d4 l
        for i in rates:
    2 |  P2 M) t  f; s' V( f1 v        user_rank=(i[1],i[2])# k7 H  R# |& }* G
            if i[0] in user_rate_dic:- |/ `2 d, Q: v( _+ F9 ?1 v
                user_rate_dic[i[0]].append(user_rank)/ X! G: q: h6 l: o7 y
            else:$ ^. ~% ^( ^3 s3 _1 J
                user_rate_dic[i[0]]=[user_rank]
    3 ?( v$ i; M& @/ G" O% U' u            
    " f. O( E* ~5 J- M9 B        if i[1] in item_to_user:" l* Z5 I  p! A1 _0 B
                item_to_user[i[1]].append(i[0])
      W% J1 ~$ z: @+ {: {( U. j        else:
    ' @6 h# U  y3 ~  E            item_to_user[i[1]]=[i[0]]
      D3 B: }' f& h4 z* v; A; C            
    ( W, ^% W; h! B5 H7 M. x3 H    return user_rate_dic,item_to_user, _; `5 B. \. O0 M9 h# [

    ( F. {3 R- d2 w
    & S" s# g4 ^2 p) [1 H( z- k# C#
    " A! V6 m4 z2 d#   计算与指定用户最相近的邻居
    0 i# V. u$ }; B+ d0 x( t; x#   输入:指定用户ID,所以用户数据,所以物品数据
    * J2 {- `) |* D% z, l9 G#   输出:与指定用户最相邻的邻居列表
    $ d: B$ g% ]7 x; m; y#
    9 \9 U6 H$ q# H5 B  C+ d8 S$ Fdef calcNearestNeighbor(userid,users_dic,item_dic):
    ; j: r/ Y. q# o, Q# _! T: S    neighbors=[]4 g# K3 }6 e- T8 P- {
        #neighbors.append(userid)
    " Y2 W; {) N4 C* V    for item in users_dic[userid]:1 Y) I2 Q7 K1 G  {2 B. E
            for neighbor in item_dic[item[0]]:5 J1 p5 }/ [. i! l; K2 W# l
                if neighbor != userid and neighbor not in neighbors:   h& w, G% h3 |8 \& z3 x  _
                    neighbors.append(neighbor)
    ; T& k3 l" Q% w* j' l$ y2 {7 A% p( U      
    + Q1 k4 k# r3 @    neighbors_dist=[]7 h+ c* z* C8 |+ p" m
        for neighbor in neighbors:
    ; A9 m0 F) ^# @# \  W9 ~7 a; J        dist=calcSimlaryCosDist(users_dic[userid],users_dic[neighbor])  #calcSimlaryCosDist  calcCosDist calcCosDistSpe) E& n" I. _! l* i
            neighbors_dist.append([dist,neighbor])9 k* {  W9 Z: q0 ]+ R+ H
        neighbors_dist.sort(reverse=True)
    5 D/ j' x3 f* J) V1 y% E    #print neighbors_dist
    7 b3 \' \7 l3 V    return  neighbors_dist
    % [! d6 i( R' a9 O4 b% ~9 _, e
    , o, S% }2 o. ]& W
    + X8 W" e, z( `9 a#
    # v: W" \% G: R6 n( M7 l#   使用UserFC进行推荐
    ( L9 N5 J+ ?* ]5 E2 e* M#   输入:文件名,用户ID,邻居数量& R6 J' S* b2 T
    #   输出:推荐的电影ID,输入用户的电影列表,电影对应用户的反序表,邻居列表4 J2 i2 J7 y& f9 M# v. j
    #- c6 t1 f7 l4 N! Z( l$ N
    def recommendByUserFC(file_name,userid,k=5):
    : F8 ?4 f# k( D9 m  s+ {   
    ' f# U. G1 y/ Y3 W* Y+ Y/ m& U    #读取文件数据2 ]# h4 ]7 g" q, ~, j
        test_contents=readFile(file_name)
    " N% }8 I+ u2 Q  _% L$ p* [   
    9 k: l; b/ O/ A  J    #文件数据格式化成二维数组 List[[用户id,电影id,电影评分]...] ) e/ G& \; \+ f* o/ y
        test_rates=getRatingInformation(test_contents)! H2 o( n  P+ `4 |+ A8 g/ y9 \
       
    * d+ {! a( v$ G4 q1 W0 _. ~    #格式化成字典数据 1 A/ x7 q8 a# L+ @
        #    1.用户字典:dic[用户id]=[(电影id,电影评分)...]
    ! O3 Y& P2 v3 O$ F    #    2.电影字典:dic[电影id]=[用户id1,用户id2...]
    8 |7 R, D$ I2 h# h. H) s0 D: ~    test_dic,test_item_to_user=createUserRankDic(test_rates), A& I# p; o3 A0 W9 \$ S( P
       
    9 R" |, l; R* o" U5 R- v' I    #寻找邻居
    % e% G6 B& ^& F8 @    neighbors=calcNearestNeighbor(userid,test_dic,test_item_to_user)[:k]
    & \9 n2 u' f0 u  e+ Y        
    / M* h+ l5 i, B  A    recommend_dic={}
    $ T5 y" H* z$ o$ v0 {6 d    for neighbor in neighbors:, |! ^  l8 B, q9 C+ V0 I& ]% j. o
            neighbor_user_id=neighbor[1]
    " o0 V/ e/ Q) d4 f4 L; B        movies=test_dic[neighbor_user_id]/ A; ^. s  X- `7 O; d! w$ x
            for movie in movies:
    6 i( B" C( C( K! r            #print movie
    1 H2 b3 |! Z6 J7 G            if movie[0] not in recommend_dic:
    % |2 G& s: H3 W  g- y                recommend_dic[movie[0]]=neighbor[0]) y8 ~0 O/ J/ w4 H+ ?% y& J/ F
                else:! q/ o' y' ~: S+ }7 P* v9 e3 I* r
                    recommend_dic[movie[0]]+=neighbor[0]
    9 B9 W. A2 e9 m6 E6 e( B- d    #print len(recommend_dic)
    # ^: g3 \" a; b4 s( ~; Y8 b4 I   
      C/ ~: o: s; W: m    #建立推荐列表
    , K8 ]7 c! v& a4 R7 R3 v    recommend_list=[]
    % g4 X% L$ N9 U+ ?7 v- g2 D5 s    for key in recommend_dic:+ I* E+ [8 N' A9 L. |& k9 M
            #print key
    / y- }7 G& W2 F6 K# L; h& N+ B        recommend_list.append([recommend_dic[key],key])
    ! l; v! R9 \: ?* F- `6 i   
    1 W0 Q# p' b# S" y/ b+ R3 S4 v/ L* Y   
    $ o6 C2 g3 |) ~" d9 v    recommend_list.sort(reverse=True). I0 S: S( }. i5 z
        #print recommend_list
    " |! s  U% Z  _+ g$ o8 Q0 _# Q    user_movies = [ i[0] for i in test_dic[userid]]% S) Z- G* r. x# a% t

    . }1 h* `4 m0 ^+ H/ U    return [i[1] for i in recommend_list],user_movies,test_item_to_user,neighbors
    $ [) p$ ]' @! V$ n" }' w    * A1 z" ?" e6 H- f
       
      R7 P) J# \$ G* ^7 Q& _5 k+ D! I9 I, t( N1 u( T
    #
    # z# x5 ?* s! g% i3 z#
    ' j5 R$ k  H8 B8 s. j& c) e0 K#   获取电影的列表: S/ n. ]9 z9 k; Q0 |* j
    #
    ! E# W9 o7 Y# p#
    + a* V. L0 Q/ G6 `) Y( S2 }/ _#
    # S9 L* S, [9 ]0 Idef getMoviesList(file_name):
    " V5 O6 w# E/ {) \5 ^1 k    #print sys.getdefaultencoding()# G: l; C1 F. q( a# \8 c- W1 ^" \
        movies_contents=readFile(file_name), @' }% l2 W( ?' y( k# Z
        movies_info={}
    9 ~" q( P/ H% K* `* f    for movie in movies_contents:% m8 C& s, j6 e; s
            movie_info=movie.split("|")
    * s0 V3 r5 l0 y. k5 _        movies_info[int(movie_info[0])]=movie_info[1:]
    7 H0 [& Z$ ?! `; q9 S% t    return movies_info/ B( H) _2 k2 X0 _8 j2 U* \
       
    8 w5 M1 K' y) p+ O7 c   
    1 l9 A8 R- b2 ]+ g   
      n( |# i: F. }* ]: O# E7 @#主程序
    . A4 u, E8 ^8 Z# |# X#输入 : 测试数据集合7 ?, {5 p$ N$ I! M) Q6 |7 R% W+ ~* C7 y
    if __name__ == '__main__':  C, a" ~( d, \1 U, X/ x
        reload(sys)
    - q$ P& z9 t4 l2 ]/ N    sys.setdefaultencoding('utf-8'). d7 z: j, l6 P7 Z! I
        movies=getMoviesList("/Users/wuyinghao/Downloads/ml-100k/u.item")
    3 x/ x; S: b! |4 r3 Z5 B, }. _    recommend_list,user_movie,items_movie,neighbors=recommendByUserFC("/Users/wuyinghao/Downloads/ml-100k/u.data",179,80)& z3 Z  k  [- M7 Y. V% e" V
        neighbors_id=[ i[1] for i in neighbors]
    ) _9 x3 M& L/ o2 v: ]' G    table = Texttable()3 Q' ~% y3 t4 \9 m  Z  b
        table.set_deco(Texttable.HEADER)+ ]  z& U6 s, c+ M0 Z/ f: v/ S# [
        table.set_cols_dtype(['t',  # text
    " O& N5 z% F. B- N; E% }/ r7 [3 X8 m6 O7 _  K                          't',  # float (decimal)
    * \3 J, I0 {, w                          't']) # automatic
    4 b3 u5 q% s' k2 l2 Y, K& \    table.set_cols_align(["l", "l", "l"]); W4 X/ j% r0 K
        rows=[]& b8 F; I1 f8 [, r: _, Y
        rows.append([u"movie name",u"release", u"from userid"])
    5 g1 {' \8 ]% o    for movie_id in recommend_list[:20]:# \2 X0 }6 h, K3 b) G* h
            from_user=[]: U- c1 N  b) K5 r5 C- A
            for user_id in items_movie[movie_id]:
    / f' A; H2 e: V2 F. B( {: ?& ^7 a            if user_id in neighbors_id:- W  S' G' B/ m5 |
                    from_user.append(user_id)
    7 g2 L" {- W; Q1 A  z/ X' s        rows.append([movies[movie_id][0],movies[movie_id][1],""])
    ; O# K& }- J/ D, Y    table.add_rows(rows): E1 s3 H* T! v3 U4 j- a( K  I4 |  ^- y
        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
    * c8 [( G* X( f# -*- coding=utf-8 -*-
    , t) V$ X3 u/ j0 F/ g4 i, q8 G, V8 \. `' j+ q
    import math

    7 U% V# d* K# `5 I7 i这是什么语言的程序?: f! \3 P" v2 a& g; A& T6 `4 n# c) K
    回复

    使用道具 举报

    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-7-17 12:35 , Processed in 0.585047 second(s), 67 queries .

    回顶部