提交 3de40211 编写于 作者: S Sylvester

add chapter 2

上级 79e36d29
# 第二章
k1
k2
接下来,考虑特征的规模。最大值和最小值是什么?它们跨越几个数量级吗?输入特性平滑的模型对输入的尺度敏感。例如,3x+ 1是输入X的简单线性函数,其输出的规模直接取决于输入的比例。其他例子包括k-均值聚类,最近邻居方法,RBF内核,以及使用欧几里得距离的任何东西。对于这些模型和建模组件,通常规范化特征以使输出保持在预期的规模上通常是一个好主意。
另一方面,逻辑函数对输入特征量表不敏感。无论输入是什么,它们的输出都是二进制的。例如,逻辑,并采取任何两个变量和输出1,当且仅当两个输入均为真。逻辑函数的另一个例子是阶跃函数“输入x大于5”。决策树模型由输入特征的阶跃函数组成。因此,基于空间划分树(决策树、梯度提升机、随机森林)的模型对尺度不敏感。唯一的例外是如果输入的规模随着时间的增长而增长,那么如果该特征是某种类型的累积计数。最终它将生长在树被训练的范围之外。如果可能是这样的话,那么就有必要周期性地重新调整输入。另一个解决方案是第5章讨论的bin计数方法。
考虑数值特征的分布也是很重要的。分布总结了承担特定价值的可能性。输入特征的分布对某些模型比其他模型更重要。例如,线性回归模型的训练过程假定预测误差分布得像高斯。这通常是好的,除非预测目标在几个数量级上扩散。在这种情况下,高斯误差假设可能不再成立。解决这一问题的一种方法是转变产出目标,以驯服规模的增长。(严格地说,这将是目标工程,而不是特征工程。)对数变换,这是一种幂变换,将变量的分布接近高斯。另一个解决方案是第5章讨论的bin计数方法。
除了裁剪模型或培训过程的假设, 多个功能可以组合成更复杂的功能。希望复杂的功能能够更简洁地捕捉原始数据中的重要信息。通过使输入功能更加 "雄辩", 模型本身可以更简单, 更容易进行培训和评估, 并做出更好的预测。作为一个极端的, 复杂的特点本身可能是统计模型的输出。这是一个称为模型堆叠的概念, 我们将在7章和8章中更详细地讨论。在本章中, 我们给出了复杂特征的最简单示例: 交互功能。
交互特征易于制定,但特征的组合导致更多的输入到模型中。为了减少计算开销,通常需要使用自动特征选择来修剪输入特征。
我们将从标量、向量和空间的基本概念开始,然后讨论尺度、分布、交互特征和特征选择。
## 标量、向量和空间
在我们开始之前, 我们需要定义一些基本概念, 这本书的其余部分。单个数字特征也称为标量。标量的有序列表称为向量。向量位于向量空间中。在绝大多数机器学习应用中, 对模型的输入通常表示为数字向量。本书的其余部分将讨论将原始数据转换为数字向量的最佳实践策略.
向量可以被可视化为空间中的一个点。(有时人们从原点到那一点画一条线和一个箭头。在这本书中,我们将主要使用这一点。例如,假设我们有一个二维向量v=[1,-1]。也就是说,向量包含两个数,在第一方向d1中,向量具有1的值,并且在第二方向d2中,它具有-1的值。我们可以在二维图中绘制v。
![A single vector](../images/chapter2/A_single_vector.png)
**Figure 2-1. A single vector.**
在数据世界中, 抽象向量及其特征维度具有实际意义。例如, 它可以代表一个人对歌曲的偏爱。每首歌都是一个特征, 其中1的值相当于大拇指向上,-1 个拇指向下。假设向量 v 表示一个听众 Bob 的喜好。Bob喜欢 Bob Dylan 的 “Blowin’ in the Wind” 和 Lady Gaga 的 "Poker Face"。其他人可能有不同的喜好。总的来说, 数据集合可以在特征空间中可视化为点云.
相反,一首歌可以由一组人的个人喜好来表示。假设只有两个听众,Alice 和 Bob。Alice 喜欢 Leonard Cohen 的 “Poker Face”, “Blowin’ in the Wind” 和 “Hallelujah”,但讨厌 Katy Perry 的 “Roar” 和 Radiohead 的 “Creep”。Bob 喜欢 “Roar", “Hallelujah”和“Blowin’ in the Wind”,但讨厌 “Poker Face” 和 “Creep” 。在听众的空间里,每一首歌都是一个点。就像我们可以在特征空间中可视化数据一样,我们可以在数据空间中可视化特征。图2-2显示了这个例子。
![Illustration of feature space vs. data space](../images/chapter2/Illustration_of_feature_space_vs_data_space.png)
**Figure 2-2. Illustration of feature space vs. data space.**
## 处理计数
在大数据时代,计数可以快速积累而不受约束。用户可以将歌曲或电影放在无限播放中,或者使用脚本反复检查流行节目的门票可用性,这会导致播放次数或网站访问计数迅速上升。当数据可以以高的体积和速度产生时,它们很可能包含一些极值。这是一个好主意,检查他们的规模,并确定是否保持它们作为原始数字,将它们转换成二进制变量,以指示存在,或将它们放入粗粒度。
## 二值化
Million Song 数据集中的用户品味画像包含了一百万个用户在 Echo Nest 的完整音乐聆听历史。下面是有关数据集的一些相关统计数据。
### Echo Nest 品味画像数据集的统计
- 有超过4800万个用户ID、音乐ID和监听计数三元组。
- 完整的数据集包含1019318个独特用户和384546首独特歌曲。
- 引文:Echo Nest 品味画像的数据子集,官方的 Million Song 数据集的用户数据集,可从这里获得:http://labrosa.ee.columbia.edu/millionsong/tasteprofile
假设任务是建立一个推荐器向用户推荐歌曲。推荐器的一个组件可以预测用户将对一首特别的歌曲会有多少喜欢。由于数据包含实际的听歌次数,这应该是预测的目标吗?如果一个大的听计数意味着用户真的喜欢这首歌,反之亦然,那是正确的。然而,数据表明,虽然99%的听计数是24或更低,也有一些听计数数以千计,最大为9667。(如图2-3所示,直方图最接近于0的bin中的峰值。但是超过10000个三元组的计数更大,几千个则有几个。这些值异常大;如果我们试图预测实际的听计数,那么模型将被这些大的值拉离。
![Histogram of listen counts in the user taste profile of the Million Song Dataset. Note that the y-axis is on a log scale.](../images/chapter2/listen_count.png)
**Figure 2-3. Histogram of listen counts in the user taste profile of the Million Song Dataset. Note that the y-axis is on a log scale.**
在 Million Song 数据集中,原始监听计数不是用户口味的可靠度量。(在统计术语中,健壮性意味着该方法在各种各样的条件下工作。)用户有不同的听力习惯。有些人可能把他们最喜欢的歌曲放在无限的循环中,而其他人可能只在特殊的场合品尝它们。很难说听一首歌20次的人一定喜欢听10次的人的两倍。
用户偏好的更健壮表示是使计数二元化和修剪所有大于1的计数为1。换句话说,如果用户至少听过一首歌,那么我们将其视为用户喜欢歌曲。这样,模型不需要花费周期来预测原始计数之间的微小差异。二进制目标是用户偏好的简单而稳健的度量。
### 例子2-1。使 Million Song 数据集中听歌计数二进制化。
```
import pandas as pd
listen_count = pd.read_csv('millionsong/train_triplets.txt.zip', header=None, delimiter='\t')
# The table contains user-song-count triplets. Only non-zero counts are
# included. Hence to binarize the count, we just need to set the entire
# count column to 1.
listen_count[2] = 1
```
这是我们设计模型目标变量的一个例子。严格地说, 目标不是一个特征, 因为它不是输入。但有时我们确实需要修改目标以解决正确的问题。
## 量化或装箱
对于本练习, 我们从第 6 轮 Yelp 数据集挑战中采集数据, 并创建一个更小的分类数据集。Yelp 数据集包含用户对来自北美和欧洲十个城市的企业的评论。每个业务都标记为零个或多个类别。以下是有关数据集的相关统计信息。
### 关于第 6 轮 Yelp 数据集的统计
- 有782种业务类别。
- 完整的数据集包含 1569264 个(约1.6M)评论和 61184 个(61K)业务。
- “餐厅”(990627个评论)和“夜生活”(210028个评论)是最流行的类别,评论计数是明智的。
- 没有业务同时属于餐厅和夜生活分类。因此,这两组评论之间没有重叠。
每个业务都有一个评论计数。假设我们的任务是使用协同过滤来预测用户可能给企业的评级。评论计数可能是一个有用的输入特征,因为通常在流行和良好的评级之间有很强的相关性。现在的问题是,我们应该使用原始评论计数或进一步处理它吗?图2-4显示了所有业务评论计数的直方图。我们看到和音乐听歌计数一样的模式。大部分的统计数字都很小,但一些企业有成千上万的评论。
### 例子2-2。在YELP数据集中可视化业务评论计数。
```
>>> import pandas as pd
>>> import json
### Load the data about businesses
>>> biz_file = open('yelp_academic_dataset_business.json')
>>> biz_df = pd.DataFrame([json.loads(x) for x in biz_file.readlines()])
>>> biz_file.close()
>>> import matplotlib.pyplot as plt
>>> import seaborn as sns
### Plot the histogram of the review counts
>>> sns.set_style('whitegrid')
>>> fig, ax = plt.subplots()
>>> biz_df['review_count'].hist(ax=ax, bins=100)
>>> ax.set_yscale('log')
>>> ax.tick_params(labelsize=14)
>>> ax.set_xlabel('Review Count', fontsize=14)
>>> ax.set_ylabel('Occurrence', fontsize=14)
```
![review count](../images/chapter2/review_count.png)
**Figure 2-4. Histogram of business review counts in the Yelp reviews dataset. The y-axis is on a log-scale.**
对于许多模型来说,跨越数个数量级的原始计数是有问题的。在线性模型中,相同的线性系数必须对计数的所有可能值工作。大量的计数也可能破坏无监督学习方法,如k-均值聚类,它使用相似性函数来测量数据点之间的相似性。k-均值使用数据点之间的欧几里得距离。数据向量的一个元素中的大计数将超过所有其他元素中的相似性,这可能会丢弃整个相似性度量。
一种解决方案是通过量化计数来包含标量。换句话说,我们将计数分组到容器中,并且去掉实际的计数值。量化将连续数映射成离散数。我们可以把离散化的数字看作是代表强度度量的容器的有序的序列。
为了量化数据,我们必须决定每一个箱子应该有多宽。解决方案分为固定宽度或自适应两种类型。我们将给出每个类型的例子。
### 固定宽度装箱
对于固定宽度装箱, 每个 bin 都包含一个特定的数值范围。范围可以是定制设计或自动分割, 它们可以线性缩放或指数缩放。例如, 我们可以将一个人的年龄分组为十年: 0-9 岁归纳到bin 1, 10-19 年归纳到 bin 2 等。要从计数映射到 bin, 只需除以 bin 的宽度并取整部分。
也经常看到定制设计的年龄范围更适合于生活的阶段:
- 0-12 岁
- 12-17 岁
- 18-24 岁
- 25-34 岁
- 35-44 岁
- 45-54 岁
- 55-64 岁
- 65-74 岁
- 75 岁以上
当数字跨越多个数量级时,最好用10个幂(或任何常数的幂)来分组:0-9、10-99、100-999、100-9999等。容器宽度呈指数增长,从O(10)、O(100)到O(1000)和以上。要从计数映射到bin,取计数的log值。指数宽度的划分与对数变换非常相关,我们在“对数变换”中讨论。
### 例子2-3。用固定宽度的箱进行量化计数
```
>>> import numpy as np
### Generate 20 random integers uniformly between 0 and 99
>>> small_counts = np.random.randint(0, 100, 20)
>>> small_counts
array([30, 64, 49, 26, 69, 23, 56, 7, 69, 67, 87, 14, 67, 33, 88, 77, 75, 47, 44, 93])
### Map to evenly spaced bins 0-9 by division
>>> np.floor_divide(small_counts, 10)
array([3, 6, 4, 2, 6, 2, 5, 0, 6, 6, 8, 1, 6, 3, 8, 7, 7, 4, 4, 9], dtype=int32)
### An array of counts that span several magnitudes
>>> large_counts = [296, 8286, 64011, 80, 3, 725, 867, 2215, 7689, 11495, 91897, 44, 28, 7971, 926, 122, 22222]
### Map to exponential-width bins via the log function
>>> np.floor(np.log10(large_counts))
array([ 2., 3., 4., 1., 0., 2., 2., 3., 3., 4., 4., 1., 1., 3., 2., 2., 4.])
```
### 分位数装箱
Fixed-width binning is easy to compute. But if there are large gaps in the counts, then there will be many empty bins with no data. This problem can be solved by adaptively positioning the bins based on the distribution of data. This can be done using the quantiles of the distribution.
固定宽度装箱很容易计算。但是如果计数有很大的差距, 那么将会有许多空的垃圾箱没有数据。该问题可以通过基于数据分布的垃圾箱自适应定位来解决。这可以使用分发的分位数来完成。
15~
~54
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册