본문 바로가기

독립성분분석(ICA) 본문

Python/machine learning

독립성분분석(ICA)

Data to Knowledge 2020. 1. 28. 21:41

 

사람들이 붐비는 칵테일 파티장이나 음식점에서 상대방의 말을 제대로 이해하기 힘들다불분명한 신호를 분리하는 비지도학습(unsupervised learning)을 소개하고자 한다비지도 학습은 머신러닝(Machine Learning)의 일종이다 비지도 학습은 입력값에 대한 목표치가 주어지지 않는 대신 주어진 데이터의 주요 특징을 요약하고 설명하는 방식을 말한다.

"머신러닝(Machine Learning)은 컴퓨터에 입력값과 답이 있는 데이터를 이용하여 모델을 학습시킨 다음 답이 없는 데이터(유보표본)를 추가해서 이 모델에 적용해 보고 해(분류, 회귀)를 구하는 방법"

서로 다른 유형의 신호를 암묵적으로 분리할 수 있도록 독립성분분석(ICA, Independent Component Analysis) 알고리즘을 개발한 사람은 앤서니 벨(ANTHONY J. BELL)  테런스 J.  세즈노스키(TERRENCE J. SEJNOWSK)이다

성분 또는 요인을 구분하는 방법은 주성분분석(Principal Component Analysis, PCA) 독립성분석이 있다. 두 방법은 독립 차원 감소(Dimensionality reduction) 가장 방법이다. PCA 일반적인 비지도학습기법으로 개의 신호가 양분되는 방향을 포착해 가장 효과적으로 혼합한다. PCA 양축은 언제나 수직으로 교차한다. 반면에 ICA 경우는 개의 축은 점들이 위치하는 방향과 일치하며 서로 구분하는 신호를 나타낸다.  ICA 이용하면 분류되지 않은 특징들 확률적으로 독립(independent) 성분을 충분히 포함하고 있는 새로운 특징을 추출할 있다. PCA ICA 차이를 그림으로 나타낼 있다.

[그림1] PCA ICA

 

ICA네트워크에는 동일한 수의 인풋 및 아웃풋 유닛과 그 사이를 완전하게 하는 연결하는 가중치의 집합이 존재한다. 암묵신호분리의 문제를 해결하기 위해서는 모든 마이크에 각각 한 개의 유닛이 주어진 상태에서 마이크 소리가 인풋 층을 통과한다. ICA학습 알고리즘은 아웃풋 층에 이르는 가중치를 수렴할 때까지 반복적으로 수정한다. 아웃풋의 독립성을 최대한 확보하기 위해 가중치를 변경하는 과정에서 최초의 음원이 완벽하게 분리되는 것이다. 만약, 독립성이 충분히 확보되지 않았다면(상관관계가 0) 최초 음원은 상관성의 정도가 최대로 낮아지도록 만든다.

앤서니 벨(ANTHONY J. BELL)  테런스 J.  세즈노스키(TERRENCE J. SEJNOWSK) ICA 자연음에 적용될 독립성분이 각기 다른 주파수와 지속 시간을 지닌 시계열 필터 역할을 한다는 사실도 입증하였다. 관련한 논문 2편을 업로드합니다.

 

download.pdf
0.60MB

  

1-s2.0-S0042698997001211-main.pdf
1.32MB

오늘날 ICA 같은 뉴럴 네트워크가 머신러닝의 도구로 이용되고 있고 일상 생활의 도구로 많이 사용되고 있다. 대표적인 것이 휴대폰, 에어 등에 사용된다.

이제 파이썬 Jupyter 이용하여 ICA 실행해 보자

1) 예제1

[1 단계] Jupyter에서 matplotlib를 설치한다.

pip install -U matplotlib

[2단계] 다음과 같은 명령문을 입력한다.

print(__doc__)

import numpy as np

import matplotlib.pyplot as plt

from scipy import signal

from sklearn.decomposition import FastICA, PCA

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

# Generate sample data

np.random.seed(0)

n_samples = 2000

time = np.linspace(0, 8, n_samples)

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.0], [1.5, 1.0, 2.0]])  # Mixing matrix

X = np.dot(S, A.T)  # Generate observations

# Compute ICA

ica = FastICA(n_components=3)

S_ = ica.fit_transform(X)  # Reconstruct signals

A_ = ica.mixing_  # Get estimated mixing matrix

# We can `prove` that the ICA model applies by reverting the unmixing.

assert np.allclose(X, np.dot(S_, A_.T) + ica.mean_)

# For comparison, compute PCA

pca = PCA(n_components=3)

H = pca.fit_transform(X)  # Reconstruct signals based on orthogonal components

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

# Plot results

plt.figure()

models = [X, S, S_, H]

names = ['Observations (mixed signal)',

         'True Sources',

         'ICA recovered signals',

         'PCA recovered signals']

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()

 [3단계] 분석결과를 얻을 수 있다.

 

[결과해석] 세번째 그림에서 ICA실행 결과는 네번째 PCA결과보다 명확하게 사이클을 보이며 구분이 이루어지고 있음을 확인할 수 있다.

2) 예제2

[1단계] 다음과 같은 명령어를 입력한다.

print(__doc__)

# Authors: Alexandre Gramfort, Gael Varoquaux

# License: BSD 3 clause

import numpy as np

import matplotlib.pyplot as plt

from sklearn.decomposition import PCA, FastICA

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

# Generate sample data

rng = np.random.RandomState(42)

S = rng.standard_t(1.5, size=(20000, 2))

S[:, 0] *= 2.

# Mix data

A = np.array([[1, 1], [0, 2]])  # Mixing matrix

X = np.dot(S, A.T)  # Generate observations

pca = PCA()

S_pca_ = pca.fit(X).transform(X)

ica = FastICA(random_state=rng)

S_ica_ = ica.fit(X).transform(X)  # Estimate the sources

S_ica_ /= S_ica_.std(axis=0)

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

# Plot results

def plot_samples(S, axis_list=None):

    plt.scatter(S[:, 0], S[:, 1], s=2, marker='o', zorder=10,

                color='steelblue', alpha=0.5)

    if axis_list is not None:

        colors = ['orange', 'red']

        for color, axis in zip(colors, axis_list):

            axis /= axis.std()

            x_axis, y_axis = axis

            # Trick to get legend to work

            plt.plot(0.1 * x_axis, 0.1 * y_axis, linewidth=2, color=color)

            plt.quiver(0, 0, x_axis, y_axis, zorder=11, width=0.01, scale=6,

                       color=color)

    plt.hlines(0, -3, 3)

    plt.vlines(0, -3, 3)

    plt.xlim(-3, 3)

    plt.ylim(-3, 3)

    plt.xlabel('x')

    plt.ylabel('y')

plt.figure()

plt.subplot(2, 2, 1)

plot_samples(S / S.std())

plt.title('True Independent Sources')

axis_list = [pca.components_.T, ica.mixing_]

plt.subplot(2, 2, 2)

plot_samples(X / np.std(X), axis_list=axis_list)

legend = plt.legend(['PCA', 'ICA'], loc='upper right')

legend.set_zorder(100)

plt.title('Observations')

plt.subplot(2, 2, 3)

plot_samples(S_pca_ / np.std(S_pca_, axis=0))

plt.title('PCA recovered signals')

plt.subplot(2, 2, 4)

plot_samples(S_ica_ / np.std(S_ica_))

plt.title('ICA recovered signals')

plt.subplots_adjust(0.09, 0.04, 0.94, 0.94, 0.26, 0.36)

plt.show()

[2단계] 다음 결과를 얻을 수 있다. 

'Python > machine learning' 카테고리의 다른 글

Convolutional Neural Network  (0) 2020.08.11
scikit-learn Machine Learning in Python  (0) 2020.08.11
Comments