chapter 2JS 仿腾讯发表微博之力量代码。

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

不久前2天研究了下 腾讯发表微博之职能 特这来划分享下,效果如下:

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

betway官网手机版 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),实现一个推荐算法。

相关文章

admin

网站地图xml地图