# 1.2 Data Visualization & Dimension Reduction

* 我们实际中遇到的数据往往都在高维空间上。在拿到了数据之后，为了对不同样本之间的相似程度有一些直观的认识，最直接的做法就是进行可视化。常见的可视化方法通过降维(dimensional reduction)的方法把高维空间上的样本点投影到二维平面上，使得相似的样本靠得更近，不相似的样本离得更远。
* 数据可视化可以让我们对分类的效果有一个大致的预期。多数降维方法都属于无监督学习的范畴。如果通过无监督的降维可视化，都可以发现发现带有同一个label的样本明显的聚集成一群，这就是一个比较容易的分类问题，我们可以预期一个比较好的分类效果。
* 最常见的用于可视化的降维方法有:
  * PCA (Principal component analysis): 线性降维，除了可视化还可以用来做很多其他分析
  * MDS (Multidimensional scaling, 有时又叫做Principal Coordinates Analysis, PCoA)
  * tSNE (t-distributed stochastic neighbor embedding)
  * UMAP (Uniform Manifold Approximation and Projection)
* 除此之外还有大量的降维方法，有一些降维方法的作用也不限于数据可视化，有兴趣的同学可以自行了解。
* 这些方法前人都已经实现好了现成的工具，我们可以直接拿来使用。我们这里主要介绍如何利用python和R中现有的工具来实现PCA和tSNE。

## 1) 基本原理

### 1a) PCA

* PCA的主要思想是找到k组线性组合，将n维特征投影到k维上，使得新的k维特征彼此正交，并且可以尽可能多的解释数据中的variation。
* 这样得到新的k维特征就被称为k个主成分。k个主成分实际上对应着我们从输入数据估计出的协方差矩阵最大的k个特征值对应的特征向量。
* 目前已经有很多高度优化的数值计算的工具实现了矩阵的特征向量的求解(一般是通过singular vector decomposition一类的方法实现的)，在实践中我们直接调用即可。
* 对于数据可视化，因为我们需要把数据投影到二维平面上，所以只需要考虑前两个主成分。
* 在生物信息学分析中，PCA是样本量不多的bulk RNA-seq转录组的可视化最常用的方法。
* 在python中, `sklearn.decomposition`中的[PCA](https://scikit-learn.org/stable/modules/generated/sklearn.decomposition.PCA.html)类为主成分分析提供了非常方便的接口。
* 原生的R语言自带一个`prcomp`函数，实现了主成分分析的功能。

### 1b) t-SNE

* t-SNE（t-Distribution Stochastic Neighbour Embedding）翻译名为"t-分布随机近邻嵌入"，是一种专门用于可视化的降维方法。
* t-SNE主要的优势就是保持非线性的局部结构的能力，比较适用于样本量较大，样本之间相互关系比较复杂的数据，所以在单细胞转录组的可视化中有大量应用。
* 在python中, `sklearn.manifold`中的[TSNE](https://scikit-learn.org/stable/modules/generated/sklearn.manifold.TSNE.html)类为tSNE提供了非常方便的接口。
* 在R语言中，t-SNE可以用`Rtsne`这个package来实现。Rtsne host在CRAN上，用`install.packages("Rtsne")`即可安装。

## 2) 实例

### 2a) Data

* 我们用iris(鸢尾花)这样一个一个toy dataset来演示如何在python和R语言中用PCA和tSNE进行可视化。sklearn和原生的R语言都自带这样一个示例数据。

### 2b) Python

**加载模块**

```python
from sklearn.datasets import load_iris
from sklearn.decomposition import PCA
from sklearn.manifold import TSNE
from sklearn.preprocessing import StandardScaler
from matplotlib import pyplot as plt
```

**加载数据**

```python
iris_dataset = load_iris()
X = iris_dataset['data']
y = iris_dataset['target']
names = iris_dataset['target_names']
X = StandardScaler().fit_transform(X) # Z score scaling
```

**利用PCA可视化**

```python
X2d = PCA(2).fit_transform(X)
fig,ax = plt.subplots(figsize=(4.5,4))
for i in range(3):
    plt.scatter(X2d[y==i,0],X2d[y==i,1],label=names[i])
ax.set_xlabel("PC-1")
ax.set_ylabel("PC-2")
plt.legend()
plt.show()
#plt.savefig("PCA-plot.png",bbox_inches="tight")
```

PCA的结果如下

![png](https://4115668567-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LPVsf5VZbQ7h14X29qW%2Fuploads%2Fgit-blob-98439c134b46a744842c71b8a67f01068f534ed9%2Firis-python-PCA-plot.png?alt=media)

**利用tSNE可视化**

```python
X2d = TSNE(2).fit_transform(X)
fig,ax = plt.subplots(figsize=(4.5,4))
for i in range(3):
    plt.scatter(X2d[y==i,0],X2d[y==i,1],label=names[i])
ax.set_xlabel("tSNE-1")
ax.set_ylabel("tSNE-2")
plt.legend()
plt.show()
#plt.savefig("tSNE-plot.png",bbox_inches="tight")
```

t-SNE的结果如下

![png](https://4115668567-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LPVsf5VZbQ7h14X29qW%2Fuploads%2Fgit-blob-444712a39893bd7a743f7746ed6bb860c296c4b6%2Firis-python-tSNE-plot.png?alt=media)

### 2c) Visualization with R

**加载模块**

```r
library("Rtsne")
library("ggplot2")
```

**加载数据**

```r
X <- as.matrix(iris[,1:4])
X <- scale(X, center = T, scale = T)
```

**利用PCA可视化**

```r
pca.res <- prcomp(X, center = F, scale = F, rank. = 2)
iris$PC1 <- pca.res$x[,1]
iris$PC2 <- pca.res$x[,2]
ggplot(iris, aes(x=PC1, y=PC2,color=species)) + geom_point() + theme_bw()
```

PCA的结果如下

![png](https://4115668567-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LPVsf5VZbQ7h14X29qW%2Fuploads%2Fgit-blob-a9a342a0c598ff30d3d0c8e98e9edb000aec55e0%2Fr-iris-PCA-plot.png?alt=media)

**利用tSNE可视化**

```r
tsne.res <- Rtsne(X, dims = 2, check_duplicates = F)
iris$tSNE1 <- tsne.res$Y[,1]
iris$tSNE2 <- tsne.res$Y[,2]
ggplot(iris, aes(x=tSNE1, y=tSNE2,color=species)) + geom_point() + theme_bw()
```

t-SNE的结果如下

![png](https://4115668567-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-LPVsf5VZbQ7h14X29qW%2Fuploads%2Fgit-blob-158fe9166b58265d06c85a725469d0d9873b95aa%2Fr-iris-tSNE-plot.png?alt=media)

## 3) Homework

对乳腺癌数据集 [BreastCancer.csv](https://cloud.tsinghua.edu.cn/d/ad22768345664924b202/?p=%2FFiles%2FPART_IV\&mode=list) 进行降维和可视化。 数据集第一列为样本编号，最后一列是样本的标签(即良性/benign和恶性/malignant)，剩下9列对应9个特征。 请参考本章内容,使用你最熟悉的脚本语言，用PCA（或者其他降维方法）对该数据进行降维可视化，用颜色标明样本标签（即良性和恶行样本使用不同的颜色），提交图片和相应的代码。

> 提示：在PCA前，需要进行数据空缺值填充（用特征的样本中位数补全缺失值）和data scaling（任意一种方式均可）。

## 4) 阅读材料

* 2008, *JMLR*, [Visualizing Data using t-SNE](https://www.jmlr.org/papers/volume9/vandermaaten08a/vandermaaten08a.pdf) (对t-SNE的原理感兴趣的同学可参考)
* 2018, *Nature Biotechnology*, [Dimensionality reduction for visualizing single-cell data using UMAP](https://www.nature.com/articles/nbt.4314)
* 2019, *Nature Communication*, [The art of using t-SNE for single-cell transcriptomics](https://www.nature.com/articles/s41467-019-13056-x)
