独立成分分析(ICA)是一种用于从混合信号中恢复独立源的统计技术。想象一下,有三个乐器同时演奏,而三个麦克风记录下了混合的信号。ICA的目标是恢复这些源,即每个乐器各自演奏的内容。重要的是,主成分分析(PCA)在恢复这些乐器的信号时会失败,因为这些信号反映了非高斯过程。
在下面的Python代码中,首先生成了三个不同信号的样本数据。这些信号包括正弦波、方波和锯齿波,然后将它们混合并添加噪声。接着,对数据进行了标准化处理。
import numpy as np
from scipy import signal
np.random.seed(0)
n_samples = 2000
time = np.linspace(0, 8, n_samples)
s1 = np.sin(2 * time) # 信号1:正弦波信号
s2 = np.sign(np.sin(3 * time)) # 信号2:方波信号
s3 = signal.sawtooth(2 * np.pi * time) # 信号3:锯齿波信号
S = np.c_[s1, s2, s3]
S += 0.2 * np.random.normal(size=S.shape) # 添加噪声
S /= S.std(axis=0) # 标准化数据
# 混合数据
A = np.array([[1, 1, 1], [0.5, 2, 1.0], [1.5, 1.0, 2.0]]) # 混合矩阵
X = np.dot(S, A.T) # 生成观测数据
接下来,使用ICA和PCA模型来拟合这些数据,并尝试恢复原始信号。ICA模型能够很好地恢复原始信号,而PCA模型则不能,因为PCA假设数据是高斯分布的,而ICA则不需要这样的假设。
from sklearn.decomposition import PCA, FastICA
# 计算ICA
ica = FastICA(n_components=3, whiten="arbitrary-variance")
S_ = ica.fit_transform(X) # 恢复信号
A_ = ica.mixing_ # 获取估计的混合矩阵
# 可以通过反转混合过程来“证明”ICA模型的应用。
assert np.allclose(X, np.dot(S_, A_.T) + ica.mean_)
# 为了比较,计算PCA
pca = PCA(n_components=3)
H = pca.fit_transform(X) # 基于正交成分重建信号
最后,绘制了混合信号、真实源信号、ICA恢复的信号和PCA恢复的信号的图表,以直观地比较ICA和PCA的效果。
import matplotlib.pyplot as plt
plt.figure()
models = [X, S, S_, H]
names = ["观测(混合信号)", "真实源", "ICA恢复信号", "PCA恢复信号"]
colors = ["red", "steelblue", "orange"]
for ii, (model, name) in enumerate(zip(models, names), 1):
plt.subplot(4, 1, ii)
plt.title(name)
for sig, color in zip(model.T, colors):
plt.plot(sig, color=color)
plt.tight_layout()
plt.show()