Python机器学习笔记(十一、特征提取)

embedded/2024/12/27 17:18:36/

特征提取

PCA 的另一个应用是特征提取特征提取背后的思想是,可以找到一种数据表示,比给定的原始表示更适合于分析。特征提取很有用,它的一个很好的应用实例就是图像。图像由像素组成,通常存储为红绿蓝(RGB)强度。图像中的对象通常由上千个像素组成,它们只有放在一起才有意义。

现在学习使用 PCA 对图像做特征提取的一个简单示例,处理 Wild 数据集 Labeled Faces (标记人脸)中的人脸图像。这一数据集包含从互联网下载的名人脸部图像,它包含从 21 世纪初开始的政治家、歌手、演员和运动员的人脸图像。(终于将Wild 数据集 Labeled Faces (标记人脸)手动处理好了),我们使用这些图像的灰度版本,并将它们按比例缩小以加快处理速度:

python">
import matplotlib.pyplot as plt
from sklearn.datasets import fetch_lfw_peoplepeople = fetch_lfw_people(min_faces_per_person=20, resize=0.7)
print("people.images.shape: {}".format(people.images.shape))
print("Number of classes: {}".format(len(people.target_names)))
image_shape = people.images[0].shape
fix, axes = plt.subplots(2, 5, figsize=(15, 8), subplot_kw={'xticks': (), 'yticks': ()})
for target, image, ax in zip(people.target, people.images, axes.ravel()):ax.imshow(image)ax.set_title(people.target_names[target])
plt.show()

通过以上代码加载数据集会很慢,报403错误。为了避免网络问题,所以手动下载lfw-funneled.tgz压缩包(通过 http://vis-www.cs.umass.edu/lfw/lfw-funneled.tgz 地址),下载完成后,将压缩包移动到以下目录:C:\Users\leo\scikit_learn_data\lfw_home,其中leo是我的用户名。运行上面代码,会解压lfw-funneled.tgz该压缩包,并输出结果如下:

people.images.shape: (3023, 87, 65)
Number of classes: 62

上图是来自 Wild 数据集中 Labeled Faces 的一些图像,一共有 3023 张图像,每张大小为 87 像素 ×65 像素,分别属于 62 个不同的人。这个数据集有些偏斜,其中包含 George W. Bush(小布什)和 Colin Powell(科林 • 鲍威 尔)的大量图像,我们用下面代码何输出来观察下:

python">import numpy as np
from sklearn.datasets import fetch_lfw_peoplepeople = fetch_lfw_people(min_faces_per_person=20, resize=0.7)# 计算每个目标出现的次数
counts = np.bincount(people.target)
# 将次数与目标名称一起打印出来
for i, (count, name) in enumerate(zip(counts, people.target_names)):print("{0:25} {1:3}".format(name, count), end=' ')if (i + 1) % 3 == 0:print()

输出结果:

为了降低数据偏斜,我们对每个人最多只取 50 张图像(降低 George W. Bush 对特征提取的影响)。

人脸识别的一个常见任务就是看某个前所未见的人脸是否属于数据库中的某个已知人物。 这在照片收集、社交媒体和安全应用中都有应用。解决这个问题的方法之一就是构建一个分类器,每个人都是一个单独的类别。但人脸数据库中通常有许多不同的人,而同一个人的图像很少(也就是说,每个类别的训练样例很少)。这使得大多数分类器的训练都很困难。另外,通常我们还需要能够轻松添加新的人物,不需要重新训练一个大型模型。一种简单的解决方法是使用单一最近邻分类器,寻找与要分类的人脸最为相似的人脸。这个分类器原则上可以处理每个类别只有一个训练样例的情况。下面看一下 KNeighborsClassifier 的表现如何:

python">import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.datasets import fetch_lfw_people
from sklearn.neighbors import KNeighborsClassifierpeople = fetch_lfw_people(min_faces_per_person=20, resize=0.7)mask = np.zeros(people.target.shape, dtype=np.bool_)
for target in np.unique(people.target):mask[np.where(people.target == target)[0][:50]] = 1
X_people = people.data[mask]
y_people = people.target[mask]
# 将灰度值缩放到0到1之间,而不是在0到255之间
# 以得到更好的数据稳定性
X_people = X_people / 255.from sklearn.neighbors import KNeighborsClassifier
# 将数据分为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X_people, y_people, stratify=y_people, random_state=0)
# 使用一个邻居构建KNeighborsClassifier
knn = KNeighborsClassifier(n_neighbors=1)
knn.fit(X_train, y_train)
print("Test set score of 1-nn: {:.2f}".format(knn.score(X_test, y_test)))

输出结果:Test set score of 1-nn: 0.22

我们得到的精度大约为 22%。对于包含 62 个类别的分类问题来说,这实际上不算太差(随机猜测的精度约为 1/62=1.5%),但也不算好。我们每识别五次仅正确识别了一个人。

这里可以用到 PCA。想要度量人脸的相似度,计算原始像素空间中的距离是一种相当糟糕的方法。用像素表示来比较两张图像时,我们比较的是每个像素的灰度值与另一张图像对应位置的像素灰度值。这种表示与人们对人脸图像的解释方式有很大不同,使用这种原始表示很难获取到面部特征。例如,如果使用像素距离,那么将人脸向右移动一个像素将会发生巨大的变化,得到一个完全不同的表示。我们希望,使用沿着主成分方向的距离可以提高精度。这里我们启用 PCA 的白化(whitening)选项,它将主成分缩放到相同的尺度。变换后的结果与使用 StandardScaler 相同。再次使用上一次学习中的数据,白化不仅对应于旋转数据,还对应于缩放数据使其形状是圆形而不是椭圆:

python">import matplotlib.pyplot as plt
import mglearnmglearn.plots.plot_pca_whitening()
plt.show()

 输出图形:

上图是启用白化的 PCA 进行数据变换。我们对训练数据拟合 PCA 对象,并提取前 100 个主成分。然后对训练数据和测试数据进行变换:

python">import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.decomposition import PCA
from sklearn.datasets import fetch_lfw_peoplepeople = fetch_lfw_people(min_faces_per_person=20, resize=0.7)mask = np.zeros(people.target.shape, dtype=np.bool_)
for target in np.unique(people.target):mask[np.where(people.target == target)[0][:50]] = 1
X_people = people.data[mask]
y_people = people.target[mask]
# 将灰度值缩放到0到1之间,而不是在0到255之间
# 以得到更好的数据稳定性
X_people = X_people / 255.from sklearn.neighbors import KNeighborsClassifier
# 将数据分为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X_people, y_people, stratify=y_people, random_state=0)pca = PCA(n_components=100, whiten=True, random_state=0).fit(X_train)
X_train_pca = pca.transform(X_train)
X_test_pca = pca.transform(X_test)
print("X_train_pca.shape: {}".format(X_train_pca.shape))

输出结果:X_train_pca.shape: (1547, 100)

新数据有 100 个特征,即前 100 个主成分。现在,可以对新表示使用单一最近邻分类器来将我们的图像分类:

python">import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.decomposition import PCA
from sklearn.datasets import fetch_lfw_people
from sklearn.neighbors import KNeighborsClassifierpeople = fetch_lfw_people(min_faces_per_person=20, resize=0.7)mask = np.zeros(people.target.shape, dtype=np.bool_)
for target in np.unique(people.target):mask[np.where(people.target == target)[0][:50]] = 1
X_people = people.data[mask]
y_people = people.target[mask]
# 将灰度值缩放到0到1之间,而不是在0到255之间
# 以得到更好的数据稳定性
X_people = X_people / 255.# 将数据分为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X_people, y_people, stratify=y_people, random_state=0)pca = PCA(n_components=100, whiten=True, random_state=0).fit(X_train)
X_train_pca = pca.transform(X_train)
X_test_pca = pca.transform(X_test)
print("X_train_pca.shape: {}".format(X_train_pca.shape))knn = KNeighborsClassifier(n_neighbors=1)
knn.fit(X_train_pca, y_train)
print("Test set accuracy: {:.2f}".format(knn.score(X_test_pca, y_test)))

输出结果:Test set accuracy: 0.30

我们的精度有了一定的提高,从 22% 提升到 30%,这证实了我们的直觉,即主成分可能提供了一种更好的数据表示。

对于图像数据,还可以很容易地将找到的主成分可视化。请记住,成分对应于输入空间里的方向。这里的输入空间是 87 像素 ×65 像素的灰度图像,所以在这个空间中的方向也是 87 像素 ×65 像素的灰度图像。 我们来看一下前几个主成分:

python">import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.decomposition import PCA
from sklearn.datasets import fetch_lfw_people
from sklearn.neighbors import KNeighborsClassifierpeople = fetch_lfw_people(min_faces_per_person=20, resize=0.7)
image_shape = people.images[0].shape
mask = np.zeros(people.target.shape, dtype=np.bool_)
for target in np.unique(people.target):mask[np.where(people.target == target)[0][:50]] = 1
X_people = people.data[mask]
y_people = people.target[mask]
# 将灰度值缩放到0到1之间,而不是在0到255之间
# 以得到更好的数据稳定性
X_people = X_people / 255.# 将数据分为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X_people, y_people, stratify=y_people, random_state=0)pca = PCA(n_components=100, whiten=True, random_state=0).fit(X_train)
X_train_pca = pca.transform(X_train)
X_test_pca = pca.transform(X_test)
#print("X_train_pca.shape: {}".format(X_train_pca.shape))knn = KNeighborsClassifier(n_neighbors=1)
knn.fit(X_train_pca, y_train)
#print("Test set accuracy: {:.2f}".format(knn.score(X_test_pca, y_test)))print("pca.components_.shape: {}".format(pca.components_.shape))
fix, axes = plt.subplots(3, 5, figsize=(15, 12), subplot_kw={'xticks': (), 'yticks': ()})
for i, (component, ax) in enumerate(zip(pca.components_, axes.ravel())):ax.imshow(component.reshape(image_shape), cmap='viridis')ax.set_title("{}. component".format((i + 1)))
plt.show()

输出结果:

输出的图像:人脸数据集前 15 个主成分的成分向量

虽然我们肯定无法理解这些成分的所有内容,但可以猜测一些主成分捕捉到了人脸图像的哪些方面。第一个主成分似乎主要编码的是人脸与背景的对比,第二个主成分编码的是人脸左半部分和右半部分的明暗程度差异,如此等等。虽然这种表示比原始像素值的语义稍强,但它仍与人们感知人脸的方式相去甚远。由于 PCA 模型是基于像素的,因此人脸的相对位置(眼睛、下巴和鼻子的位置)和明暗程度都对两张图像在像素表示中的相似程度有很大影响。但人脸的相对位置和明暗程度可能并不是人们首先感知的内容。在要求人们评价人脸的相似度时,他们更可能会使用年龄、性别、面部表情和发型等属性,而这些属性很难从像素强度中推断出来。重要的是要记住,算法对数据(特别是视觉数据,比如人们非常熟悉的图像)的解释通常与人类的解释方式大不相同。

不过让我们回到 PCA 的具体案例。我们对 PCA 变换的介绍是:先旋转数据,然后删除方差较小的成分。另一种有用的解释是尝试找到一些数字(PCA 旋转后的新特征值),使我们可以将测试点表示为主成分的加权求和:

这里 x0、x1 等是这个数据点的主成分的系数,换句话说,它们是图像在旋转后的空间中的表示。

还可以用另一种方法来理解 PCA 模型,就是仅使用一些成分对原始数据进行重建。 在上一次的学习中用到的数据,在去掉第二个成分并来到第三张图之后,我们反向旋转并重新加上平均值, 这样就在原始空间中获得去掉第二个成分的新数据点,正如最后一张图所示。我们可以对人脸做类似的变换,将数据降维到只包含一些主成分,然后反向旋转回到原始空间。回到原始特征空间可以通过 inverse_transform 方法来实现。这里我们分别利用 10 个、50 个、 100 个和 500 个成分对一些人脸进行重建并将其可视化:

python">import numpy as np
import matplotlib.pyplot as plt
import mglearn
from sklearn.model_selection import train_test_split
from sklearn.datasets import fetch_lfw_peoplepeople = fetch_lfw_people(min_faces_per_person=20, resize=0.7)
image_shape = people.images[0].shape
mask = np.zeros(people.target.shape, dtype=np.bool_)
for target in np.unique(people.target):mask[np.where(people.target == target)[0][:50]] = 1
X_people = people.data[mask]
y_people = people.target[mask]
# 将灰度值缩放到0到1之间,而不是在0到255之间
# 以得到更好的数据稳定性
X_people = X_people / 255.# 将数据分为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X_people, y_people, stratify=y_people, random_state=0)mglearn.plots.plot_pca_faces(X_train, X_test, image_shape)
plt.show()

输出结果:

可以看到,这里失败了!按照理论来讲:在仅使用前 10 个主成分时,会仅捕捉到图片的基本特点,比如人脸方向和明暗程度。随着使用的主成分越来越多,图像中也会保留越来越多的细节。这对应于上图的求和中包含越来越多的项。如果使用的成分个数与像素个数相等,意味着我们在旋转后不会丢弃任何信息,可以完美重建图像。 

下面尝试使用 PCA 的前两个主成分,将数据集中的所有人脸在散点图中可视化,其类别在图中给出。如下:

python">import numpy as np
import matplotlib.pyplot as plt
import mglearn
from sklearn.model_selection import train_test_splitfrom sklearn.decomposition import PCA
from sklearn.datasets import fetch_lfw_peoplepeople = fetch_lfw_people(min_faces_per_person=20, resize=0.7)
image_shape = people.images[0].shape
mask = np.zeros(people.target.shape, dtype=np.bool_)
for target in np.unique(people.target):mask[np.where(people.target == target)[0][:50]] = 1
X_people = people.data[mask]
y_people = people.target[mask]
# 将灰度值缩放到0到1之间,而不是在0到255之间
# 以得到更好的数据稳定性
X_people = X_people / 255.# 将数据分为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X_people, y_people, stratify=y_people, random_state=0)pca = PCA(n_components=100, whiten=True, random_state=0).fit(X_train)
X_train_pca = pca.transform(X_train)
X_test_pca = pca.transform(X_test)mglearn.discrete_scatter(X_train_pca[:, 0], X_train_pca[:, 1], y_train)
plt.xlabel("First principal component")
plt.ylabel("Second principal component")
plt.show()

输出结果:

上图输出的是:利用前两个主成分绘制人脸数据集的散点图。如果我们只使用前两个主成分,整个数据只是一大团,看不到类别之间的分界。这并不意外,因为即使有 10 个成分,PCA 也仅捕捉到人脸非常粗略的特征。

非负矩阵分解

非负矩阵分解(non-negative matrix factorization,NMF)是另一种无监督学习算法,其目的在于提取有用的特征。它的工作原理类似于 PCA,也可以用于降维。与 PCA 相同,我们试图将每个数据点写成一些分量的加权求和。但在 PCA 中,我们想要的是正交分量,并且能够解释尽可能多的数据方差;而在 NMF 中,我们希望分量和系数均为非负,也就是说,我们希望分量和系数都大于或等于0。因此,这种方法只能应用于每个特征都是非负的数据,因为非负分量的非负求和不可能变为负值。

将数据分解成非负加权求和的这个过程,对由多个独立源相加(或叠加)创建而成的数据特别有用,比如多人说话的音轨或包含多种乐器的音乐。在这种情况下,NMF 可以识别出组成合成数据的原始分量。总之,与 PCA 相比,NMF 得到的分量更容易解释,因为负的分量和系数可能会导致难以解释的抵消效应(cancellation effect)。举例,上图的特征脸图中同时包含正数和负数,我们在 PCA 的说明中也提到过,正负号实际上是任意的。在将 NMF 应用于人脸数据集之前,我们先来简要回顾一下模拟数据。

NMF 应用于模拟数据

与使用 PCA 不同,我们需要保证数据是正的,NMF能够对数据进行操作。这说明数据相对于原点 (0, 0) 的位置实际上对NMF很重要。因此,可以将提取出来的非负分量看作是从 (0, 0) 到数据的方向。 下面的例子给出了NMF在二维玩具数据上的结果:

python">import matplotlib.pyplot as plt
import mglearnmglearn.plots.plot_nmf_illustration()
plt.show()

输出结果:

上图是:两个分量的非负矩阵分解(左)和一个分量的非负矩阵分解(右)找到的分量。

对于两个分量的NMF(如上左图所示),显然所有数据点都可以写成这两个分量的正数组合。如果有足够多的分量能够完美地重建数据(分量个数与特征个数相同),那么算法会选择指向数据极值的方向。

如果我们仅使用一个分量,那么NMF会创建一个指向平均值的分量,因为指向这里可以对数据做出最好的解释。可以看到,与 PCA 不同,减少分量个数不仅会删除一些方向,而且会创建一组完全不同的分量。NMF的分量也没有按任何特定方法排序,所以不存在 “第一非负分量”:所有分量的地位平等。

NMF使用了随机初始化,根据随机种子的不同可能会产生不同的结果。在相对简单的情况下(比如两个分量的模拟数据),所有数据都可以被完美地解释,那么随机性的影响很小(虽然可能会影响分量的顺序或尺度)。在更加复杂的情况下,影响可能会很大。

NMF 应用于人脸图像

现在我们将NMF应用于之前用过的 Wild 数据集中的 Labeled Faces。NMF的主要参数是我们想要提取的分量个数。通常来说,这个数字要小于输入特征的个数(否则,将每个像素作为单独的分量就可以对数据进行解释)。 首先,我们来观察分量个数如何影响NMF重建数据的好坏:

python">import numpy as np
import matplotlib.pyplot as plt
import mglearn
from sklearn.model_selection import train_test_split
from sklearn.datasets import fetch_lfw_peoplepeople = fetch_lfw_people(min_faces_per_person=20, resize=0.7)
image_shape = people.images[0].shape
mask = np.zeros(people.target.shape, dtype=np.bool_)
for target in np.unique(people.target):mask[np.where(people.target == target)[0][:50]] = 1
X_people = people.data[mask]
y_people = people.target[mask]
# 将灰度值缩放到0到1之间,而不是在0到255之间
# 以得到更好的数据稳定性
X_people = X_people / 255.# 将数据分为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X_people, y_people, stratify=y_people, random_state=0)mglearn.plots.plot_nmf_faces(X_train, X_test, image_shape)
plt.show()

输出的结果:

失败!反向变换的数据质量与使用 PCA 时类似,似乎更差一些。这符合预期,因为PCA找到的是重建的最佳方向。NMF通常并不用于对数据进行重建或编码,而是用于在数据中寻找有趣的模式。

尝试仅提取一部分分量(比如 15 个),初步观察一下数据:

python">import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.datasets import fetch_lfw_people
from sklearn.decomposition import NMFpeople = fetch_lfw_people(min_faces_per_person=20, resize=0.7)
image_shape = people.images[0].shape
mask = np.zeros(people.target.shape, dtype=np.bool_)
for target in np.unique(people.target):mask[np.where(people.target == target)[0][:50]] = 1
X_people = people.data[mask]
y_people = people.target[mask]
# 将灰度值缩放到0到1之间,而不是在0到255之间
# 以得到更好的数据稳定性
X_people = X_people / 255.# 将数据分为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X_people, y_people, stratify=y_people, random_state=0)nmf = NMF(n_components=15, random_state=0)
nmf.fit(X_train)
X_train_nmf = nmf.transform(X_train)
X_test_nmf = nmf.transform(X_test)
fix, axes = plt.subplots(3, 5, figsize=(15, 12), subplot_kw={'xticks': (), 'yticks': ()})
for i, (component, ax) in enumerate(zip(nmf.components_, axes.ravel())):ax.imshow(component.reshape(image_shape))ax.set_title("{}. component".format(i))
plt.show()

输出结果:

上图是:使用15个分量的NMF在人脸数据集上找到的分量。这些分量都是正的,因此比PCA 分量更像人脸原型。例如,可以清楚地看到,分量 3(component 3)显示了稍微向右转动的人脸,而分量 7(component 7)则显示了稍微向左转动的人脸。我们来看一下这两个分量特别大的那些图像,如下所示:

python">import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.datasets import fetch_lfw_people
from sklearn.decomposition import NMFpeople = fetch_lfw_people(min_faces_per_person=20, resize=0.7)
image_shape = people.images[0].shape
mask = np.zeros(people.target.shape, dtype=np.bool_)
for target in np.unique(people.target):mask[np.where(people.target == target)[0][:50]] = 1
X_people = people.data[mask]
y_people = people.target[mask]
# 将灰度值缩放到0到1之间,而不是在0到255之间
# 以得到更好的数据稳定性
X_people = X_people / 255.# 将数据分为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X_people, y_people, stratify=y_people, random_state=0)nmf = NMF(n_components=15, random_state=0)
nmf.fit(X_train)
X_train_nmf = nmf.transform(X_train)
X_test_nmf = nmf.transform(X_test)compn = 3
# 按第3个分量排序,绘制前10张图像
inds = np.argsort(X_train_nmf[:, compn])[::-1]
fig, axes = plt.subplots(2, 5, figsize=(15, 8), subplot_kw={'xticks': (), 'yticks': ()})
for i, (ind, ax) in enumerate(zip(inds, axes.ravel())):ax.imshow(X_train[ind].reshape(image_shape))
plt.show()

输出图形分量3系数较大的人脸:

 

python">import numpy as np
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.datasets import fetch_lfw_people
from sklearn.decomposition import NMFpeople = fetch_lfw_people(min_faces_per_person=20, resize=0.7)
image_shape = people.images[0].shape
mask = np.zeros(people.target.shape, dtype=np.bool_)
for target in np.unique(people.target):mask[np.where(people.target == target)[0][:50]] = 1
X_people = people.data[mask]
y_people = people.target[mask]
# 将灰度值缩放到0到1之间,而不是在0到255之间
# 以得到更好的数据稳定性
X_people = X_people / 255.# 将数据分为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X_people, y_people, stratify=y_people, random_state=0)nmf = NMF(n_components=15, random_state=0)
nmf.fit(X_train)
X_train_nmf = nmf.transform(X_train)
X_test_nmf = nmf.transform(X_test)compn = 7
# 按第7个分量排序,绘制前10张图像
inds = np.argsort(X_train_nmf[:, compn])[::-1]
fig, axes = plt.subplots(2, 5, figsize=(15, 8), subplot_kw={'xticks': (), 'yticks': ()})
for i, (ind, ax) in enumerate(zip(inds, axes.ravel())):ax.imshow(X_train[ind].reshape(image_shape))
plt.show()

 输出图形分量 7 系数较大的人脸:

如图所示,分量 3 系数较大的人脸都是向右看的人脸,而分量 7 系数较大的人脸都向左看。提取这样的模式最适合于具有叠加结构的数据,包括音频、基因表达和文本数据。我们通过一个模拟数据的例子来看一下这种用法。 假设我们对一个信号感兴趣,它是三个不同信号源合成的:

python">import matplotlib.pyplot as plt
import mglearnS = mglearn.datasets.make_signals()
plt.figure(figsize=(6, 1))
plt.plot(S, '-')
plt.xlabel("Time")
plt.ylabel("Signal")
plt.show()

输出图形:

上图是:原始信号源

但是我们无法观测到原始信号,只能观测到三个信号的叠加混合。我们想要将混合信号分解为原始分量。假设我们有许多种不同的方法来观测混合信号(比如有100台测量 装置),每种方法都为我们提供了一系列测量结果。

python">import numpy as np
import matplotlib.pyplot as plt
import mglearn
from sklearn.decomposition import NMF
from sklearn.decomposition import PCAS = mglearn.datasets.make_signals()
#plt.figure(figsize=(6, 1))
#plt.plot(S, '-')
#plt.xlabel("Time")
#plt.ylabel("Signal")
#plt.show()# 将数据混合成100维的状态
A = np.random.RandomState(0).uniform(size=(100, 3))
X = np.dot(S, A.T)
print("Shape of measurements: {}".format(X.shape))# 用 NMF 来还原这三个信号
nmf = NMF(n_components=3, random_state=42)
S_ = nmf.fit_transform(X)
print("Recovered signal shape: {}".format(S_.shape))# 同时用 PCA 来还原这三个信号,以做比较:
pca = PCA(n_components=3)
H = pca.fit_transform(X)models = [X, S, S_, H]
names = ['Observations (first three measurements)','True sources','NMF recovered signals','PCA recovered signals']
fig, axes = plt.subplots(4, figsize=(8, 4), gridspec_kw={'hspace': .5}, subplot_kw={'xticks': (), 'yticks': ()})
for model, name, ax in zip(models, names, axes):ax.set_title(name)ax.plot(model[:, :3], '-')
plt.show()

输出结果:

Shape of measurements: (2000, 100)
Recovered signal shape: (2000, 3)

上图是:利用NMFPCA还原混合信号源

图中包含来自 X 的 100 次测量中的 3 次,用于参考。可以看到,NMF 在发现原始信号源时得到了不错的结果,而 PCA 则失败了,仅使用第一个成分来解释数据中的大部分变化。 要记住,NMF 生成的分量是没有顺序的。在这个例子中,NMF分量的顺序与原始信号完全相同(参见三条曲线的颜色),但这纯属偶然。 还有许多其他算法可用于将每个数据点分解为一系列固定分量的加权求和,如 PCANMF 所做的那样。如果对这种类型的模式提取感兴趣,可以学习 scikit-learn 用户指南中关于独立成分分析(ICA)、因子分析(FA)和稀疏编码(字典学习)等内容(http://scikit-learn.org/stable/ modules/decomposition.html)。

 

 


http://www.ppmy.cn/embedded/149222.html

相关文章

蓝桥杯真题 - 与或异或 - 题解

题目链接:https://www.lanqiao.cn/problems/3552/learning/ 个人评价:难度 2 星(满星:5) 前置知识:位运算,递归 整体思路 行列下标按照从 0 0 0 开始,第 0 0 0 行数字是固定的&a…

关于FPGA的IO三引脚形式

1. 为什么需要IO的三引脚模式呢? 1. 问题起因 在做正点原子VDMA LCD实验的时候,LCD 屏的数据引脚是双向的引脚,由于在封装 IP 核的时候不能直接定义成 inout 信号(软件最终会综合成输出的引脚),因此这里需要将 LCD 的数据引脚定义成三个引脚…

C语言项目 天天酷跑(上篇)

前言 这里讲述这个天天酷跑是怎么实现的,我会在天天酷跑的下篇添加源代码,这里会讲述天天酷跑这个项目是如何实现的每一个思路,都是作者自己学习于别人的代码而创作的项目和思路,这个代码和网上有些许不一样,因为掺杂了…

前端工程化的理解

‌前端工程化是指将软件工程的方法和实践应用于前端开发的过程,以提高开发效率、保证项目质量、优化资源管理和促进协作‌。前端工程化的核心概念包括模块化、自动化构建、代码质量控制、持续集成/持续部署(CI/CD)等。 核心概念 ‌模块化‌…

【Apache Paimon】-- 11 -- Flink 消费 kakfa 写 S3 File

目录 1、项目构建 2、项目新增和修改 2.1 pom.xml 新增依赖 2.2 本地测试或者 flink on k8s 时,新增 S3FileSystemFactory.java 第一步:创建包=org.apache.flink.fs.s3hadoop 第二步:新增 java 类 S3FileSystemFactory 特别注意 (1)本地测试时需要新增以下内容 (…

NVIDIA GB200 Superchip及各厂家液冷服务器和液冷机柜介绍

(一)前言 NVIDIA GB200是一款高度集成的超级计算模块,它是基于NVIDIA的Blackwell架构设计的。这款模块结合了两个NVIDIA B200 Tensor Core GPU和一个NVIDIA Grace CPU,旨在提供前所未有的AI性能。 GB200 搭载液冷,产…

IntelliJ IDEA Docker集成

一、概述 Docker是一种用于在隔离和可复制环境中部署和运行可执行文件的工具。这可能很有用,例如,在与生产相同的环境中测试代码。 IntelliJ IDEA集成了Docker功能,并为创建Docker映像、运行Docker容器、管理Docker Compose应用程序、使用公…

(笔记)一个有趣的终端屏幕保护程序,显示类似《黑客帝国》中字符雨的效果

mac上安装 brew install cmatrix 运行 cmatrix 效果 地址:GitHub - abishekvashok/cmatrix: Terminal based "The Matrix" like implementation