73.md 9.9 KB
Newer Older
片刻小哥哥's avatar
片刻小哥哥 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208
# 无监督学习: 寻求数据表示

校验者:
        [@片刻](https://github.com/apachecn/scikit-learn-doc-zh)
翻译者:
        [@X](https://github.com/apachecn/scikit-learn-doc-zh)

## 聚类: 对样本数据进行分组

可以利用聚类解决的问题

对于 iris 数据集来说,我们知道所有样本有 3 种不同的类型,但是并不知道每一个样本是那种类型:此时我们可以尝试一个 **clustering task(聚类任务)** 聚类算法: 将样本进行分组,相似的样本被聚在一起,而不同组别之间的样本是有明显区别的,这样的分组方式就是 _clusters(聚类)_

### K-means 聚类算法

关于聚类有很多不同的聚类标准和相关算法,其中最简便的算法是 [K-means](../../modules/clustering.html#k-means)

[![http://sklearn.apachecn.org/cn/0.19.0/_images/sphx_glr_plot_cluster_iris_002.png](img/43fc8286f3bb11d7c8eb1e83e6538ac6.jpg)](../../auto_examples/cluster/plot_cluster_iris.html)

```py
>>> from sklearn import cluster, datasets
>>> iris = datasets.load_iris()
>>> X_iris = iris.data
>>> y_iris = iris.target

>>> k_means = cluster.KMeans(n_clusters=3)
>>> k_means.fit(X_iris) 
KMeans(algorithm='auto', copy_x=True, init='k-means++', ...
>>> print(k_means.labels_[::10])
[1 1 1 1 1 0 0 0 0 0 2 2 2 2 2]
>>> print(y_iris[::10])
[0 0 0 0 0 1 1 1 1 1 2 2 2 2 2]

```

Warning

k_means 算法无法保证聚类结果完全绝对真实的反应实际情况。首先,选择正确合适的聚类数量不是一件容易的事情,第二,该算法对初始值的设置敏感,容易陷入局部最优。尽管 scikit-learn 采取了不同的方式来缓解以上问题,目前仍没有完美的解决方案。

| [![k_means_iris_bad_init](img/41c9612e6e74708a274b11f770810663.jpg)](../../auto_examples/cluster/plot_cluster_iris.html) | [![k_means_iris_8](img/f7ee2b868860148ea59bc617d8ba7bb1.jpg)](../../auto_examples/cluster/plot_cluster_iris.html) | [![cluster_iris_truth](img/9839512f63b7e5de021f13f7e6bd6b22.jpg)](../../auto_examples/cluster/plot_cluster_iris.html) |
| **Bad initialization** | **8 clusters** | **Ground truth** |

**Don’t over-interpret clustering results(不要过分解读聚类结果)**

**Application example: vector quantization(应用案例:向量量化(vector quantization))**

一般来说聚类,特别是 K_means 聚类可以作为一种用少量样本来压缩信息的方式。这种方式就是 [vector quantization](https://en.wikipedia.org/wiki/Vector_quantization) 。例如,K_means 算法可以用于对一张图片进行色调分离:

```py
>>> import scipy as sp
>>> try:
...    face = sp.face(gray=True)
... except AttributeError:
...    from scipy import misc
...    face = misc.face(gray=True)
>>> X = face.reshape((-1, 1)) # We need an (n_sample, n_feature) array
>>> k_means = cluster.KMeans(n_clusters=5, n_init=1)
>>> k_means.fit(X) 
KMeans(algorithm='auto', copy_x=True, init='k-means++', ...
>>> values = k_means.cluster_centers_.squeeze()
>>> labels = k_means.labels_
>>> face_compressed = np.choose(labels, values)
>>> face_compressed.shape = face.shape

```

| [![face](img/c593cc77e5133571028587b75182d3b3.jpg)](../../auto_examples/cluster/plot_face_compress.html) | [![face_compressed](img/c8b386f383c840e769d6dae0eeac73dd.jpg)](../../auto_examples/cluster/plot_face_compress.html) | [![face_regular](img/9cb7de99579cbd4664159c8a06417d13.jpg)](../../auto_examples/cluster/plot_face_compress.html) | [![face_histogram](img/3a03009ea272ed427cfa033086b89c72.jpg)](../../auto_examples/cluster/plot_face_compress.html) |
| Raw image | K-means quantization | Equal bins | Image histogram |

### 分层聚类算法: 谨慎使用

```py
 分层聚类算法是一种旨在构建聚类层次结构的分析方法一般来说实现该算法的大多数方法有以下两种
```

*   **Agglomerative(聚合)** - 自底向上的方法: 初始阶段,每一个样本将自己作为单独的一个簇,聚类的簇以最小

化距离的标准进行迭代聚合。当感兴趣的簇只有少量的样本时,该方法是很合适的。如果需要聚类的 簇数量很大,该方法比K_means算法的计算效率也更高。 * **Divisive(分裂)** - 自顶向下的方法: 初始阶段,所有的样本是一个簇,当一个簇下移时,它被迭代的进 行分裂。当估计聚类簇数量较大的数据时,该算法不仅效率低(由于样本始于一个簇,需要被递归的进行 分裂),而且从统计学的角度来讲也是不合适的。

#### 连接约束聚类

对于逐次聚合聚类,通过连接图可以指定哪些样本可以被聚合在一个簇。在 scikit 中,图由邻接矩阵来表示,通常该矩阵是一个稀疏矩阵。这种表示方法是非常有用的,例如在聚类图像时检索连接区域(有时也被称为连接要素):

[![http://sklearn.apachecn.org/cn/0.19.0/_images/sphx_glr_plot_face_ward_segmentation_001.png](img/6521e34e11e73c0fae9a5bd3c7980a9f.jpg)](../../auto_examples/cluster/plot_face_ward_segmentation.html)

```py

import matplotlib.pyplot as plt

from sklearn.feature_extraction.image import grid_to_graph
from sklearn.cluster import AgglomerativeClustering

# #############################################################################
# Generate data
try:  # SciPy >= 0.16 have face in misc
    from scipy.misc import face
    face = face(gray=True)
except ImportError:
    face = sp.face(gray=True)

# Resize it to 10% of the original size to speed up the processing
face = sp.misc.imresize(face, 0.10) / 255.

X = np.reshape(face, (-1, 1))

# #############################################################################
# Define the structure A of the data. Pixels connected to their neighbors.
connectivity = grid_to_graph(*face.shape)

# #############################################################################

```

#### 特征聚集

我们已经知道,稀疏性可以缓解特征维度带来的问题,_i.e_ 即与特征数量相比,样本数量太少。 另一个解决该问题的方式是合并相似的维度:**feature agglomeration(特征聚集)**。该方法可以通过对特征聚类来实现。换 句话说,就是对样本数据转置后进行聚类。

[![http://sklearn.apachecn.org/cn/0.19.0/_images/sphx_glr_plot_digits_agglomeration_001.png](img/2d7a3ddf62ceb125c15ba1947173e790.jpg)](../../auto_examples/cluster/plot_digits_agglomeration.html)

```py
>>> digits = datasets.load_digits()
>>> images = digits.images
>>> X = np.reshape(images, (len(images), -1))
>>> connectivity = grid_to_graph(*images[0].shape)

>>> agglo = cluster.FeatureAgglomeration(connectivity=connectivity,
...                                      n_clusters=32)
>>> agglo.fit(X) 
FeatureAgglomeration(affinity='euclidean', compute_full_tree='auto',...
>>> X_reduced = agglo.transform(X)

>>> X_approx = agglo.inverse_transform(X_reduced)
>>> images_approx = np.reshape(X_approx, images.shape)

```

`transform` and `inverse_transform` methods

Some estimators expose a `transform` method, for instance to reduce the dimensionality of the dataset.

## 分解: 将一个信号转换成多个成份并且加载

**Components and loadings(成分和载荷)**

如果 X 是多维数据,那么我们试图解决的问题是在不同的观察基础上对数据进行重写。我们希望学习得到载荷 L 和成分 C 使得 _X = L C_ 。提取成分 C 有多种不同的方法。

### 主成份分析: PCA

[主成分分析(PCA)](../../modules/decomposition.html#pca) 将能够解释数据信息最大方差的的连续成分提取出来

[![pca_3d_axis](img/33a8ceddf8e3edfad259a804819c2637.jpg)](../../auto_examples/decomposition/plot_pca_3d.html) [![pca_3d_aligned](img/c39b576ee6e4fc82b4d9edd06ffc8c9c.jpg)](../../auto_examples/decomposition/plot_pca_3d.html)

上图中样本点的分布在一个方向上是非常平坦的:即三个单变量特征中的任何一个都可以有另外两个特征来表示。主成分分析法(PCA)可以找到使得数据分布不 _flat_ 的矢量方向(可以反映数据主要信息的特征)。

当用主成分分析(PCA)来 _transform(转换)_ 数据时,可以通过在子空间上投影来降低数据的维数。

```py
>>> # Create a signal with only 2 useful dimensions
>>> x1 = np.random.normal(size=100)
>>> x2 = np.random.normal(size=100)
>>> x3 = x1 + x2
>>> X = np.c_[x1, x2, x3]

>>> from sklearn import decomposition
>>> pca = decomposition.PCA()
>>> pca.fit(X)
PCA(copy=True, iterated_power='auto', n_components=None, random_state=None,
 svd_solver='auto', tol=0.0, whiten=False)
>>> print(pca.explained_variance_)  
[  2.18565811e+00   1.19346747e+00   8.43026679e-32]

>>> # As we can see, only the 2 first components are useful
>>> pca.n_components = 2
>>> X_reduced = pca.fit_transform(X)
>>> X_reduced.shape
(100, 2)

```

### 独立成分分析: ICA

[独立成分分析(ICA)](../../modules/decomposition.html#ica) 可以提取数据信息中的独立成分,这些成分载荷的分布包含了最多的 的独立信息。该方法能够恢复 **non-Gaussian(非高斯)** 独立信号:

[![http://sklearn.apachecn.org/cn/0.19.0/_images/sphx_glr_plot_ica_blind_source_separation_001.png](img/5f0a6e9a20a071d688e183c9675544e5.jpg)](../../auto_examples/decomposition/plot_ica_blind_source_separation.html)

```py
>>> # Generate sample data
>>> import numpy as np
>>> from scipy import signal
>>> time = np.linspace(0, 10, 2000)
>>> s1 = np.sin(2 * time)  # Signal 1 : sinusoidal signal
>>> s2 = np.sign(np.sin(3 * time))  # Signal 2 : square signal
>>> s3 = signal.sawtooth(2 * np.pi * time)  # Signal 3: saw tooth signal
>>> S = np.c_[s1, s2, s3]
>>> S += 0.2 * np.random.normal(size=S.shape)  # Add noise
>>> S /= S.std(axis=0)  # Standardize data
>>> # Mix data
>>> A = np.array([[1, 1, 1], [0.5, 2, 1], [1.5, 1, 2]])  # Mixing matrix
>>> X = np.dot(S, A.T)  # Generate observations

>>> # Compute ICA
>>> ica = decomposition.FastICA()
>>> S_ = ica.fit_transform(X)  # Get the estimated sources
>>> A_ = ica.mixing_.T
>>> np.allclose(X,  np.dot(S_, A_) + ica.mean_)
True

```