钱柜游戏官网 > 综合体育 > 无监督学习算法

综合体育

无监督学习算法

监察学习算法:线性回归,逻辑回归,神经互连网,SVM

无监控学习算法:聚类算法,降维算法

破例算法:推荐算法

除外那几个算法以外,有局部算法的名字在机器学习园地中也平日现身。但他俩自己并不算是二个机械学习算法,而是为了清除某块头难点而诞生的。你能够明白他们为上述算法的子算法,用于大幅度升高训练进度。此中的象征有:

梯度下落法,首要利用在线型回归,逻辑回归,神经互连网,推荐算法中;

Newton法,首要行使 在线型回归中;

BP算法,首要利用在神经网络中;

SMO算法,首要行使在SVM中。

 

# 第二章:推荐系统入门

原文:

内容:
* 推荐系统职业原理
* 社会化协同过滤职业原理
* 怎么着找到相符物品
* 曼哈顿相距
* 欧几里得间隔
* 闵可夫斯基间距
* 皮尔逊相关全面
* 余弦相同度
* 使用Python完成K最临近算法
* 图书漂流站(BookCrossing)数据集

## 你心爱的事物自个儿也垂怜

我们将从推荐系统初阶,开启数据发掘之旅。推荐系统无处不在,如亚马逊(亚马逊(Amazon卡塔尔国卡塔尔网址的“看过这件商品的顾客还购买过”板块:

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

last.fm上对音乐和演奏会的推荐(相近歌唱家):

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

在亚马逊的例证里,它用了多少个因一贯进展推荐介绍:一是自己浏览了里维斯翻译的《法华经》生机勃勃书;二是此外浏览过该书的消费者还浏览过的译作。

本章大家汇报的引入方法称为合营过滤。看名就能够猜到其意义,那几个方式是运用旁人的喜好来开展推荐,也正是说,是膏腴贵游一齐爆发的引荐。他的劳作规律是如此的:如果要推荐一本书给您,小编会在网址上搜索三个和你就好像的客商,然后将他心爱的书本推荐给您——比如巴奇加澳元的《发条女孩》。

### 怎么着找到相像的客户?

据此首先要做的专门的学问是找到类似的客商。这里用最简便的二维模型来说述。借使客商会在网址用五颗星来争辨一本书——未有星表示书写得很糟,五颗星表示很好。因为我们用的是二维模型,所以仅对两本书举办业评比价:史蒂芬森的《雪崩》(纵轴)和Larsson的《龙纹身的女孩》(横轴)。

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

先是,下表突显有四个人客户对这两本书做了争辩:

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

现行反革命自身想为神秘的X先生推荐一本书,他给《雪崩》打了四星,《龙纹身的女孩》两星。第三个任务是寻觅哪些客户和她最为相近。大家用间隔来表示。

### 曼哈顿相差

最简便的间距计算方法是曼哈顿相距。在二维模型中,各种人都得以用(x, y卡塔尔(英语:State of Qatar)的点来表示,这里自个儿用下标来表示差异的人,(x<sub>1</sub>, y<sub>1</sub>卡塔尔(قطر‎表示Aimee,(x<sub>2</sub>, y<sub>2</sub>)表示那位神秘的X先生,那么她们之间的曼哈顿间距正是:

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

约等于x之差的断然值加上y之差的断然值,那样他们的偏离正是4。

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

总体的计量结果如下:

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

Aimee的间隔这几天,在她的浏览历史中能够见到他曾给巴奇加美元的《发条女孩》打过五星,于是大家就能够把这本书推荐给X先生。

### 欧几里得间隔

曼哈顿间距的长处之一是估测计算速度快,对于推特那样须求计算百万客商之间的相符度时就不行便于。

**勾股定理**

或许你还隐隐记得勾股定理。另风华正茂种计算间距的艺术正是看两点之间的直线间隔:

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

动用勾股定理,大家得以如下总结距离:

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

那条斜线正是欧几里得间隔,公式是:

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

遥想一下,这里的x<sub>1</sub>表示客商1心仪《龙纹身》的品位,x<sub>2</sub>是客商2中意这本书的水平;y<sub>1</sub>则是客户1合意《雪崩》的水准,y<sub>2</sub>是顾客2中意那本书的等级次序。

Aimee给《龙纹身》和《雪崩》都打了五颗星,神秘的X先素不相识别打了两星和四星,那样他们之间的欧几里得间隔便是:

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

以下是任何客户的乘除结果:

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

### N维模型

刚才我们独有对两本书实行评价(二维模型),上面让我们扩充学一年级下,尝试更眼花缭乱的模子。假若大家几方今要为一个在线音乐网址的客商推荐乐队。客户能够用1至5星来评价叁个乐队,个中积攒半星(如2.5星)。下表显示了8位客户对8支乐队的评论和介绍:

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

表中的短横表示那位客商并未有给那支乐队打分。大家在总括七个客商的离开时,只利用他们都评价过的乐队,举个例子要计算Angelica和Bill的相距,大家只会用到5支乐队。那多少个客户的曼哈顿间距为:

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

最终离开正是上方数据的加和:(1.5 + 1.5 + 3 + 2 + 1卡塔尔国。

总结欧几里得间距的方法也是看似的,大家也只取两个都评价过的乐队。

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

用公式来陈述即:

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

**左右了啊?** 那就探寻计算其余多少个顾客之间的离开吗。

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

**有个缺欠**

当我们总计Hailey和Veronica的偏离时会发现二个主题材料:他们同盟批评的乐队独有两支(娜拉h 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象征使用欧几里得距离
```

### 客户的标题

让我们紧凑看看用户对乐队的评分,可以开采各种顾客的打分标准十三分例外:

* 比尔未有打出Infiniti的分数,都在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分。

### Pearson相关周密

杀绝方法之一是利用Pearson相关周详。轻易起见,大家先看上面包车型客车数额(和此前的多少分歧):

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

这种现象在数码发现领域称为“分数膨胀”。Clara最低给了4分——她具备的打分都在4至5分之间。我们将它绘制作而成图表:

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

**一条直线——完全符合!!!**

直线即表示克拉拉和罗Bert的偏幸完全大器晚成致。他们皆认为Phoenix是最好的乐队,然后是Blues Traveler、Norah Jones。假如Clara和Robert的见识不相似,那么落在直线上的点就越少。

**眼光基本黄金年代致的动静**

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

**思想不太相像的图景**

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

故而从图纸上知道,意见相平等表现为一条直线。Pearson相关周全用于衡量五个变量之间的相关性(这里的五个变量指的是Clara和罗Bert),它的值在-1至1之间,1意味完全相符,-1意味完全相反。从直观上了然,最起先的那条直线Pearson相关周全为1,第二张是0.91,第三张是0.81。由此大家使用这点来找到相符的客户。

Pearson相关周详的总括公式是:

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

这里本身说说本身的经验。小编大学读的是今世音乐艺术,课程包涵芭蕾、现代派舞蹈、衣裳设计等,未有别的数学课程。作者高级中学读的是男儿高校,学习了管道工程和汽车维修,只了然很根基的数学知识。不知是因为自个儿的学科背景,如故习贯于用直觉来揣摩,当自家遇见这么的数学公式时会习于旧贯性地跳过,继续读下边包车型大巴文字。假如您和本人相通,我生硬建议你与这种惰性抗争,试着去精通那几个公式。它们纵然看起来很复杂,但还是能够够被常人所知道的。

地点的公式除了看起来相比较复杂,另贰个难点是要拿走计算结果必得对数据做往往遍历。万幸我们有别的三个公式,能够计算Pearson相关周详的雷同值:

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

以此公式即使看起来特别深根固柢,何况其总括结果会不太平静,有必然标称误差存在,但它最大的优点是,用代码完毕的时候能够只遍历一遍数据,大家会在下文看见。首先,我们将以此公式做三个表明,总括上面那一个表明式的值:

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

对此Clara和罗Bert,大家能够得到:

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

很简短把?上面咱们计算这么些公式:

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

Clara的总评分是22.5, 罗Bert是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)

对此罗Bert,我们用同生龙活虎的措施总括:

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

最终得到:

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

所以,1意味Clara和罗Bert的溺爱完全适合。

**先苏息一下吧**

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

**计算Pearson相关周全的代码**

```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那首歌作者播放了21次,但很有希望您叁次都未有听过。事实上,上边列出的这几个歌曲只怕您一首都没听过。别的,iTunes上有1500万首音乐,而本身只听过4000首。所以说单个顾客的数量是 *稀疏* 的,因为非零值较完整要少得多。当大家用1500万首歌曲来相比五个顾客时,很有十分大希望他们之间未有其他交集,这样一来就未能总括他们中间的相距了。

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

接近的气象是在酌量两篇著作的相同度时。例如说大家想找一本和《The Space Pioneers》相像佛的书,方法之一是选择单词现身的功效,即总计每一种单词在书中现身的次数占全书单词的百分比,如“the”现身频率为6.13%,“汤姆” 0.89%,“space” 0.伍分一。大家得以用那么些多少来查找一本周围的书。不过,这里相近有数据的荒废性难题。《The Space Pioneers》中有66二十六个差异的单词,但英文语言中有当先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)

* 借使数量存在“分数膨胀”难点,就动用Pearson相关周详。
* 借使数据相比“密集”,变量之间基本都存在公有值,且那么些离开数据是比较重大的,这就动用欧几里得或曼哈顿间隔。
* 假若数据是抛荒的,则利用余弦相符度。

于是,假使数额是凝聚的,曼哈顿间隔和欧几里得间隔都以适用的。那么荒芜的数目足以行使啊?大家来看二个也和音乐有关的言传身教:尽管有六人,每人都给100首音乐评过分。

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

* Jake(左):民谣的忠诚客官。
* Linda和Eric(右):大家爱三十时期的爵士乐!

Linda和埃里克向往相通的音乐,他们的评分列表中有20首雷同的的歌曲,且评分均值相差不到0.5!所以她们中间的曼哈顿间隔为20 x 0.5 = 10,欧几里得间距则为:

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

Linda和Jake只协同评分了风流罗曼蒂克首歌曲:克Rees Cagle的 *What a Beautiful Day* 。琳达打了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和凯尔西。他们和Jake都具备非常相像的音乐偏幸,此中Jake在我们网址上评价了25首歌曲。

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

Cooper评价了26首歌曲,在那之中25首和Jake是相像的。他们对每首歌曲的评说差值唯有0.25!

凯尔西在大家网址上商议了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。和她最相近的客商是鲍伯,他也爱不释手那三支乐队。他的老爸为WalterOstanek乐队演奏手风琴,所以受此影响,他给了那支乐队5星评价。根据大家今后的推荐逻辑,大家会将那支乐队推荐给Amy,但有相当大恐怕他并不爱好。

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

只怕试想一下,Billy Bob奥利弗a教师心仪读书数据开掘地点的图书以致科学幻想小说,他最临近的客商是本人,因为本身也兴奋那二种书。然则,作者又是一个贵宾犬的爱好者,所以给《贵宾犬的隐私生活》这本书打了超级高的分。那样一来,现存的引进方法会将那本书介绍给奥利弗a教师。

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

难点就在于大家只依赖最肖似的 **一个** 顾客来做推荐,要是那么些客商某些异样的偏心,就能够一贯反映在举荐内容里。解决办法之一是寻觅多少个平时的客户,这里就要用到K最临近算法了。

### K最接近算法

在联合过滤中能够使用K最接近算法来寻觅K个最相符的客户,以此作为推荐的底子。分歧的施用有区别的K值,供给做一些实验来得出。以下给到读者壹此中坚的思绪。

万风流罗曼蒂克作者要为Ann做推荐,并令K=3。使用Pearson相关周全得到的结果是:

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

那多个人都会对推荐结果有所进献,难点在于大家怎样规定他们的比例呢?我们一向用相关周到的百分比来描述,Sally的百分比是0.8/2=十分之六,Eric是0.7/2=35%,Amanda则是六成:

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

假如他们多个人对Grey 沃德ens的评分以致加权后的结果如下:

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

末了计算获得的分数为:

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

## Python推荐模块

本身将本章学到的剧情都汇聚成了一个Python类,纵然[代码](code/chapter-2/recommender.py卡塔尔(英语:State of Qatar)有个别长,作者依旧贴在了那边:

```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("%st%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-NicolasZeigler从画集漂流站搜集了超越100万条商量数据——278,8伍十四位顾客为271,379本书打了分。这份数据(无名氏)能够从[本条地点](

CSV文件包蕴了三张表:

* 客户表,满含客户ID、地方、年龄等消息。在那之中客户的真名已经隐去;
* 书籍表,包蕴ISBN号、标题、我、出版日期、出版社等;
* 评分表,满含客商ID、书籍ISBN号、以至评分(0-10分)。

上文Python代码中的loadBookDB方法能够加载那个多少,用法如下:

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

**注意** 由于数据集比十分大,大致需求几十秒的年月加载和询问。

### 项目实行

唯有运维调解过书中的代码后技能真的通晓那些格局,以下是部分实行建议:

  1. 福寿绵绵四个计量曼哈顿相距和欧几里得间隔的艺术;
    2. 本书的网址上有叁个包蕴25部摄像争辩的[数据集](
上一篇:没有了 下一篇:没有了