澳门1495

chapter 2JS 仿腾讯发表微博之功用代码。

十月 22nd, 2018  |  澳门1495

监察上算法:线性回归,逻辑回归,神经网络,SVM

近年来2天研究了下 腾讯发表微博之效能 特是来划分享下,效果如下:

任由监控上算法:聚类算法,降维算法

澳门1495 1

破例算法:推荐算法

 

除了这些算法以外,有一对算法的讳在机械上园地中为经常出现。但他俩自己并无算是一个机上算法,而是为缓解有块头问题设生之。你可以理
解他们为上述算法的子算法,用于大幅度提高训练过程。其中的代表有:

于这分享前 来谈谈自己编写代码的惯,很多人会问我既用的是jquery框架
为什么写的机件不用Jquery那种样式?我立刻应答的是:每个人编写代码有每个人之惯。但是自重新眷恋发挥的凡:这种编码个人觉得
有一个死老之亮点,我弗是殊靠让Jquery框架,因为不同之营业所发出差的框架
比如在淘宝用的kissy框架 在开宝用的是支付宝框架 在百度用底凡百度框架
在腾讯有腾讯的前端js框架 假如我的编制代码太依仗让jquery
那如若其他人想要用自家代码或者本身要好某个平等龙去开腾讯项目了
但是他俩那里要求我们不得不用他们之JS框架
且又来诸如此类的功能?那使本身一心依赖jquery那种形式编码
那本本人是匪是如更编码为?如果照现行编码方式去编码
最多只是用了下jquery选择器而都 那么要反下摘器
其他的代码都好直接以来用,这样的扩张性非常好!我个人认为作为一个正式的前端开发,不仅仅只是见面一点点jquery做做东西,而重新应考虑编写高质量之代码,可能为此jquery写写简单的代码同样会做好某个东西,但是有没发考虑到要是有一样龙需求大增了有功能
你是匪是还要如果转代码?能无克在原先的功底及更勾新的效能?而不论是需改代码!

梯度下降法,主要使用在线型回归,逻辑回归,神经网络,推荐算法中;

称高质量的代码?

牛顿法,主要运用 在线型回归中;

私认为必须满足以下几点:

BP算法,主要以在神经网络中;

   1. 可扩展性。

SMO算法,主要使用在SVM中。

   2. 可维护性。

 

   3. 可读性,易使用性。

# 第二回:推荐系统入门

   4. JS性能。

原文:http://guidetodatamining.com/chapter-2/

 最要害满足以上几乎点。

内容:
* 推荐系统办事原理
* 社会化协同过滤工作规律
* 如何找到相似物品
* 曼哈顿相距
* 欧几里得距离
* 闵可夫斯基距离
* 皮尔逊相关系数
* 余弦相似度
* 使用Python实现K最贴近算法
* 图书漂流站(BookCrossing)数据集

 好了 废话不多说了!转主题,目前己开的此上微博效果 只是略的
当然腾讯发表微博发出一部分犬牙交错的效用
比如说下面有抬高神等等功能,目前没有做成那样的(工作量比老)。

## 你喜爱的物本身哉喜好

 下面我写的斯JS代码需要注意2点:

咱俩拿从推荐系统开始,开启数据挖掘的同。推荐系统无处不在,如亚马逊网站的“看了及时宗商品之买主还请过”板块:

 1.每次上下后 大家以说列表会补充加同漫漫,目前无发ajax请求 后台从未记录
所以刷新页面 会清掉。

![](img/chapter-2/chapter-2-1.png)

 2. 光阴是故底是客户端时间 假如客户端时间错的话 那么时间呢会受影响。

last.fm上针对音乐与演唱会的引荐(相似歌手):

实质上思路好粗略 看上面的成效就是清楚
所以思路在这边不多说了!或者自己下会供压缩demo
可以好下载下来省效果就是ok了!每次上一不善后 都提供了回调
作为扩大吧!当然鼠标移到某一样宗时 会出现删除按钮
同时可以随便删除某平项。直接贴代码吧 也并未什么好说的!

![](img/chapter-2/chapter-2-2.png)

HTML代码如下:

当亚马逊的事例里,它用了点滴只元素来拓展推介:一凡是自身浏览了里维斯翻译的《法华经》一书写;二凡任何浏览过该书的买主还浏览了之译作。

复制代码 代码如下:

本章我们描述的引进方法称为协同过滤。顾名思义,这个点子是利用他人的喜爱好来进展推介,也就是说,是豪门一道发生的引进。他的做事原理是这般的:如果如推荐一本书给你,我会以网站及找一个同您仿佛的用户,然后拿他爱的图书推荐给你——比如巴奇加卢比的《发条女孩》。

<div id=”msgBox”>
        <form>
            <h2>来 , 说说您以做什么 , 想什么</h2>
            <div>
                <input id=”userName” class=”f-text” value=”” />
                <p id=”face”>
                    <img src=”img/face1.gif” class=”current” />
                    <img src=”img/face2.gif” />
                    <img src=”img/face3.gif” />
                    <img src=”img/face4.gif” />
                    <img src=”img/face5.gif” />
                    <img src=”img/face6.gif” />
                    <img src=”img/face7.gif” />
                    <img src=”img/face8.gif” />
                </p>
            </div>
            <div>
                <textarea id=”conBox”
class=”f-text”></textarea>
            </div>
            <div class=”tr”>
                <p>
                    <span
class=”countTxt”>还会输入</span><strong
class=”maxNum”>140</strong><span>个字</span>
                    <input id=”sendBtn” type=”button” value=””
title=”快捷键 Ctrl+Enter” />
                </p>
            </div>
        </form>
        <div class=”list”>
            <h3><span>大家在说</span></h3>
            <ul id=”list-msg”></ul>
        </div>   
    </div>

### 如何找到相似的用户?

CSS代码如下:

故此率先使做的做事是找到相似的用户。这里用最为简便的二维模型来讲述。假设用户会当网站因此五发星球来评价一本书——没有星表示开得可怜潮,五颗星表示特别好。因为我们因此底凡二维模型,所以才对少本书进行评价:史蒂芬森的《雪崩》(纵轴)和拉尔森的《龙纹身的女孩》(横轴)。

复制代码 代码如下:

![](img/chapter-2/chapter-2-3.png)

body,div,h2,h3,ul,li,p{margin:0;padding:0;}
    a{text-decoration:none;}
    a:hover{text-decoration:underline;}
    ul{list-style-type:none;}
    body{color:#333;background:#3c3a3b;font:12px/1.5 \5b8b\4f53;}
    #msgBox{width:500px;background:#fff;border-radius:5px;margin:10px
auto;padding-top:10px;}
    #msgBox form h2{font-weight:400;font:400 18px/1.5
\5fae\8f6f\96c5\9ed1;}
    #msgBox form{background:url(img/boxBG.jpg) repeat-x 0
bottom;padding:0 20px 15px;}
    #userName,#conBox{color:#777;border:1px solid
#d0d0d0;border-radius:6px;background:#fff url(img/inputBG.png)
repeat-x;padding:3px 5px;font:14px/1.5 arial;}
    #userName.active,#conBox.active{border:1px solid #7abb2c;}
    #userName{height:20px;}
    #conBox{width:448px;resize:none;height:65px;overflow:auto;}
    #msgBox form div{position:relative;color:#999;margin-top:10px;}
    #msgBox img{border-radius:3px;}
    #face{position:absolute;top:0;left:172px;}
    #face
img{float:left;display:inline;width:30px;height:30px;cursor:pointer;margin-right:6px;opacity:0.5;filter:alpha(opacity=50);}
    #face img.hover,#face
img.current{width:28px;height:28px;border:1px solid
#f60;opacity:1;filter:alpha(opacity=100);}
   
#sendBtn{border:0;width:112px;height:30px;cursor:pointer;margin-left:10px;background:url(img/btn.png)
no-repeat;}
    #sendBtn.hover{background-position:0 -30px;}
    #msgBox form .maxNum{font:26px/30px Georgia, Tahoma,
Arial;padding:0 5px;}
    #msgBox .list{padding:10px;}
    #msgBox .list
h3{position:relative;height:33px;font-size:14px;font-weight:400;background:#e3eaec;border:1px
solid #dee4e7;}
    #msgBox .list h3
span{position:absolute;left:6px;top:6px;background:#fff;line-height:28px;display:inline-block;padding:0
15px;}
    #msgBox .list ul{overflow:hidden;zoom:1;}
    #msgBox .list ul
li{float:left;clear:both;width:100%;border-bottom:1px dashed
#d8d8d8;padding:10px 0;background:#fff;overflow:hidden;}
    #msgBox .list ul li.hover{background:#f5f5f5;}
    #msgBox .list
.userPic{float:left;width:50px;height:50px;display:inline;margin-left:10px;border:1px
solid #ccc;border-radius:3px;}
    #msgBox .list
.content{float:left;width:400px;font-size:14px;margin-left:10px;font-family:arial;word-wrap:break-word;}
    #msgBox .list .userName{display:inline;padding-right:5px;}
    #msgBox .list .userName a{color:#2b4a78;}
    #msgBox .list .msgInfo{display:inline;word-wrap:break-word;}
    #msgBox .list .times{color:#889db6;font:12px/18px
arial;margin-top:5px;overflow:hidden;zoom:1;}
    #msgBox .list .times span{float:left;}
    #msgBox .list .times a{float:right;color:#889db6;}
    .tr{overflow:hidden;zoom:1;}
    .tr p{float:right;line-height:30px;}
    .tr *{float:left;}
    .hidden {display:none;}

首先,下表显示出三员用户指向当时片本书做了评论:

JS代码如下:

![](img/chapter-2/chapter-2-4.png)

复制代码 代码如下:

今天自眷恋吧机要之X先生推荐一本书,他受《雪崩》打了季星,《龙纹身的女孩》两星球。第一独任务是摸索来哪位用户与外顶相似。我们就此去来表示。

/**
 * 仿腾讯发表微博之效能
 * 1.手上不曾发ajax请求 后台从未记录 所以刷新页面 会清掉
 * 2. 时刻是故之凡客户端时间 假如客户端时间错的话
那么时间啊会为影响。
 * 目前就算如此相互 具体的思路不太复杂 如果项目被因故到这般的
可以因具体的要求变动
 * @constructor Microblog
 * @date 2013-12-23
 * @author tugenhua
 * @email 879083421@qq.com
 */

### 曼哈顿去

 function Microblog(options) {

顶简便易行的离开计算方式是曼哈顿去。在二维模型中,每个人还好用(x,
y)的接触来代表,这里自己所以生标来代表不同之人,(x<sub>1</sub>,
y<sub>1</sub>)表示艾米,(x<sub>2</sub>,
y<sub>2</sub>)表示那位神秘之X先生,那么她们中的曼哈顿距离就是:

    this.config = {
        maxNum                        :   140,               //
最要命的字符数
        targetElem                    :   ‘.f-text’,         // 输入框
或者文本域的class名
        maxNumElem                    :   ‘.maxNum’,         //
还能够输入多少字容器
        sendBtn                       :   ‘#sendBtn’,        //
广播按钮
        face                          :   ‘#face’,           //
表情容器
        activeCls                     :   ‘active’,          //
鼠标点击输入框add类
        currentCls                    :   ‘current’,         //
鼠标点击face头像时 增加的类名
        inputID                       :   ‘#userName’,       //
输入框ID
        textareaId                    :   ‘#conBox’,         //
文本域ID
        list                          :   ‘#list-msg’,       //
大家以说之容器
        callback                      :   null               //
动态播放完后的回调函数
    };

![](img/chapter-2/chapter-2-5.png)

    this.cache = {};
    this.init(options);
 }

为尽管是x之异的绝对化值加上y之差之断然值,这样他们之离便是4。

 Microblog.prototype = {

![](img/chapter-2/chapter-2-6.png)

    constructor: Microblog,

完的乘除结果如下:

    init: function(options) {
        this.config = $.extend(this.config,options || {});
        var self = this,
            _config = self.config,
            _cache = self.cache;

![](img/chapter-2/chapter-2-7.png)

        // 点击输入框input 文本域 textarea 边框的变更
        $(_config.targetElem).each(function(index,item){

艾米的离最近,在她的浏览历史中可见到它们曾让巴奇加卢比底《发条女孩》打过五星,于是我们就得将及时仍开推荐给X先生。

            $(item).unbind(‘focus’);
            $(item).bind(‘focus’,function(e){
                !$(this).hasClass(_config.activeCls) &&
$(this).addClass(_config.activeCls);
            });
            $(item).unbind(‘blur’);
            $(item).bind(‘blur’,function(e){
                $(this).hasClass(_config.activeCls) &&
$(this).removeClass(_config.activeCls);
            });
        });

### 欧几里得距离

        // 点击face头像 add(增加)类名
        var faceImg = $(‘img’,$(_config.face));
        $(faceImg).each(function(index,item){
            $(item).unbind(‘click’);
            $(item).bind(‘click’,function(e){
               
$(this).addClass(_config.currentCls).siblings().removeClass(_config.currentCls);
            });
        });

曼哈顿距的助益之一是计量速度快,对于Facebook这样用计算百万用户之间的相似度时就是格外便宜。

        // 广播按钮hover事件
        $(_config.sendBtn).hover(function(){
            !$(this).hasClass(‘hover’) && $(this).addClass(‘hover’);
        },function(){
            $(this).hasClass(‘hover’) && $(this).removeClass(‘hover’);
        })

**勾股定理**

        // 绑定事件
        self._bindEnv();
    },
    /*
     * 计算字符的长短 包括中文 数字 英文等等
     * @param str
     * @return 字符串的长度
     */
     _countCharacters: function(str) {
         var totalCount = 0;
          for (var i=0; i<str.length; i++) {
             var c = str.charCodeAt(i);
             if ((c >= 0x0001 && c <= 0x007e) || (0xff60<=c &&
c<=0xff9f)) {
                totalCount++;
             }else {  
                totalCount+=2;
             }
         }
         return totalCount;
     },
     /*
      * 所有的绑定事件
      */
     _bindEnv: function() {
        var self = this,
            _config = self.config,
            _cache = self.cache;

或者你还隐约记得勾股定理。另一样种计算距离的方尽管是圈片接触内的直线距离:

        // 文本域keyup事件
        self._keyUp();

![](img/chapter-2/chapter-2-8.png)

        // 点击播放按钮事件
        self._clickBtn();
     },
     /*
      * 文本域keyup事件
      */
     _keyUp: function() {
         var self = this,
             _config = self.config,
             _cache = self.cache;
         $(_config.textareaId).unbind(‘keyup’);
         $(_config.textareaId).bind(‘keyup’,function(){
             var len = self._countCharacters($(this).val()),
                 html;
             if(_config.maxNum * 1 >= len * 1) {
                html = _config.maxNum * 1 – len * 1;
             }else {
                html = _config.maxNum * 1 – len * 1;
             }
             $(_config.maxNumElem).html(html);
             $(_config.maxNumElem).attr(‘data-html’,html);
         });
     },
     /*
      * 点击播放按钮事件
      */
     _clickBtn: function() {

动用勾股定理,我们得如下计算距离:

        var self = this,
            _config = self.config,
            _cache = self.cache;
        var reg = /^\s*$/g;
        $(_config.sendBtn).unbind(‘click’);
        $(_config.sendBtn).bind(‘click’,function(){

![](img/chapter-2/chapter-2-9.png)

            var inputVal = $(_config.inputID).val(),
                textVal = $(_config.textareaId).val(),
                maxNum = $(_config.maxNumElem).attr(‘data-html’);
            if(reg.test(inputVal)) {
                alert(‘请输入而的姓名’);
                return;
            }else if(reg.test(textVal)) {
                alert(“随便说接触啊吧!”);
                return;
            }
            if(maxNum * 1 < 0) {
                alert(‘字符超过限定 请缩减字’);
                return;
            }
            // 本来是设发ajax请求的 但是随即边没有后台处理
所以目前只是是客户端渲染页面
            self._renderHTML(inputVal,textVal);
        });
     },
     /*
      * 把html结构渲染出来
      */
     _renderHTML: function(inputVal,textVal) {
         var self = this,
             _config = self.config,
             _cache = self.cache;
        var oLi = document.createElement(“li”),
            oDate = new Date();
        oLi.innerHTML = ‘<div class=”userPic”>’ +
                           ‘<img src=”‘+self._getSrc()+'” />’+
                        ‘</div>’ +
                        ‘<div class=”content”>’ +
                            ‘<div class=”userName”><a
href=”javascript:;”>’+inputVal+'</a>:</div>’ +
                            ‘<div
class=”msgInfo”>’+textVal+'</div>’ +
                            ‘<div class=”times”>’+
                               
‘<span>’+self._format(oDate.getMonth() + 1) + “\u6708” +
self._format(oDate.getDate()) + “\u65e5 ” +
self._format(oDate.getHours()) + “:” +
self._format(oDate.getMinutes())+'</span>’+
                                ‘<a class=”del hidden”
href=”javascript:;”>删除</a>’+
                            ‘</div>’ +
                        ‘</div>’;
        // 插入元素
        if($(_config.list + ” li”).length > 0) {

即时漫漫斜线就是欧几里得距离,公式是:

            $(oLi).insertBefore($(_config.list + ” li”)[0]);
            self._animate(oLi);
        }else {

![](img/chapter-2/chapter-2-10.png)

            $(_config.list).append(oLi);
            self._animate(oLi);

回顾一下,这里的x<sub>1</sub>表示用户1喜欢《龙纹身》的档次,x<sub>2</sub>是用户2喜欢这仍开的水平;y<sub>1</sub>则是用户1喜欢《雪崩》的程度,y<sub>2</sub>是用户2喜欢这本开之档次。

        }
        _config.callback && $.isFunction(_config.callback) &&
_config.callback();

艾米于《龙纹身》和《雪崩》都打了五颗星,神秘的X先生分别由了片星星及季星星,这样他们中的欧几里得距离便是:

        // 清空输入框 文本域的值
        self._clearVal();

![](img/chapter-2/chapter-2-11.png)

        // hover事件
        self._hover();
     },
     /*
      * 格式化时间, 如果为同样员数时补0
      */
    _format: function(str){
        return str.toString().replace(/^(\d)$/,”0$1″);
    },
    /*
     * 获取ing src
     * @return src
     */
    _getSrc: function() {
        var self = this,
            _config = self.config,
            _cache = self.cache;
        var faceImg = $(‘img’,$(_config.face));

以下是全方位用户之测算结果:

        for(var i = 0; i < faceImg.length; i++) {
            if($(faceImg[i]).hasClass(_config.currentCls)) {
                return $(faceImg[i]).attr(‘src’);
                break;
            }
        }
    },
    /*
     * 清空值
     */
    _clearVal: function() {
        var self = this,
            _config = self.config,
            _cache = self.cache;

![](img/chapter-2/chapter-2-12.png)

        $(_config.inputID) && $(_config.inputID).val(”);
        $(_config.textareaId) && $(_config.textareaId).val(”);

### N维模型

    },
    /*
     * hover事件
     */
    _hover: function() {
        var self = this,
            _config = self.config,
            _cache = self.cache;
        $(_config.list + ‘ li’).hover(function(){
            !$(this).hasClass(‘hover’) &&
$(this).addClass(‘hover’).siblings().removeClass(‘hover’);
            $(‘.del’,$(this)).hasClass(‘hidden’) &&
$(‘.del’,$(this)).removeClass(‘hidden’);
            var $that = $(this);

刚才咱们才针对少本书进行评价(二维模型),下面让咱们扩张一下,尝试再次复杂的型。假设我们今天而呢一个在线音乐网站的用户推荐乐队。用户可据此1交5星星来评论一个乐队,其中包含半星(如2.5星体)。下表展示了8个用户对8开发乐队的品:

            // 删除事件
            $(‘.del’,$that).unbind(‘click’);
            $(‘.del’,$that).bind(‘click’,function(){

![](img/chapter-2/chapter-2-13.png)

                $($that).animate({
                    ‘opacity’ : 0
                },500,function(){
                    $that.remove();   
                });
            });
        },function(){
            $(this).hasClass(‘hover’) && $(this).removeClass(‘hover’);
            !$(‘.del’,$(this)).hasClass(‘hidden’) &&
$(‘.del’,$(this)).addClass(‘hidden’);
        });

表明中之短横表示这号用户没有让就出乐队打分。我们以测算两个用户之离开时,只行使他们还评价了之乐队,比如使计算Angelica和Bill的去,我们一味会就此到5开销乐队。这半单用户的曼哈顿距离吗:

    },
    /*
     * height
     */
     _animate: function(oLi) {
        var self = this;
        var iHeight = $(oLi).height(),
            alpah = 0,
            timer,
            count = 0;
        $(oLi).css({“opacity” : “0”, “height” : “0”});

![](img/chapter-2/chapter-2-14.png)

        timer && clearInterval(timer);
        timer = setInterval(function (){
            $(oLi).css({“display” : “block”, “opacity” : “0”, “height” :
(count += 8) + “px”});
            if (count > iHeight){
                    clearInterval(timer);
                    $(oLi).css({ “height” : iHeight + “px”});
                    timer = setInterval(function (){
                        $(oLi).css({“opacity” : alpah += 10});

末离开就是头数的加和:(1.5 + 1.5 + 3 + 2 + 1)。

                        alpah > 100 && (clearInterval(timer),
$(oLi).css({“opacity”:100}));

算算欧几里得距离的法门吗是看似的,我们吧仅仅落两者都评价了之乐队。

                    },30);
                }
            },30);
     }
 };

![](img/chapter-2/chapter-2-15.png)

 // 初始化代码
 $(function(){
    new Microblog({});
 });

故此公式来叙述就是:

源码下载:http://xiazai.jb51.net//201312/yuanma/wb(jb51.net).rar

![](img/chapter-2/chapter-2-16.png)

君或许感兴趣之稿子:

  • js获取url参数值的有数种植办法
  • JS
    URL传中文参数引发的乱码问题
  • JS获取URL中参数值(QueryString)的4种方法分享
  • javascript/jquery获取地址栏url参数的办法
  • js URL参数的拼凑方法较
  • 每当JavaScript中取得请求的URL参数
  • js修改地址栏URL参数解决url参数问题
  • JavaScript
    Base64编码和解码,实现URL参数传递。
  • JavaScript
    URL参数读取改进版本
  • javascript
    获取url参数的正则表达式(用来收获有参数值)
  • js获取url中之参数都参数为华语时不时经过js解码
  • js实现将当选内容分享到新浪或腾讯微博
  • JS实现仿腾讯微博无刷新删除微博效果代码
  • javascript兑现之仿腾讯QQ窗口抖动效果代码
  • js获取腾讯视频ID的法门

**控了呢?** 那就是试计算其他几独用户中的离开吧。

![](img/chapter-2/chapter-2-17.png)

**发生个缺陷**

当我们算Hailey和Veronica的去时会见发现一个题目:他们同台评论的乐队就来三三两两支付(Norah
Jones和The
Strokes),而Hailey和Jordyn共同评论了五支出乐队,这不啻会影响我们的计量结果,因为Hailey和Veronica之间是二维的,而Haily和Veronica之间是五维的。曼哈顿距离及欧几里得距离在数量整体的情事下效果太好。如何处理缺失数据,这当研究世界以是一个欢蹦乱跳的话题。本书的接轨内容会展开一些谈谈,这里先不进行。现在,让咱开构建一个引进系统吧。

### 推广:闵可夫斯基距离

咱俩可以曼哈顿距与欧几里得距离综合成一个公式,这个公式称为闵可夫斯基距离:

![](img/chapter-2/chapter-2-18.png)

其中:

* `r = 1` 该公式即曼哈顿距离
* `r = 2` 该公式即欧几里得离
* `r = ∞` 极大距离

![](img/chapter-2/chapter-2-19.png)

当你在书写中来看这些数学公式,你可择快速小过它们,继续读下面的契,过去本人虽是这样;你也可住下来,好好分析一下这些公式,会发现实际她并不难理解。比如上面的公式,当r
= 1经常,可以简化成如下形式:

![](img/chapter-2/chapter-2-20.png)

遵用上文的音乐站点为条例,x和y分别代表两只用户,d(x,
y)表示他们之间的离,n表示他们联合评论了的乐队数量,我们事先就召开了测算:

![](img/chapter-2/chapter-2-21.png)

其中Difference一栏表示双方评分的差之绝值,加起来相当9,也尽管是他们中的去。

当r = 2时,我们沾欧几里得距离的计算公式:

![](img/chapter-2/chapter-2-22.png)

**提早预告一下:r值越怪,单个维度的差值大小会针对总体距离有重新不行之熏陶。**

![](img/chapter-2/chapter-2-23.png)

## 使用Python代码来代表数据(终于要起编程了)

每当Python中,我们可以据此多措施来叙述上表明中的数目,这里我选Python的字典类型(或者叫做关联数组、哈希表)。

流淌:本书的装有代码可以当[这里](code/)找到。

“`python
users = {“Angelica”: {“Blues Traveler”: 3.5, “Broken Bells”: 2.0, “Norah
Jones”: 4.5, “Phoenix”: 5.0, “Slightly Stoopid”: 1.5, “The Strokes”:
2.5, “Vampire Weekend”: 2.0},
         “Bill”:{“Blues Traveler”: 2.0, “Broken Bells”: 3.5, “Deadmau5”:
4.0, “Phoenix”: 2.0, “Slightly Stoopid”: 3.5, “Vampire Weekend”: 3.0},
         “Chan”: {“Blues Traveler”: 5.0, “Broken Bells”: 1.0,
“Deadmau5”: 1.0, “Norah Jones”: 3.0, “Phoenix”: 5, “Slightly Stoopid”:
1.0},
         “Dan”: {“Blues Traveler”: 3.0, “Broken Bells”: 4.0, “Deadmau5”:
4.5, “Phoenix”: 3.0, “Slightly Stoopid”: 4.5, “The Strokes”: 4.0,
“Vampire Weekend”: 2.0},
         “Hailey”: {“Broken Bells”: 4.0, “Deadmau5”: 1.0, “Norah Jones”:
4.0, “The Strokes”: 4.0, “Vampire Weekend”: 1.0},
         “Jordyn”:  {“Broken Bells”: 4.5, “Deadmau5”: 4.0, “Norah
Jones”: 5.0, “Phoenix”: 5.0, “Slightly Stoopid”: 4.5, “The Strokes”:
4.0, “Vampire Weekend”: 4.0},
         “Sam”: {“Blues Traveler”: 5.0, “Broken Bells”: 2.0, “Norah
Jones”: 3.0, “Phoenix”: 5.0, “Slightly Stoopid”: 4.0, “The Strokes”:
5.0},
         “Veronica”: {“Blues Traveler”: 3.0, “Norah Jones”: 5.0,
“Phoenix”: 4.0, “Slightly Stoopid”: 2.5, “The Strokes”: 3.0}
        }
“`

咱得以就此以下方法来获得有用户的评分:

“`python
>>> user[“Veronica”]
{“Blues Traveler”: 3.0, “Norah Jones”: 5.0, “Phoenix”: 4.0, “Slightly
Stoopid”: 2.5, “The Strokes”: 3.0}
>>>
“`

### 计算曼哈顿相差

“`python
def manhattan(rating1, rating2):
    “””计算曼哈顿距离。rating1和rating2参数中储存的数额格式均为
    {‘The Strokes’: 3.0, ‘Slightly Stoopid’: 2.5}”””
    distance = 0
    for key in rating1:
        if key in rating2:
            distance += abs(rating1[key] – rating2[key])
    return distance
“`

咱们得开一下测试:

“`python
>>> manhattan(users[‘Hailey’], users[‘Veronica’])
2.0
>>> manhattan(users[‘Hailey’], users[‘Jordyn’])
7.5
>>>
“`

脚我们编辑一个函数来寻觅有距离最近之用户(其实该函数会回去一个用户列表,按离排序):

“`python
def computeNearestNeighbor(username, users):
    “””计算有所用户至username用户之偏离,倒序排列并返结果列表”””
    distances = []
    for user in users:
        if user != username:
            distance = manhattan(users[user], users[username])
            distances.append((distance, user))
    # 按离排序——距离近的排除在前
    distances.sort()
    return distances
“`

简单测试一下:

“`python
>>> computeNearestNeighbor(“Hailey”, users)
[(2.0, ‘Veronica’), (4.0, ‘Chan’), (4.0, ‘Sam’), (4.5, ‘Dan’), (5.0,
‘Angelica’), (5.5, ‘Bill’), (7.5, ‘Jordyn’)]
“`

说到底,我们做以上内容来进行推介。假设我怀念呢Hailey做推荐,这里自己找到了偏离他离最近底用户Veronica。然后,我会找到出Veronica评价了但是Hailey没有评的乐队,并使Hailey对这些陌生乐队的品会跟Veronica相近。比如,Hailey没有评了Phoenix乐队,而Veronica对斯乐队由有了4分叉,所以我们看Hailey也会见喜欢就出乐队。下面的函数就兑现了这同一逻辑:

“`python
def recommend(username, users):
    “””返回推荐结果列表”””
    # 找到距离最近底用户
    nearest = computeNearestNeighbor(username, users)[0][1]
    recommendations = []
    # 找有立刻员用户评价了、但自己没有评价的乐队
    neighborRatings = users[nearest]
    userRatings = users[username]
    for artist in neighborRatings:
        if not artist in userRatings:
            recommendations.append((artist,
neighborRatings[artist]))
    # 按照评分进行排序
    return sorted(recommendations, key=lambda artistTuple:
artistTuple[1], reverse = True)
“`

下我们就是可为此其来也Hailey做推荐了:

“`python
>>> recommend(‘Hailey’, users)
[(‘Phoenix’, 4.0), (‘Blues Traveler’, 3.0), (‘Slightly Stoopid’,
2.5)]
“`

运行结果跟我们的预想相符。我们看可以见见,和Hailey距离最近的用户是Veronica,Veronica对Phoenix乐队打了4分叉。我们又试试其他人:

“`python
>>> recommend(‘Chan’, users)
[(‘The Strokes’, 4.0), (‘Vampire Weekend’, 1.0)]
>>> recommend(‘Sam’, users)
[(‘Deadmau5’, 1.0)]
“`

咱们好猜想Chan会喜欢The Strokes乐队,而Sam不会见尽欣赏Deadmau5。

“`python
>>> recommend(‘Angelica’, users)
[]
“`

对Angelica,我们得了拖欠的回值,也就是说我们鞭长莫及对该进行推荐。让我们看是哪来问题:

“`python
>>> computeNearestNeighbor(‘Angelica’, users)
[(3.5, ‘Veronica’), (4.5, ‘Chan’), (5.0, ‘Hailey’), (8.0, ‘Sam’), (9.0,
‘Bill’), (9.0, ‘Dan’), (9.5, ‘Jordyn’)]
“`

Angelica最相似之用户是Veronica,让我们回头望数据:

![](img/chapter-2/chapter-2-13.png)

俺们好观看,Veronica评价了的乐队,Angelica也都评价了了,所以我们无推荐。

今后,我们会讨论哪边化解就无异题目。

**作业:实现一个乘除闵可夫斯基距离的函数,并于盘算用户距离时使用其。**

“`python
def minkowski(rating1, rating2, r):
    distance = 0
    for key in rating1:
        if key in rating2:
            distance += pow(abs(rating1[key] – rating2[key]), r)
    return pow(distance, 1.0 / r)

# 修改computeNearestNeighbor函数中之一条龙
distance = minkowski(users[user], users[username], 2)
# 这里2意味着用欧几里得距离
“`

### 用户之问题

为咱密切瞧用户指向乐队的评分,可以发现每个用户之打分专业大不同:

* Bill没有自来最为的分,都在2暨4分开中;
* Jordyn似乎爱不释手具有的乐队,打分都当4届5之间;
* Hailey是一个有趣的口,他的分不是1不怕是4。

这就是说,如何比较这些用户也?比如Hailey的4分开相当给Jordan的4划分还是5瓜分也?我认为再次类似5瓜分。这样一来就见面影响到推介系统的准头了。

![](img/chapter-2/chapter-2-24.png)

* 左:我特别欣赏Broken Bells乐队,所以我给他们打4分!
* 右:Broken Bells乐队还可,我自从4区划。

### 皮尔逊相关系数

缓解办法有是下皮尔逊相关系数。简单起见,我们先押下面的多少(和前面的多寡不同):

![](img/chapter-2/chapter-2-25.png)

这种场面在数挖掘领域称为“分数膨胀”。Clara最低为了4区划——她有的打分都以4及5划分次。我们以它绘制成图:

![](img/chapter-2/chapter-2-26.png)

**平等修直线——完全符合!!!**

直线即意味着Clara和Robert的宠幸完全一致。他们还当Phoenix是极好之乐队,然后是Blues
Traveler、Norah
Jones。如果Clara和Robert的见解不等同,那么得于直线上之接触就算愈加少。

**意基本一致的状态**

![](img/chapter-2/chapter-2-27.png)

**理念无顶相同的景况**

![](img/chapter-2/chapter-2-28.png)

于是从图纸上知道,意见相平等表现为同一漫长直线。皮尔逊相关系数用于衡量两个变量之间的相关性(这里的少单变量指的是Clara和Robert),它的值在-1顶1内,1代表了合乎,-1代表完全相反。从直观上亮,最初步之那漫长直线皮尔逊相关系数为1,第二摆设凡0.91,第三摆是0.81。因此我们应用就一点来找到相似的用户。

皮尔逊相关系数的计算公式是:

![](img/chapter-2/chapter-2-29.png)

此处自己说说好的阅历。我大学读之是现代音乐艺术,课程包括芭蕾、现代跳舞、服装设计等,没有其余数学课程。我高中读的凡男子汉学校,学习了管道工程和汽车维修,只懂很基础之数学知识。不知是坐自之课程背景,还是习惯给用直觉来考虑,当自家遇到这样的数学公式时会习惯性地跳过,继续读下面的仿。如果你跟自我平,我强烈建议你及这种惰性抗争,试着去了解这些公式。它们虽然看起老复杂,但要会为常人所知的。

上面的公式除了扣起比较复杂,另一个题材是要落计算结果必须对数码做往往遍历。好于咱们发另外一个公式,能够计算皮尔逊相关系数的将近似值:

![](img/chapter-2/chapter-2-30.png)

这公式虽然看起更加扑朔迷离,而且那计算结果碰头不太稳定,有得误差是,但它们最特别的优点是,用代码实现的时候可以仅遍历一不行数据,我们会以下文看到。首先,我们以之公式做一个诠释,计算下面是表达式的价值:

![](img/chapter-2/chapter-2-31.png)

对此Clara和Robert,我们可以获得:

![](img/chapter-2/chapter-2-32.png)

深简单把?下面我们算是公式:

![](img/chapter-2/chapter-2-33.png)

Clara的总评分是22.5, Robert是15,他们评头论足了5支付乐队,因此:

![](img/chapter-2/chapter-2-34.png)

之所以,那个巨型公式的成员就是70 – 67.5 = 2.5。

下面我们来拘禁分母:

![](img/chapter-2/chapter-2-35.png)

首先:

![](img/chapter-2/chapter-2-36.png)

咱既算过Clara的终究评分是22.5,它的平方是506.25,除以乐队的多少5,得到101.25。综合得到:

![](img/chapter-2/chapter-2-37.png)

于Robert,我们用同的措施计算:

![](img/chapter-2/chapter-2-38.png)

末尾取得:

![](img/chapter-2/chapter-2-39.png)

据此,1代表Clara和Robert的宠爱完全契合。

**先行休息一下吧**

![](img/chapter-2/chapter-2-40.png)

**测算皮尔逊相关系数的代码**

“`python
from math import sqrt

def pearson(rating1, rating2):
    sum_xy = 0
    sum_x = 0
    sum_y = 0
    sum_x2 = 0
    sum_y2 = 0
    n = 0
    for key in rating1:
        if key in rating2:
            n += 1
            x = rating1[key]
            y = rating2[key]
            sum_xy += x * y
            sum_x += x
            sum_y += y
            sum_x2 += pow(x, 2)
            sum_y2 += pow(y, 2)
    # 计算分母
    denominator = sqrt(sum_x2 – pow(sum_x, 2) / n) * sqrt(sum_y2 –
pow(sum_y, 2) / n)
    if denominator == 0:
        return 0
    else:
        return (sum_xy – (sum_x * sum_y) / n) / denominator
“`

测试一下:

“`python
>>> pearson(users[‘Angelica’], users[‘Bill’])
-0.9040534990682699
>>> pearson(users[‘Angelica’], users[‘Hailey’])
0.42008402520840293
>>> pearson(users[‘Angelica’], users[‘Jordyn’])
0.7639748605475432
“`

## 最后一个公式:余弦相似度

此间我拿奉上最后一个公式:余弦相似度。它以文书挖掘中采用得比多,在齐过滤中呢会以及。为了演示如何采取该公式,我们换一个演示。这里记录了每个用户播放歌曲的次数,我们就此这些多少开展推介:

![](img/chapter-2/chapter-2-41.png)

粗略扫一眼上面的数码(或者用事先说过的离开计算公式),我们好窥见Ann的宠幸和Sally更为相似。

**问题在何方?**

自己在iTunes上产生大约4000篇歌,下面是自个儿最好经常听的乐:

![](img/chapter-2/chapter-2-42.png)

好望,Moonlight
Sonata这首歌唱我播放了25糟,但好有或而平潮都未曾放罢。事实上,上面列有之这些歌或而同一篇犹不曾听了。此外,iTunes上生1500万首音乐,而己才放罢4000首。所以说单个用户之数据是
*稀疏*
的,因为非零值较完整要丢得多。当我们为此1500万篇歌来比少单用户时时,很有或他们中莫另外交集,这样一来就得不到计算他们之间的偏离了。

![](img/chapter-2/chapter-2-43.png)

仿佛之事态是当算两首文章的一般度时。比如说我们想找一按和《The Space
Pioneers》相接近之题,方法之一是使用单词出现的频率,即统计每个单词在开中出现的次数占全书单词之比例,如“the”出现频率为6.13%,“Tom”
0.89%,“space”
0.25%。我们可以就此这些数量来查找相同按照相近的开。但是,这里同样发出数量的稀疏性问题。《The
Space
Pioneers》中有6629个不等之单词,但英语语言中出超常100万单单词,这样一来非零值就坏稀少了,也即无克计算两本书里面的偏离。

余弦相似度的计算着会稍为过这些非零值。它的计算公式是:

![](img/chapter-2/chapter-2-44.png)

内,“·”号表示数量积。“||x||”表示向量x的模子,计算公式是:

![](img/chapter-2/chapter-2-45.png)

我们为此上文中“偏好完全一致”的演示:

![](img/chapter-2/chapter-2-25.png)

于是个别单向量为:

![](img/chapter-2/chapter-2-46.png)

她的模是:

![](img/chapter-2/chapter-2-47.png)

数据积的算计:

![](img/chapter-2/chapter-2-48.png)

就此余弦相似度是:

![](img/chapter-2/chapter-2-49.png)

余弦相似度的克由1届-1,1象征完全匹配,-1代表完全相反。所以0.935意味着相当配度很高。

**学业:尝试计算Angelica和Veronica的余弦相似度**

### 应该运用啊种相似度?

俺们整理本书还见面追究这个问题,以下是片提醒:

![](img/chapter-2/chapter-2-50.png)

* 如果数额有“分数膨胀”问题,就采取皮尔逊相关系数。
*
如果数额比较“密集”,变量之间基本还有公有值,且这些离开数据是可怜重要的,那便动用欧几里得或曼哈顿距离。
* 如果数量是稀疏的,则以余弦相似度。

故此,如果数额是凝聚的,曼哈顿距离同欧几里得距离还是适用的。那么稀的多少足以应用啊?我们来拘禁一个啊与音乐有关的演示:假设有三单人口,每人还深受100篇音乐评论过分。

![](img/chapter-2/chapter-2-51.png)

* Jake(左):乡村音乐的忠实听众。
* Linda和Eric(右):我们好六十年代的摇滚乐!

Linda和Eric喜欢相同的音乐,他们的评分列表中来20篇相同的底曲,且评分都值相差不至0.5!所以他们中间的曼哈顿距离吗20
x 0.5 = 10,欧几里得距离则也:

![](img/chapter-2/chapter-2-52.png)

Linda和Jake只同评分了平等篇歌:Chris Cagle的 *What a Beautiful Day*
。Linda打了3私分,Jake打了5区划,所以她们之间的曼哈顿距离吗2,欧几里得距离吗:

![](img/chapter-2/chapter-2-53.png)

从而随便是曼哈顿离要欧几里得距离,Jake都使于Eric离Linda近,这不符合实际情况。

![](img/chapter-2/chapter-2-54.png)

>
嘿,我想到一个道。人们叫音乐打分是自从1交5区划,那些尚未打分的乐就是联合叫0分好了,这样虽可知缓解数据稀疏的题材了!

想法是,但是这样做为蛮。为了解释这无异于问题,我们再次引入两独人口及例子里来:Cooper和Kelsey。他们同Jake都持有不行相像之乐偏好,其中Jake在我们网站上评论了25篇歌。

![](img/chapter-2/chapter-2-55.png)

Cooper评价了26篇歌,其中25首和Jake是一模一样的。他们针对各国首歌的评论差值只发0.25!

Kelsey在咱们网站及评价了150篇歌,其中25首和Jake相同。和Cooper一样,她跟Jake之间的评头品足差值也只有0.25!

因而我们由直觉上看Cooper和Keylsey离Jake的离开该相似。但是,当我们算他们中间的曼哈顿距离与欧几里得距离时(代入0值),会发觉Cooper要较Keylsey离Jake近得差不多。

**缘何也?**

我们来拘禁下面的数目:

![](img/chapter-2/chapter-2-56.png)

由4、5、6随即三首歌来拘禁,两人口离Jake的距离是一致的,但计算出底曼哈顿距离也无这么显示:

![](img/chapter-2/chapter-2-57.png)

题材即在于数量被之0值对结果的熏陶特别充分,所以用0代替空值的办法并无比较原来的方程好。还有一样种变更的主意是计算“平均值”——将简单总人口共评论了的歌分数除因歌数量。

一言以蔽之,曼哈顿距离及欧几里得距离在数额总体的情形下会运行得特别好,如果数据较稀疏,则要考虑采用余弦距离。

### 古怪的状况

假使我们只要也Amy推荐乐队,她爱Phoenix、Passion Pit、以及Vampire
Weekend。和它最相似之用户是Bob,他呢喜爱就三付出乐队。他的父呢Walter
Ostanek乐队演奏手风琴,所以于此影响,他吃了立出乐队5星星评价。按照我们现的引进逻辑,我们会将马上出乐队推荐给Amy,但生或其连无希罕。

![](img/chapter-2/chapter-2-58.png)

或者试想一下,Billy Bob
Olivera教授喜读数据挖掘地方的书跟科幻小说,他最好贴近的用户是本人,因为自啊喜好就点儿种书。然而,我又是一个贵宾犬的发烧友,所以于《贵宾犬的隐秘生活》这仍开于了充分高之撤并。这样一来,现有的推荐方法会将即刻按照开介绍给Olivera教授。

![](img/chapter-2/chapter-2-59.png)

题目就是在于我们惟有因最相似之 **一个**
用户来做推荐,如果此用户有些异常之偏好,就会见直接体现在推荐内容里。解决智之一是寻觅寻多独一般的用户,这里就要用到K最接近算法了。

### K最贴近算法

以合过滤中好使用K最靠近算法来寻觅有K个最相似之用户,以此作为推荐的功底。不同的使来两样之K值,需要举行有尝试来得出。以下让到读者一个中坚的笔触。

如果我如果吗Ann做推荐,并叫K=3。使用皮尔逊相关系数得到的结果是:

![](img/chapter-2/chapter-2-60.png)

当即三个人且见面指向推荐结果有贡献,问题在我们哪确定他们之百分比为?我们直接用相关系数的比重来叙述,Sally的比重是0.8/2=40%,Eric是0.7/2=35%,Amanda则是25%:

![](img/chapter-2/chapter-2-61.png)

比方他们三人数对Grey Wardens的评分和加权后底结果如下:

![](img/chapter-2/chapter-2-62.png)

最终计算得到的分为:

![](img/chapter-2/chapter-2-63.png)

## Python推荐模块

我将本章学到之始末都集中成了一个Python类,虽然[代码](code/chapter-2/recommender.py)有来长,我或者贴在了此间:

“`python
import codecs
from math import sqrt

users = {“Angelica”: {“Blues Traveler”: 3.5, “Broken Bells”: 2.0,
                      “Norah Jones”: 4.5, “Phoenix”: 5.0,
                      “Slightly Stoopid”: 1.5,
                      “The Strokes”: 2.5, “Vampire Weekend”: 2.0},
         
         “Bill”:{“Blues Traveler”: 2.0, “Broken Bells”: 3.5,
                 “Deadmau5”: 4.0, “Phoenix”: 2.0,
                 “Slightly Stoopid”: 3.5, “Vampire Weekend”: 3.0},
         
         “Chan”: {“Blues Traveler”: 5.0, “Broken Bells”: 1.0,
                  “Deadmau5”: 1.0, “Norah Jones”: 3.0, “Phoenix”: 5,
                  “Slightly Stoopid”: 1.0},
         
         “Dan”: {“Blues Traveler”: 3.0, “Broken Bells”: 4.0,
                 “Deadmau5”: 4.5, “Phoenix”: 3.0,
                 “Slightly Stoopid”: 4.5, “The Strokes”: 4.0,
                 “Vampire Weekend”: 2.0},
         
         “Hailey”: {“Broken Bells”: 4.0, “Deadmau5”: 1.0,
                    “Norah Jones”: 4.0, “The Strokes”: 4.0,
                    “Vampire Weekend”: 1.0},
         
         “Jordyn”:  {“Broken Bells”: 4.5, “Deadmau5”: 4.0,
                     “Norah Jones”: 5.0, “Phoenix”: 5.0,
                     “Slightly Stoopid”: 4.5, “The Strokes”: 4.0,
                     “Vampire Weekend”: 4.0},
         
         “Sam”: {“Blues Traveler”: 5.0, “Broken Bells”: 2.0,
                 “Norah Jones”: 3.0, “Phoenix”: 5.0,
                 “Slightly Stoopid”: 4.0, “The Strokes”: 5.0},
         
         “Veronica”: {“Blues Traveler”: 3.0, “Norah Jones”: 5.0,
                      “Phoenix”: 4.0, “Slightly Stoopid”: 2.5,
                      “The Strokes”: 3.0}
        }

class recommender:

    def __init__(self, data, k=1, metric=’pearson’, n=5):
        “”” 初始化推荐模块
        data   训练多少
        k      K邻近算法中的价值
        metric 使用何种距离计算方式
        n      推荐结果的数
        “””
        self.k = k
        self.n = n
        self.username2id = {}
        self.userid2name = {}
        self.productid2name = {}
        # 将偏离计算办法保存下来
        self.metric = metric
        if self.metric == ‘pearson’:
            self.fn = self.pearson
        #
        # 如果data是一个字典类型,则保留下去,否则忽略
        #
        if type(data).__name__ == ‘dict’:
            self.data = data

    def convertProductID2name(self, id):
        “””通过产品ID获取名称”””
        if id in self.productid2name:
            return self.productid2name[id]
        else:
            return id

    def userRatings(self, id, n):
        “””返回该用户评分最高的物料”””
        print (“Ratings for ” + self.userid2name[id])
        ratings = self.data[id]
        print(len(ratings))
        ratings = list(ratings.items())
        ratings = [(self.convertProductID2name(k), v)
                   for (k, v) in ratings]
        # 排序并返回结果
        ratings.sort(key=lambda artistTuple: artistTuple[1],
                     reverse = True)
        ratings = ratings[:n]
        for rating in ratings:
            print(“%s\t%i” % (rating[0], rating[1]))

    def loadBookDB(self, path=”):
        “””加载BX数据集,path是数据文件位置”””
        self.data = {}
        i = 0
        #
        # 将图书评分数放入self.data
        #
        f = codecs.open(path + “BX-Book-Ratings.csv”, ‘r’, ‘utf8’)
        for line in f:
            i += 1
            #separate line into fields
            fields = line.split(‘;’)
            user = fields[0].strip(‘”‘)
            book = fields[1].strip(‘”‘)
            rating = int(fields[2].strip().strip(‘”‘))
            if user in self.data:
                currentRatings = self.data[user]
            else:
                currentRatings = {}
            currentRatings[book] = rating
            self.data[user] = currentRatings
        f.close()
        #
        # 将书籍信息存入self.productid2name
        # 包括isbn号、书名、作者等
        #
        f = codecs.open(path + “BX-Books.csv”, ‘r’, ‘utf8’)
        for line in f:
            i += 1
            #separate line into fields
            fields = line.split(‘;’)
            isbn = fields[0].strip(‘”‘)
            title = fields[1].strip(‘”‘)
            author = fields[2].strip().strip(‘”‘)
            title = title + ‘ by ‘ + author
            self.productid2name[isbn] = title
        f.close()
        #
        #  将用户信息存入self.userid2name和self.username2id
        #
        f = codecs.open(path + “BX-Users.csv”, ‘r’, ‘utf8’)
        for line in f:
            i += 1
            #print(line)
            #separate line into fields
            fields = line.split(‘;’)
            userid = fields[0].strip(‘”‘)
            location = fields[1].strip(‘”‘)
            if len(fields) > 3:
                age = fields[2].strip().strip(‘”‘)
            else:
                age = ‘NULL’
            if age != ‘NULL’:
                value = location + ‘  (age: ‘ + age + ‘)’
            else:
                value = location
            self.userid2name[userid] = value
            self.username2id[location] = userid
        f.close()
        print(i)

    def pearson(self, rating1, rating2):
        sum_xy = 0
        sum_x = 0
        sum_y = 0
        sum_x2 = 0
        sum_y2 = 0
        n = 0
        for key in rating1:
            if key in rating2:
                n += 1
                x = rating1[key]
                y = rating2[key]
                sum_xy += x * y
                sum_x += x
                sum_y += y
                sum_x2 += pow(x, 2)
                sum_y2 += pow(y, 2)
        if n == 0:
            return 0
        # 计算分母
        denominator = (sqrt(sum_x2 – pow(sum_x, 2) / n)
                       * sqrt(sum_y2 – pow(sum_y, 2) / n))
        if denominator == 0:
            return 0
        else:
            return (sum_xy – (sum_x * sum_y) / n) / denominator

    def computeNearestNeighbor(self, username):
        “””获取将近用户”””
        distances = []
        for instance in self.data:
            if instance != username:
                distance = self.fn(self.data[username],
                                   self.data[instance])
                distances.append((instance, distance))
        # 按距离排序,距离近之消在前头
        distances.sort(key=lambda artistTuple: artistTuple[1],
                       reverse=True)
        return distances

    def recommend(self, user):
       “””返回推荐列表”””
       recommendations = {}
       # 首先,获取将近用户
       nearest = self.computeNearestNeighbor(user)
       #
       # 获取用户评价了之货品
       #
       userRatings = self.data[user]
       #
       # 计算总去
       totalDistance = 0.0
       for i in range(self.k):
          totalDistance += nearest[i][1]
       # 汇总K邻近用户的评分
       for i in range(self.k):
          # 计算饼图的每个分片
          weight = nearest[i][1] / totalDistance
          # 获取用户称
          name = nearest[i][0]
          # 获取用户评分
          neighborRatings = self.data[name]
          # 获得没有评了的货品
          for artist in neighborRatings:
             if not artist in userRatings:
                if artist not in recommendations:
                   recommendations[artist] =
(neighborRatings[artist]
                                              * weight)
                else:
                   recommendations[artist] =
(recommendations[artist]
                                              +
neighborRatings[artist]
                                              * weight)
       # 开始引进
       recommendations = list(recommendations.items())
       recommendations = [(self.convertProductID2name(k), v)
                          for (k, v) in recommendations]
       # 排序并返回
       recommendations.sort(key=lambda artistTuple: artistTuple[1],
                            reverse = True)
       # 返回前n个结果
       return recommendations[:self.n]
“`

**运行示例**

第一构建一个推荐类,然后取引进结果:

“`python
>>> r = recommender(users)
>>> r.recommend(‘Jordyn’)
[(‘Blues Traveler’, 5.0)]
>>> r.recommend(‘Hailey’)
[(‘Phoenix’, 5.0), (‘Slightly Stoopid’, 4.5)]
“`

### 新的数量集

现为我们采用一个一发实际的数额集。Cai-Nicolas
Zeigler从书本漂流站收集了超越100万长达评论数据——278,858个用户为271,379本书由了细分。这卖数据(匿名)可以从[这个地点](http://www.informatik.uni-freiburg.de/~cziegler/BX/)获得,有SQL和CSV两种格式。由于特殊符号的关系,这些数据无法直接加载到Python里。我做了一些清洗,可以从\[这里下载\](http://guidetodatamining.com/guide/ch2/BX-Dump.zip)。

CSV文件包含了三张表:

* 用户表,包括用户ID、位置、年龄当消息。其中用户的全名早已隐去;
* 书籍表,包括ISBN号、标题、作者、出版日期、出版社等;
* 评分表,包括用户ID、书籍ISBN号、以及评分(0-10分开)。

达成文Python代码中之loadBookDB方法可加载这些数据,用法如下:

“`python
>>> r.loadBookDB(‘/Users/raz/Downloads/BX-Dump/’)
1700018
>>> r.recommend(‘171118’)
“`

**注意** 由于数据集比较深,大约用几十秒的光阴加载与查询。

### 项目实施

独自出运行调节了开中之代码后才能够真控制这些办法,以下是有实践建议:

  1. 兑现一个乘除曼哈顿去和欧几里得距离的不二法门;
    2.
    本书的网站及有一个包含25部电影评论的[数据集](http://guidetodatamining.com/guide/ch2/Movie\_Ratings.csv),实现一个推荐算法。
标签:

Your Comments

近期评论

    功能


    网站地图xml地图