编辑:AIWay 1024
在包含行和列的表格数据集中,列代表 n 维特征空间的维数,行则是该空间中的数据点。
降维简单地说,就是在尽可能保留原始数据集变化的前提下,减少数据集中属性的数量。这是一个数据预处理步骤,意味着我们要在训练模型之前进行降维。在本文中,我们将讨论 11 种降维技术,并使用 Python 和 Scikit-learn 库在现实世界的数据集上实现这些技术。
数据维数越少,意味着训练时间和计算资源越少,机器学习算法的整体性能也就越高--涉及许多特征的机器学习问题会使训练速度极慢。高维空间中的大多数数据点都非常接近该空间的边界。这是因为高维空间的空间很大。在高维数据集中,大多数数据点之间可能相距甚远。因此,算法无法有效、高效地对高维数据进行训练。在机器学习中,这种问题被称为 "维度诅咒"(curse of dimensionality)--这只是一个技术术语,你不必担心! 降维可避免过拟合问题--当数据中存在许多特征时,模型就会变得更加复杂,并倾向于对训练数据进行过拟合。 降维对于数据可视化非常有用--当我们把高维数据的维数降为两到三个分量时,数据就可以很容易地绘制成二维或三维图。 降维处理多重共线性--在回归中,当一个自变量与一个或多个其他自变量高度相关时,就会出现多重共线性。降维可以利用这一点,将这些高度相关的变量合并成一组不相关的变量。这将解决多重共线性问题。
降维对于因子分析非常有用--这是一种有用的方法,可以找到潜在的变量,这些变量不是直接用单一变量来测量的,而是从数据集中的其他变量推断出来的。这些潜变量被称为因子。
降维消除数据中的噪音--通过只保留最重要的特征并去除冗余特征,降维消除了数据中的噪音。这将提高模型的准确性。
降维可用于图像压缩--图像压缩是一种在尽可能保持图像质量的前提下,将图像的字节大小减至最小的技术。构成图像的像素可视为图像数据的维数(列/变量)。我们进行 PCA 处理,以获得最佳的分量数,从而在图像数据的可解释性和图像质量之间取得平衡。
from sklearn.datasets import load_iris
from sklearn.decomposition import PCA
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
iris = load_iris()
X = iris.data
y = iris.target
from sklearn.preprocessing import StandardScaler
sc = StandardScaler()
X_scaled = sc.fit_transform(X)
pca = PCA(n_components=2)
X_pca = pca.fit_transform(X_scaled)
lda = LinearDiscriminantAnalysis(n_components=2, solver='svd')
X_lda = lda.fit_transform(X, y)
fig, ax = plt.subplots(nrows=1, ncols=2, figsize=(13.5 ,4))
sns.scatterplot(X_pca[:,0], X_pca[:,1], hue=y, palette='Set1', ax=ax[0])
sns.scatterplot(X_lda[:,0], X_lda[:,1], hue=y, palette='Set1', ax=ax[1])
ax[0].set_title("PCA of IRIS dataset", fontsize=15, pad=15)
ax[1].set_title("LDA of IRIS dataset", fontsize=15, pad=15)
ax[0].set_xlabel("PC1", fontsize=12)
ax[0].set_ylabel("PC2", fontsize=12)
ax[1].set_xlabel("LD1", fontsize=12)
ax[1].set_ylabel("LD2", fontsize=12)
plt.savefig('PCA vs LDA.png', dpi=80)
from sklearn.datasets import load_iris
from sklearn.decomposition import PCA
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import TruncatedSVD
iris = load_iris()
X = iris.data
y = iris.target
sc = StandardScaler()
X_scaled = sc.fit_transform(X)
pca = PCA(n_components=2)
X_pca = pca.fit_transform(X_scaled)
svd = TruncatedSVD(n_components=2, algorithm='randomized',
random_state=0)
X_svd = svd.fit_transform(X_scaled)
fig, ax = plt.subplots(nrows=1, ncols=2, figsize=(13.5 ,4))
sns.scatterplot(X_pca[:,0], X_pca[:,1], hue=y, palette='Set1', ax=ax[0])
sns.scatterplot(X_svd[:,0], X_svd[:,1], hue=y, palette='Set1', ax=ax[1])
ax[0].set_title("PCA of IRIS dataset", fontsize=15, pad=15)
ax[1].set_title("Truncated SVD of IRIS dataset", fontsize=15, pad=15)
ax[0].set_xlabel("PC1", fontsize=12)
ax[0].set_ylabel("PC2", fontsize=12)
ax[1].set_xlabel("SVD1", fontsize=12)
ax[1].set_ylabel("SVD2", fontsize=12)
plt.savefig('PCA vs SVD.png', dpi=100)
import seaborn as sns
import matplotlib.pyplot as plt
from sklearn.datasets import make_moons
sns.set_style('darkgrid')
X, y = make_moons(n_samples = 500, random_state=42)
sns.scatterplot(X[:, 0], X[:, 1], hue=y, palette='Set1')
plt.savefig('Non-linear data.png')
from sklearn.decomposition import PCA
from sklearn.decomposition import KernelPCA
pca = PCA(n_components=2)
X_pca = pca.fit_transform(X)
kpca = KernelPCA(n_components=2, kernel='rbf',
gamma=15, random_state=42)
X_kpca = kpca.fit_transform(X)
fig, ax = plt.subplots(nrows=1, ncols=2, figsize=(13.5 ,4))
sns.scatterplot(X_pca[:, 0], X_pca[:, 1], hue=y, palette='Set1', ax=ax[0])
sns.scatterplot(X_kpca[:, 0], X_kpca[:, 1], hue=y, palette='Set1', ax=ax[1])
ax[0].set_title("PCA", fontsize=15, pad=15)
ax[1].set_title("RBF Kernel PCA", fontsize=15, pad=15)
ax[0].set_xlabel("Component 1", fontsize=12)
ax[0].set_ylabel("Component 2", fontsize=12)
ax[1].set_xlabel("Component 1", fontsize=12)
ax[1].set_ylabel("Component 2", fontsize=12)
plt.savefig('PCA vs Kernel PCA.png', dpi=100)
对比结果如下:
从上图可以看出,普通 PCA 无法将非线性数据转化为线性数据。在对相同数据应用核 PCA 后,两类数据在线性上得到了很好的分离(现在,可以通过画一条垂直直线来划分类别)。
那么,内核 PCA 是否真的降低了数据的维度呢?答案是 "是的",因为 RBF 核函数暂时将二维数据投影到一个新的高维特征空间,在这个空间中,类别变得线性可分,然后算法将高维数据投影回二维数据,并绘制成二维图。在类别可线性分离的同时,降维过程在幕后进行。
from sklearn.decomposition import PCA
from sklearn.manifold import TSNE
from sklearn.preprocessing import StandardScaler
sc = StandardScaler()
X_scaled = sc.fit_transform(X)
pca = PCA()
X_pca = pca.fit_transform(X_scaled)
tsne = TSNE()
X_tsne = tsne.fit_transform(X_pca)
现在,我们将 t-SNE 应用于虹膜数据集。它只有 4 个特征。因此,我们不需要在 t-SNE 之前运行 PCA。
from sklearn.datasets import load_iris
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.manifold import TSNE
from sklearn.preprocessing import StandardScaler
sns.set_style('darkgrid')
iris = load_iris()
X = iris.data
y = iris.target
sc = StandardScaler()
X_scaled = sc.fit_transform(X)
tsne = TSNE(n_components=2, random_state=1)
X_tsne = tsne.fit_transform(X_scaled)
sns.scatterplot(X_tsne[:,0], X_tsne[:,1], hue=y, palette='Set1')
plt.title("t-SNE of IRIS dataset", fontsize=15, pad=15)
plt.savefig('t-SNE.png')
运行结果如下:
from sklearn.datasets import load_iris
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.manifold import MDS
sns.set_style('darkgrid')
iris = load_iris()
X = iris.data
y = iris.target
mds = MDS(n_components=2, metric=True, random_state=2)
X_mds = mds.fit_transform(X)
sns.scatterplot(X_mds[:,0], X_mds[:,1], hue=y, palette='Set1')
plt.title("MDS of IRIS dataset", fontsize=15, pad=15)
plt.savefig('MDS.png')
from sklearn.datasets import load_iris
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.manifold import Isomap
sns.set_style('darkgrid')
iris = load_iris()
X = iris.data
y = iris.target
isomap = Isomap(n_neighbors=5, n_components=2,
eigen_solver='auto')
X_isomap = isomap.fit_transform(X)
sns.scatterplot(X_isomap[:,0], X_isomap[:,1], hue=y, palette='Set1')
plt.title("Isomap of IRIS dataset", fontsize=15, pad=15)
plt.savefig('Isomap.png')
view raw
import pandas as pd
from sklearn.datasets import load_iris
from sklearn.feature_selection import RFE
from sklearn.linear_model import LogisticRegression
from yellowbrick.model_selection import feature_importances
iris = load_iris()
X = iris.data
y = iris.target
estimator = LogisticRegression(max_iter=150)
selector = RFE(estimator, n_features_to_select=3, step=1)
selector.fit(X, y)
X_selected = selector.transform(X)
print('Data with initial features')
print(pd.DataFrame(X, columns=iris.feature_names).head())
print()
print('Data with selected features')
print(pd.DataFrame(X_selected).head())
print()
print(feature_importances(estimator, X, y, stack=True,
labels=iris.feature_names, relative=False))
import pandas as pd
from sklearn.datasets import load_iris
from sklearn.feature_selection import f_classif
from sklearn.feature_selection import SelectKBest
iris = load_iris()
X = iris.data
y = iris.target
X_selected = SelectKBest(f_classif, k=3).fit_transform(X, y)
# Let's see F-vlues for each feature
print('F-values: ', f_classif(X,y)[0])
print()
print('Data with initial features')
print(pd.DataFrame(X, columns=iris.feature_names).head())
print()
print('Data with selected features')
print(pd.DataFrame(X_selected).head())
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris
from sklearn.ensemble import RandomForestClassifier
iris = load_iris()
X = iris.data
y = iris.target
rf = RandomForestClassifier(n_estimators=100, max_depth=3,
bootstrap=True, n_jobs=-1,
random_state=0)
rf.fit(X, y)
feature_imp = pd.Series(rf.feature_importances_,
index=iris.feature_names).sort_values(ascending=False)
print('Feature importances: ', rf.feature_importances_)
print(sns.barplot(x=feature_imp, y=feature_imp.index))
plt.xlabel('Feature Importance Score', fontsize=12)
plt.ylabel('Features', fontsize=12)
plt.title("Visualizing Important Features", fontsize=15, pad=15)
from sklearn.feature_selection import SelectFromModel
selector = SelectFromModel(rf, threshold=0.05)
features_important = selector.fit_transform(X, y)
print('Data with initial features')
print(pd.DataFrame(X, columns=iris.feature_names).head())
print()
print('Data with selected features')
print(pd.DataFrame(features_important).head())
rf = RandomForestClassifier(n_estimators=100, max_depth=3,
bootstrap=True, n_jobs=-1,
0) =
rf.fit(features_important, y)
© THE END
转载请联系本公众号获得授权