My DimentionalReduction

25 minute read

Machine Learning

0. 8장 연습문제 : 차원축소와 훈련시간, 성능

이번 실습은 차원 축소 기법을 이용하여 데이터 세트의 특성을 줄이고 그 후에 훈련 모델을 훈련시켰을 때 훈련시간과 성능과 같이 실제적인 효과가 있는 지 확인하기 위한 실습이다.

다양한 차원 축소 기법을 이용하여 차원(데이터 특성의 개수)을 축소하고 다양한 모델을 훈련하여 평가 및 확인하여 보자

  • 즉, 차원 축소의 실제적인 효과를 알아보자

기본 설정

# 파이썬 ≥3.5 필수 (파이썬 3.7 추천)
import sys
assert sys.version_info >= (3, 5) 

# 사이킷런 ≥0.20 필수
import sklearn
assert sklearn.__version__ >= "0.20"

# 공통 모듈 임포트
import numpy as np
import os

# 노트북 실행 결과를 동일하게 유지하기 위해
np.random.seed(42)

# 깔끔한 그래프 출력을 위해
%matplotlib inline
import matplotlib as mpl
import matplotlib.pyplot as plt
mpl.rc('axes', labelsize=14)
mpl.rc('xtick', labelsize=12)
mpl.rc('ytick', labelsize=12)

# 그림 저장 위치 지정
PROJECT_ROOT_DIR = "."
CHAPTER_ID = "dim_reduction"
IMAGES_PATH = os.path.join(PROJECT_ROOT_DIR, "images", CHAPTER_ID)
os.makedirs(IMAGES_PATH, exist_ok=True)

def save_fig(fig_id, tight_layout=True, fig_extension="png", resolution=300):
    path = os.path.join(IMAGES_PATH, fig_id + "." + fig_extension)
    print("Saving figure", fig_id)
    if tight_layout:
        plt.tight_layout()
    plt.savefig(path, format=fig_extension, dpi=resolution)

mnist 데이터를 가져오겠습니다.

from sklearn.datasets import fetch_openml

mnist = fetch_openml('mnist_784', version=1)
mnist.target = mnist.target.astype(np.uint8)

그리고 훈련세트와 테스트 세트를 나누었습니다. (처음 60000개를 훈련세트로 하고 남은 10000개를 테스트 세트로 하였습니다.

X_train = mnist['data'][:60000]
y_train = mnist['target'][:60000]

X_test = mnist['data'][60000:]
y_test = mnist['target'][60000:]

실습 1 : 랜덤포레스트

  • 랜덤포레스트 모델을 훈련시키고, 훈련시간과 테스트 세트로 성능을 평가하여 보자
from sklearn.ensemble import RandomForestClassifier

rnd_clf = RandomForestClassifier(n_estimators=100, random_state=42)

먼저 사이킷런의 RandomForestClassifier 클래스를 이용하여 랜덤포레스트 모델을 사용합니다.

import time

t0 = time.time()
rnd_clf.fit(X_train, y_train)
t1 = time.time()

훈련 시작과 끝 시각을 각각 t0와 t1에 저장하고 훈련을 하였습니다.

print("Training took {:.2f}s".format(t1 - t0))
Training took 43.92s

끝 시각 - 시작 시각으로 시간을 측정해보았습니다. 약 48초 걸렸습니다.

from sklearn.metrics import accuracy_score

y_pred = rnd_clf.predict(X_test)
accuracy_score(y_test, y_pred)
0.9705

이번엔 테스트 세트로 성능을 평가해보니 약 97% 정도의 정확도가 확인됩니다.

실습 2 : PCA

  • PCA 기법을 사용하여 설명 분산 비율의 합이 95%가 유지면서 데이터의 특성 차원을 줄여 보자
from sklearn.decomposition import PCA

pca = PCA(n_components=0.95)
X_train_reduced = pca.fit_transform(X_train)

실습 3 :PCA ->랜덤포레스트

  • 이번에 다시 차원이 줄어든 데이터 세트로 새로운 랜덤 포레스트 모델을 훈련시켜보자 그리고 더 빨라졌는지 확인해보자
rnd_clf2 = RandomForestClassifier(n_estimators=100, random_state=42)
t0 = time.time()
rnd_clf2.fit(X_train_reduced, y_train)
t1 = time.time()

마찬가지로 훈련 시작과 끝에 시각을 t0 t1에 저장하고 훈련하였습니다.

print("Training took {:.2f}s".format(t1 - t0))
Training took 106.21s

훈련 시간이 2배 이상 거의 3배에 가깝게 늘어났습니다.

보통 차원축소를 하면 훈련 시간이 적게 든다고 생각하지만 항상 그런것은 아닙니다.

데이터 세트, 모델과 훈련 알고리즘에 따라 훈련 시간이 늘어 날수도 있고, 줄어들 수도 있습니다.

실습 4 : 소프트맥스 차원축소비교

  • 정확도 성능을 평가해보고 이전의(차원축소 전) 모델의 성능과 비교하여보자
X_test_reduced = pca.transform(X_test)

y_pred = rnd_clf2.predict(X_test_reduced)
accuracy_score(y_test, y_pred)
0.9481

차원 축소를 하면 데이터의 정보를 일부 손실하기 때문에 모델의 성능이 떨어지는 것은 흔한 일입니다. 그러나 이번 경우는 이전에 비해 다소 많이 떨어졌습니다.( 약 97% -> 약 94.5%)

따라서 이번 랜덤포레스트 모델에서 PCA는 도움이 되지 못 했습니다. 더 느리고 성능은 떨어졌습니다. 그럼 이번엔 소프트맥스 회귀(로지스틱 회귀)의 경우는 PCA기법이 도움이 되는지 살펴 보겠습니다.

from sklearn.linear_model import LogisticRegression

log_clf = LogisticRegression(multi_class="multinomial", solver="lbfgs", random_state=42)
t0 = time.time()
log_clf.fit(X_train, y_train)
t1 = time.time()
/usr/local/lib/python3.7/dist-packages/sklearn/linear_model/_logistic.py:940: ConvergenceWarning: lbfgs failed to converge (status=1):
STOP: TOTAL NO. of ITERATIONS REACHED LIMIT.

Increase the number of iterations (max_iter) or scale the data as shown in:
    https://scikit-learn.org/stable/modules/preprocessing.html
Please also refer to the documentation for alternative solver options:
    https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression
  extra_warning_msg=_LOGISTIC_SOLVER_CONVERGENCE_MSG)

마찬가지로 모델을 선정하고 시작시각과 끝시각을 t0와 t1에 저장하였습니다.

print("Training took {:.2f}s".format(t1 - t0))
Training took 47.76s

걸린 시간을 확인해 보겠습니다. 43초입니다.

y_pred = log_clf.predict(X_test)
accuracy_score(y_test, y_pred)
0.9255

정확도 성능은 약 92.5%입니다.

랜덤포레스트보다 시간은 더 오래 걸리고 성능은 떨어졌습니다. 하지만 우리가 관심을 가질 것은 이제부터입니다. 과연 PCA기법으로 소프트맥스 회귀(로지스틱회귀)가 차원축소의 어떤 효과를 볼 수 있는지 말입니다.

차원 축소된 데이터 셋에 다시 새로운 로지스틱 회귀 모델을 훈련시켜보겠습니다.

log_clf2 = LogisticRegression(multi_class="multinomial", solver="lbfgs", random_state=42)
t0 = time.time()
log_clf2.fit(X_train_reduced, y_train)
t1 = time.time()
/usr/local/lib/python3.7/dist-packages/sklearn/linear_model/_logistic.py:940: ConvergenceWarning: lbfgs failed to converge (status=1):
STOP: TOTAL NO. of ITERATIONS REACHED LIMIT.

Increase the number of iterations (max_iter) or scale the data as shown in:
    https://scikit-learn.org/stable/modules/preprocessing.html
Please also refer to the documentation for alternative solver options:
    https://scikit-learn.org/stable/modules/linear_model.html#logistic-regression
  extra_warning_msg=_LOGISTIC_SOLVER_CONVERGENCE_MSG)

마찬가지로 시작 시각 끝 시각을 저장하여 훈련하였습니다.

print("Training took {:.2f}s".format(t1 - t0))
Training took 14.09s

훈련 시간을 보니 약 12초입니다. 약 43초에서 약 12초까지 감소하였습니다. 엄청난 감소입니다.

y_pred = log_clf2.predict(X_test_reduced)
accuracy_score(y_test, y_pred)
0.9201

이번엔 정확도를 확인해보겠습니다. 약 92.0%

약 0.5%의 감소가 있었지만 시간 단축을 거의 3분의 1 이하로 낮추어주었습니다. 즉 시간 단축에 비해 성능 저하가 아주 조금 있었기에 PCA기법이 의미가 있었고, 실제로 훈련이 시간 단축은 모델 훈련이 아주 중요한 요소이기에 큰 도움을 주었습니다.

하지만 항상 PCA기법이 시간 단축을 해주는것은 아니라는 것을 명심해야합니다.

실습 5 : t-SNE

  • t-SNE 기법을 이용하여 MNIST 데이터셋을 2차원으로 축소하고, Matplotlib를 이용하여 결과를 scatterplot 그림으로 확인하자. (타겟 클래스가 10개이므로 10개의 다른 색상이 보인다.)

6만개의 모든 이미지를 차원축소 하면 시간이 너무 오래 걸리므로 1만개만을 이용하여 실습하겠습니다.

np.random.seed(42)

m = 10000
idx = np.random.permutation(60000)[:m]

X = mnist['data'][idx]
y = mnist['target'][idx]

1만 개 데이터와 레이블을 각각 가져왔습니다.

from sklearn.manifold import TSNE

tsne = TSNE(n_components=2, random_state=42)
X_reduced = tsne.fit_transform(X)

t-SNE 모델로 2차원 특성으로 차원을 축소 하였습니다.

Matplotlib의 scatter() 함수로 scatterplot을 확인해 보겠습니다. 각각의 숫자에 대해 각각 다른 색상 즉 10개의 색상이 이용됩니다.

plt.figure(figsize=(13,10))
plt.scatter(X_reduced[:, 0], X_reduced[:, 1], c=y, cmap="jet")
plt.axis('off')
plt.colorbar()
plt.show()

output_54_0

이 plot을 보면 어떤 숫자와 어떤 숫자가 잘 구분되는지 (예 : 0, 6, 대부분의8) 어떤 숫자와 어떤 숫자가 구분이 잘 안 되는지 (4와 9, 5와 3 등등)를 눈으로 쉽게 확인 할 수 있습니다.

3과 5만을 집중해서 살펴 보겠습니다.

plt.figure(figsize=(9,9))
cmap = mpl.cm.get_cmap("jet")
for digit in (2, 3, 5):
    plt.scatter(X_reduced[y == digit, 0], X_reduced[y == digit, 1], c=[cmap(digit / 9)])
plt.axis('off')
plt.show()

output_57_0

많이 겹치는 것이 확인됩니다.

이 3개의 숫자(2, 3, 5)를 t-SNE로 돌려서 더 좋은 그림(각각이 더 확실히 구분되는 그림)을 만들 수 있을지 확인해보겠습니다.

idx = (y == 2) | (y == 3) | (y == 5) 
X_subset = X[idx]
y_subset = y[idx]

tsne_subset = TSNE(n_components=2, random_state=42)
X_subset_reduced = tsne_subset.fit_transform(X_subset)

다시 plot을 확인해보겠습니다.

plt.figure(figsize=(9,9))
for digit in (2, 3, 5):
    plt.scatter(X_subset_reduced[y_subset == digit, 0], X_subset_reduced[y_subset == digit, 1], c=[cmap(digit / 9)])
plt.axis('off')
plt.show()

output_62_0

훨씬 좋은 그림입니다. 이제 군집이 훨씬 덜 겹칩니다. 그러나 몇몇 3은 사방에 흩어져있고, 2의 군집과 5의 군집은 2개로 떨어져잇는 것이 보입니다. 왜 그런지 몇몇의 숫자들을 시각화 해보면 좋을것 같습니다 해보겠습니다.

실습 6 : 숫자 시각화

  • 각각의 인스턴스 위치에 그 색상으로 클래스에 해당하는 숫자를 쓰거나 축소된 숫자를 표시할 수 있습니다. 모든 인스턴스에 표시하면 복잡해지므로 랜덤으로 선택하거나 주위에 숫자 표시가 안된 인스턴스로 선택하여 숫자를 표시하는 그림을 같이 표시하겠습니다.

plot(산점도)위에 같은 색상의 숫자를 표시하는 plot_digits() 함수를 생성하고 산점도를 그려보겠습니다. (인스턴스를 선택할때 최소 거리를 고려합니다.)

from sklearn.preprocessing import MinMaxScaler
from matplotlib.offsetbox import AnnotationBbox, OffsetImage

def plot_digits(X, y, min_distance=0.05, images=None, figsize=(13, 10)):
    # Let's scale the input features so that they range from 0 to 1
    X_normalized = MinMaxScaler().fit_transform(X)
    # Now we create the list of coordinates of the digits plotted so far.
    # We pretend that one is already plotted far away at the start, to
    # avoid `if` statements in the loop below
    neighbors = np.array([[10., 10.]])
    # The rest should be self-explanatory
    plt.figure(figsize=figsize)
    cmap = mpl.cm.get_cmap("jet")
    digits = np.unique(y)
    for digit in digits:
        plt.scatter(X_normalized[y == digit, 0], X_normalized[y == digit, 1], c=[cmap(digit / 9)])
    plt.axis("off")
    ax = plt.gcf().gca()  # get current axes in current figure
    for index, image_coord in enumerate(X_normalized):
        closest_distance = np.linalg.norm(np.array(neighbors) - image_coord, axis=1).min()
        if closest_distance > min_distance:
            neighbors = np.r_[neighbors, [image_coord]]
            if images is None:
                plt.text(image_coord[0], image_coord[1], str(int(y[index])),
                         color=cmap(y[index] / 9), fontdict={"weight": "bold", "size": 16})
            else:
                image = images[index].reshape(28, 28)
                imagebox = AnnotationBbox(OffsetImage(image, cmap="binary"), image_coord)
                ax.add_artist(imagebox)

이제 그림을 확인해보겠습니다.

plot_digits(X_reduced, y)

output_68_0

별로 좋지 않습니다. 색상 숫자들이 섞여서 겹치는 것들이 많이 보입니다. 실제 숫자 이미지 사진을 확인해 보겠습니다.

plot_digits(X_reduced, y, images=X, figsize=(35, 25))

output_70_0

2, 3, 5 부분을 자세히 보겠습니다.

plot_digits(X_subset_reduced, y_subset, images=X_subset, figsize=(22, 22))

output_72_0

그림을 보니 아까 위에서 왜 3의 몇몇은 사방에 있고, 군집이 2개로 나뉘었는지 확인됩니다. 가까운 그림끼리는 서로 비슷한 모양으로 오해할 수 있겠다는 판단이 됩니다.

1.다양한 2차원 차원축소 : 훈련시간과 시각화

  • PCA, LLE, MDS와 같은 다른 차원 축소 기법 알고리즘을 이용해보고 결과를 시각화하여 비교하여 봅시다.
  • 훈련시간도 측정합니다.

PCA

  • PCA 기법을 이용하여 2차원으로 축소하고 결과를 시각화하고 훈련시간을 측정하였습니다.
from sklearn.decomposition import PCA
import time

t0 = time.time()
X_pca_reduced = PCA(n_components=2, random_state=42).fit_transform(X)
t1 = time.time()
print("PCA took {:.1f}s.".format(t1 - t0))
plot_digits(X_pca_reduced, y)
plt.show()
PCA took 1.0s.

output_76_1

1.1초로 매우 빠른 시간을 보이는 것 같지만, 너무 많이 겹쳐서 군집을 몇개 구분하여 보기 힘듭니다.

LLE

  • LLE 기법을 이용하여 2차원으로 차원 축소하고 결과 시각화와 훈련시간을 측정해보았습니다.
from sklearn.manifold import LocallyLinearEmbedding

t0 = time.time()
X_lle_reduced = LocallyLinearEmbedding(n_components=2, random_state=42).fit_transform(X)
t1 = time.time()
print("LLE took {:.1f}s.".format(t1 - t0))
plot_digits(X_lle_reduced, y)
plt.show()
LLE took 186.5s.

output_79_1

시간도 꽤 걸리고, 결과도 그리 좋아보이지 않습니다.(군집의 구분이 명확하게 보이지않음)

그렇다면 먼저 설명 분산 비율의 95%를 유지하면서 PCA기법으로 차원 축소 한후 LLE기법을 훈련한다면 어떻게 될까요?

PCA -> LLE

파이프라인으로 이번엔 PCA로 설명분산비율 95%로만 차원축소하고 그 다음 LLE기법을 해보겠습니다.

from sklearn.pipeline import Pipeline

pca_lle = Pipeline([
    ("pca", PCA(n_components=0.95, random_state=42)),
    ("lle", LocallyLinearEmbedding(n_components=2, random_state=42)),
])
t0 = time.time()
X_pca_lle_reduced = pca_lle.fit_transform(X)
t1 = time.time()
print("PCA+LLE took {:.1f}s.".format(t1 - t0))
plot_digits(X_pca_lle_reduced, y)
plt.show()
PCA+LLE took 59.8s.

output_84_1

그림의 결과는 비슷하지만, LLE만 했을 때보다는 시간은 훨씬 빨라졌네요.

MDS

  • 10000개를 모두 돌리면 너무 오래 걸리므로, 2000개만 해보도록 하겠습니다. 2찬원으로 축소합니다.
from sklearn.manifold import MDS

m = 2000
t0 = time.time()
X_mds_reduced = MDS(n_components=2, random_state=42).fit_transform(X[:m])
t1 = time.time()
print("MDS took {:.1f}s (on just 2,000 MNIST images instead of 10,000).".format(t1 - t0))
plot_digits(X_mds_reduced, y[:m])
plt.show()
MDS took 169.6s (on just 2,000 MNIST images instead of 10,000).

output_87_1

이것은 정말 안 좋아보입니다. 거의 모든 군집의 샘플(인스턴스)이 너무 많이 겹쳐서 보입니다.

이번에도 PCA기법을 먼저한다면 속도는 더 빨라질까요?

PCA -> MDS

  • 마찬가지로 파이프라인을 이용하여 95%의 설명분산비율을 유지하게 PCA기법을 먼저 적용하고, MDS기법을 이용하여 2차원 특성으로 축소하겠습니다.
from sklearn.pipeline import Pipeline

pca_mds = Pipeline([
    ("pca", PCA(n_components=0.95, random_state=42)),
    ("mds", MDS(n_components=2, random_state=42)),
])
t0 = time.time()
X_pca_mds_reduced = pca_mds.fit_transform(X[:2000])
t1 = time.time()
print("PCA+MDS took {:.1f}s (on 2,000 MNIST images).".format(t1 - t0))
plot_digits(X_pca_mds_reduced, y[:2000])
plt.show()
PCA+MDS took 169.1s (on 2,000 MNIST images).

output_91_1

결과는 거의 같고 시간도 비슷합니다.(PCA효과 없었습니다.)

LDA

  • 이번에도 2차원으로 축소합니다.
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis

t0 = time.time()
X_lda_reduced = LinearDiscriminantAnalysis(n_components=2).fit_transform(X, y)
t1 = time.time()
print("LDA took {:.1f}s.".format(t1 - t0))
plot_digits(X_lda_reduced, y, figsize=(12,12))
plt.show()
LDA took 3.1s.

output_94_1

이번에는 꽤 빨리 되었습니다. 앞에서 본것들보다 그림도 군집이 잘 구분된 것처럼 보입니다. 하지만 자세히 보면 겹친 군집도 꽤 많은 것이 확인됩니다.

t-SNE

  • 앞에서 사용한 t-SNE가 가장 군집을 잘 나눈 것 같습니다. 시간 측정을 안했으니 다시 해보겠습니다.
from sklearn.manifold import TSNE

t0 = time.time()
X_tsne_reduced = TSNE(n_components=2, random_state=42).fit_transform(X)
t1 = time.time()
print("t-SNE took {:.1f}s.".format(t1 - t0))
plot_digits(X_tsne_reduced, y)
plt.show()
t-SNE took 254.1s.

output_97_1

시간은 꽤 걸리지만 앞에서 한 기법들보다 결과는 훨씬 좋아보입니다. PCA기법을 먼저 적용하면 훈련 시간을 축소 시킬 수 있을까요?

PCA -> t-SNE

  • 이번에도 파이프라인으로 먼저 PCA기법을 설명 분산 비율이 95%가 유지되게 적용하고 다음으로 t-SNE 기법을 적용하였습니다.
pca_tsne = Pipeline([
    ("pca", PCA(n_components=0.95, random_state=42)),
    ("tsne", TSNE(n_components=2, random_state=42)),
])
t0 = time.time()
X_pca_tsne_reduced = pca_tsne.fit_transform(X)
t1 = time.time()
print("PCA+t-SNE took {:.1f}s.".format(t1 - t0))
plot_digits(X_pca_tsne_reduced, y)
plt.show()
PCA+t-SNE took 133.4s.

output_100_1

PCA를 먼저 적용한 효과가 있었습니다. 시간 단축이 많이 되었습니다.

2.차원축소 데이터(2차원) 분류기 훈련

SVC 분류기

SVC 분류기에도 다양한 커널 기법이 존재하지만, rbf나 poly는 추가적인 특성을 추가하는 효과를 냅니다.

따라서 우리는 방금 데이터 세트의 차원 축소를 했기 때문에 차원을 축소했다가 다시 추가하는 효과를 얻는 모델을 사용하는 것은 모순되는 것처럼 보이기에 선형SVC모델을 사용하겠습니다.

  • SVC의 선형커널보다 LinearSVC모델이 일반적으로 훈련속도가 빠르므로 LinearSVC 모델을 사용하겠습니다.

원본데이터(차원축소X)

일단 원래 데이터 세트를 이용하여 최적의 모델을 찾겠습니다. 먼저 데이터를 훈련세트와 테스트 세트로 나누었습니다.

from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

먼저 LinearSVC 모델에 대한 하이퍼파라미터인 규제(C)에 대해 그리드 탐색을 돌려 최적의 모델을 찾아보겠습니다.

from sklearn.svm import LinearSVC
from sklearn.model_selection import GridSearchCV



params = {'C': list(range(2, 100, 10))}
grid_search_cv = GridSearchCV(LinearSVC(loss="hinge", random_state=42 ), params, verbose=1, cv=3)

grid_search_cv.fit(X_train, y_train)
Fitting 3 folds for each of 10 candidates, totalling 30 fits


[Parallel(n_jobs=1)]: Using backend SequentialBackend with 1 concurrent workers.
/usr/local/lib/python3.7/dist-packages/sklearn/svm/_base.py:947: ConvergenceWarning: Liblinear failed to converge, increase the number of iterations.
  "the number of iterations.", ConvergenceWarning)
/usr/local/lib/python3.7/dist-packages/sklearn/svm/_base.py:947: ConvergenceWarning: Liblinear failed to converge, increase the number of iterations.
  "the number of iterations.", ConvergenceWarning)
/usr/local/lib/python3.7/dist-packages/sklearn/svm/_base.py:947: ConvergenceWarning: Liblinear failed to converge, increase the number of iterations.
  "the number of iterations.", ConvergenceWarning)
/usr/local/lib/python3.7/dist-packages/sklearn/svm/_base.py:947: ConvergenceWarning: Liblinear failed to converge, increase the number of iterations.
  "the number of iterations.", ConvergenceWarning)
/usr/local/lib/python3.7/dist-packages/sklearn/svm/_base.py:947: ConvergenceWarning: Liblinear failed to converge, increase the number of iterations.
  "the number of iterations.", ConvergenceWarning)
/usr/local/lib/python3.7/dist-packages/sklearn/svm/_base.py:947: ConvergenceWarning: Liblinear failed to converge, increase the number of iterations.
  "the number of iterations.", ConvergenceWarning)
/usr/local/lib/python3.7/dist-packages/sklearn/svm/_base.py:947: ConvergenceWarning: Liblinear failed to converge, increase the number of iterations.
  "the number of iterations.", ConvergenceWarning)
/usr/local/lib/python3.7/dist-packages/sklearn/svm/_base.py:947: ConvergenceWarning: Liblinear failed to converge, increase the number of iterations.
  "the number of iterations.", ConvergenceWarning)
/usr/local/lib/python3.7/dist-packages/sklearn/svm/_base.py:947: ConvergenceWarning: Liblinear failed to converge, increase the number of iterations.
  "the number of iterations.", ConvergenceWarning)
/usr/local/lib/python3.7/dist-packages/sklearn/svm/_base.py:947: ConvergenceWarning: Liblinear failed to converge, increase the number of iterations.
  "the number of iterations.", ConvergenceWarning)
/usr/local/lib/python3.7/dist-packages/sklearn/svm/_base.py:947: ConvergenceWarning: Liblinear failed to converge, increase the number of iterations.
  "the number of iterations.", ConvergenceWarning)
/usr/local/lib/python3.7/dist-packages/sklearn/svm/_base.py:947: ConvergenceWarning: Liblinear failed to converge, increase the number of iterations.
  "the number of iterations.", ConvergenceWarning)
/usr/local/lib/python3.7/dist-packages/sklearn/svm/_base.py:947: ConvergenceWarning: Liblinear failed to converge, increase the number of iterations.
  "the number of iterations.", ConvergenceWarning)
/usr/local/lib/python3.7/dist-packages/sklearn/svm/_base.py:947: ConvergenceWarning: Liblinear failed to converge, increase the number of iterations.
  "the number of iterations.", ConvergenceWarning)
/usr/local/lib/python3.7/dist-packages/sklearn/svm/_base.py:947: ConvergenceWarning: Liblinear failed to converge, increase the number of iterations.
  "the number of iterations.", ConvergenceWarning)
/usr/local/lib/python3.7/dist-packages/sklearn/svm/_base.py:947: ConvergenceWarning: Liblinear failed to converge, increase the number of iterations.
  "the number of iterations.", ConvergenceWarning)
/usr/local/lib/python3.7/dist-packages/sklearn/svm/_base.py:947: ConvergenceWarning: Liblinear failed to converge, increase the number of iterations.
  "the number of iterations.", ConvergenceWarning)
/usr/local/lib/python3.7/dist-packages/sklearn/svm/_base.py:947: ConvergenceWarning: Liblinear failed to converge, increase the number of iterations.
  "the number of iterations.", ConvergenceWarning)
/usr/local/lib/python3.7/dist-packages/sklearn/svm/_base.py:947: ConvergenceWarning: Liblinear failed to converge, increase the number of iterations.
  "the number of iterations.", ConvergenceWarning)
/usr/local/lib/python3.7/dist-packages/sklearn/svm/_base.py:947: ConvergenceWarning: Liblinear failed to converge, increase the number of iterations.
  "the number of iterations.", ConvergenceWarning)
/usr/local/lib/python3.7/dist-packages/sklearn/svm/_base.py:947: ConvergenceWarning: Liblinear failed to converge, increase the number of iterations.
  "the number of iterations.", ConvergenceWarning)
/usr/local/lib/python3.7/dist-packages/sklearn/svm/_base.py:947: ConvergenceWarning: Liblinear failed to converge, increase the number of iterations.
  "the number of iterations.", ConvergenceWarning)
/usr/local/lib/python3.7/dist-packages/sklearn/svm/_base.py:947: ConvergenceWarning: Liblinear failed to converge, increase the number of iterations.
  "the number of iterations.", ConvergenceWarning)
/usr/local/lib/python3.7/dist-packages/sklearn/svm/_base.py:947: ConvergenceWarning: Liblinear failed to converge, increase the number of iterations.
  "the number of iterations.", ConvergenceWarning)
/usr/local/lib/python3.7/dist-packages/sklearn/svm/_base.py:947: ConvergenceWarning: Liblinear failed to converge, increase the number of iterations.
  "the number of iterations.", ConvergenceWarning)
/usr/local/lib/python3.7/dist-packages/sklearn/svm/_base.py:947: ConvergenceWarning: Liblinear failed to converge, increase the number of iterations.
  "the number of iterations.", ConvergenceWarning)
/usr/local/lib/python3.7/dist-packages/sklearn/svm/_base.py:947: ConvergenceWarning: Liblinear failed to converge, increase the number of iterations.
  "the number of iterations.", ConvergenceWarning)
/usr/local/lib/python3.7/dist-packages/sklearn/svm/_base.py:947: ConvergenceWarning: Liblinear failed to converge, increase the number of iterations.
  "the number of iterations.", ConvergenceWarning)
/usr/local/lib/python3.7/dist-packages/sklearn/svm/_base.py:947: ConvergenceWarning: Liblinear failed to converge, increase the number of iterations.
  "the number of iterations.", ConvergenceWarning)
/usr/local/lib/python3.7/dist-packages/sklearn/svm/_base.py:947: ConvergenceWarning: Liblinear failed to converge, increase the number of iterations.
  "the number of iterations.", ConvergenceWarning)
[Parallel(n_jobs=1)]: Done  30 out of  30 | elapsed:  1.5min finished
/usr/local/lib/python3.7/dist-packages/sklearn/svm/_base.py:947: ConvergenceWarning: Liblinear failed to converge, increase the number of iterations.
  "the number of iterations.", ConvergenceWarning)





GridSearchCV(cv=3, error_score=nan,
             estimator=LinearSVC(C=1.0, class_weight=None, dual=True,
                                 fit_intercept=True, intercept_scaling=1,
                                 loss='hinge', max_iter=1000, multi_class='ovr',
                                 penalty='l2', random_state=42, tol=0.0001,
                                 verbose=0),
             iid='deprecated', n_jobs=None,
             param_grid={'C': [2, 12, 22, 32, 42, 52, 62, 72, 82, 92]},
             pre_dispatch='2*n_jobs', refit=True, return_train_score=False,
             scoring=None, verbose=1)

최적의 모델을 확인해보자

grid_search_cv.best_estimator_
LinearSVC(C=2, class_weight=None, dual=True, fit_intercept=True,
          intercept_scaling=1, loss='hinge', max_iter=1000, multi_class='ovr',
          penalty='l2', random_state=42, tol=0.0001, verbose=0)

C = 2가 최적의 하이퍼파라미터로 판단되었습니다. (범위를 잘못 잡은 것은 아닌지 일단 진행 후 C=1로 하여 다시 성능평가해 보겠다.)

GridSearchCV은 자연스럽게 훈련세트에 대해 찾은 최적의 하이퍼파라미터로 훈련을 시킵니다. (기본값으로 refit=True 로 설정되기 때문입니다.) 따라서 바로 훈련된 결정트리 모델에 대하여 테스트 세트에 대한 성능 평가를 해보겠습니다.

from sklearn.metrics import accuracy_score

y_pred = grid_search_cv.predict(X_test)
accuracy_score(y_test, y_pred)
0.862

약 86% 입니다.

이번엔 다시 C=1로 해보겠습니다.

Lsvcc1 = LinearSVC(C=1, loss="hinge", random_state=42 )

훈련시키겠습니다.

Lsvcc1.fit(X_train, y_train)
/usr/local/lib/python3.7/dist-packages/sklearn/svm/_base.py:947: ConvergenceWarning: Liblinear failed to converge, increase the number of iterations.
  "the number of iterations.", ConvergenceWarning)





LinearSVC(C=1, class_weight=None, dual=True, fit_intercept=True,
          intercept_scaling=1, loss='hinge', max_iter=1000, multi_class='ovr',
          penalty='l2', random_state=42, tol=0.0001, verbose=0)
y_pred = Lsvcc1.predict(X_test)
accuracy_score(y_test, y_pred)
0.862

동일한 결과가 나왔으므로 C=1로 사용하도록 하겠습니다.

PCA

1장에서 데이터를 모두 차원축소 시켰고 그 결과를 가지고 있으므로 바로 이용하겠습니다.

  • X_pca_reduced : PCA기법으로 차원을 2차원으로 축소한 데이터입니다.

먼저 데이터를 훈련세트와 테스트 세트로 분류하겠습니다.

from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(X_pca_reduced, y, test_size=0.2, random_state=42)

훈련 모델은 위에서 찾은 최적의 모델 C=1인 LinearSVC 모델을 훈련시킵니다. 앞으로 계속 이 모델을 훈련시켜 차원축소 기법에 따른 성능을 비교하겠습니다.

훈련 후 바로 정확도 성능을 확인해보겠습니다.

Lsvcc1.fit(X_train, y_train)

y_pred = Lsvcc1.predict(X_test)
accuracy_score(y_test, y_pred)
/usr/local/lib/python3.7/dist-packages/sklearn/svm/_base.py:947: ConvergenceWarning: Liblinear failed to converge, increase the number of iterations.
  "the number of iterations.", ConvergenceWarning)





0.1835

약 18%로 성능이 저하가 꽤 심각한 수준입니다.

LLE

  • X_lle_reduced : LLE기법을 이용하여 데이터의 차원을 2차원으로 축소한 데이터입니다.

훈련세트와 테스트세트를 분류하겠습니다.

from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(X_lle_reduced, y, test_size=0.2, random_state=42)

위에서 찾은 최적의 모델 C=1인 LinearSVC 모델을 훈련시킵니다.

훈련 후 바로 정확도 성능을 확인해보겠습니다.

Lsvcc1.fit(X_train, y_train)

y_pred = Lsvcc1.predict(X_test)
accuracy_score(y_test, y_pred)
/usr/local/lib/python3.7/dist-packages/sklearn/svm/_base.py:947: ConvergenceWarning: Liblinear failed to converge, increase the number of iterations.
  "the number of iterations.", ConvergenceWarning)





0.4095

이번엔 약 40.9%로 PCA기법보다는 성능이 좋아졌지만 원본데이터를 훈련한 경우보다는 확실히 성능이 많이 떨어집니다.

PCA -> LLE

  • X_pca_lle_reduced : PCA기법으로 설명분산 비율을 95% 유지하면서 차원축소를 한후 LLE기법을 이용하여 데이터의 차원을 2차원으로 축소한 데이터입니다.

훈련세트와 테스트세트를 분류하겠습니다.

from sklearn.model_selection import train_test_split


X_train, X_test, y_train, y_test = train_test_split(X_pca_lle_reduced, y, test_size=0.2, random_state=42)

위에서 찾은 최적의 모델 C=1인 LinearSVC 모델을 훈련시킵니다.

훈련 후 바로 정확도 성능을 확인해보겠습니다.

Lsvcc1.fit(X_train, y_train)

y_pred = Lsvcc1.predict(X_test)
accuracy_score(y_test, y_pred)
/usr/local/lib/python3.7/dist-packages/sklearn/svm/_base.py:947: ConvergenceWarning: Liblinear failed to converge, increase the number of iterations.
  "the number of iterations.", ConvergenceWarning)





0.399

이번에도 약 39.9%로 LLE만 적용한 경우보다 약 1%가량 성능이 떨어졌습니다.

MDS

  • X_mds_reduced : MDS기법을 이용하여 데이터의 차원을 2차원으로 축소한 데이터입니다.
  • MDS를 이용할 때 시간상의 이유로 데이터를 2000개만 썼으므로 레이블도 2000개만 사용합니다.

훈련세트와 테스트세트를 분류하겠습니다.

from sklearn.model_selection import train_test_split

y_mds = y[:m]

X_train, X_test, y_train, y_test = train_test_split(X_mds_reduced, y_mds, test_size=0.2, random_state=42)

위에서 찾은 최적의 모델 C=1인 LinearSVC 모델을 훈련시킵니다.

훈련 후 바로 정확도 성능을 확인해보겠습니다.

Lsvcc1.fit(X_train, y_train)

y_pred = Lsvcc1.predict(X_test)
accuracy_score(y_test, y_pred)
/usr/local/lib/python3.7/dist-packages/sklearn/svm/_base.py:947: ConvergenceWarning: Liblinear failed to converge, increase the number of iterations.
  "the number of iterations.", ConvergenceWarning)





0.125

이번에는 12.5%로 원본 데이터에 비해 상당히 떨어지는 것이 확인됩니다.

PCA -> MDS

  • X_pca_mds_reduced : PCA기법으로 설명분산 비율을 95% 유지하면서 차원축소를 한후 MDS기법을 이용하여 데이터의 차원을 2차원으로 축소한 데이터입니다.
  • MDS를 이용할 때 시간상의 이유로 데이터를 2000개만 썼으므로 레이블도 2000개만 사용합니다.

훈련세트와 테스트세트를 분류하겠습니다.

from sklearn.model_selection import train_test_split


X_train, X_test, y_train, y_test = train_test_split(X_pca_mds_reduced, y_mds, test_size=0.2, random_state=42)

위에서 찾은 최적의 모델 C=1인 LinearSVC 모델을 훈련시킵니다.

훈련 후 바로 정확도 성능을 확인해보겠습니다.

Lsvcc1.fit(X_train, y_train)

y_pred = Lsvcc1.predict(X_test)
accuracy_score(y_test, y_pred)
/usr/local/lib/python3.7/dist-packages/sklearn/svm/_base.py:947: ConvergenceWarning: Liblinear failed to converge, increase the number of iterations.
  "the number of iterations.", ConvergenceWarning)





0.1175

약 11.7%로 MDS만 적용한 경우보다 약 0.7%가량 성능이 떨어졌습니다.

LDA

  • X_lda_reduced : LDA기법을 이용하여 데이터의 차원을 2차원으로 축소한 데이터입니다.

훈련세트와 테스트세트를 분류하겠습니다.

from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(X_lda_reduced, y, test_size=0.2, random_state=42)

위에서 찾은 최적의 모델 C=1인 LinearSVC 모델을 훈련시킵니다.

훈련 후 바로 정확도 성능을 확인해보겠습니다.

Lsvcc1.fit(X_train, y_train)

y_pred = Lsvcc1.predict(X_test)
accuracy_score(y_test, y_pred)
/usr/local/lib/python3.7/dist-packages/sklearn/svm/_base.py:947: ConvergenceWarning: Liblinear failed to converge, increase the number of iterations.
  "the number of iterations.", ConvergenceWarning)





0.386

이번엔 약 38.6%로 여태까지 한 차원 축소 중에서는 괜찮은 편에 속하지만 그래도 성능이 매우 좋지 않습니다.

t-SNE

  • X_tsne_reduced : t-SNE기법을 이용하여 데이터의 차원을 2차원으로 축소한 데이터입니다.

훈련세트와 테스트세트를 분류하겠습니다.

from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(X_tsne_reduced, y, test_size=0.2, random_state=42)

위에서 찾은 최적의 모델 C=1인 LinearSVC 모델을 훈련시킵니다.

훈련 후 바로 정확도 성능을 확인해보겠습니다.

Lsvcc1.fit(X_train, y_train)

y_pred = Lsvcc1.predict(X_test)
accuracy_score(y_test, y_pred)
/usr/local/lib/python3.7/dist-packages/sklearn/svm/_base.py:947: ConvergenceWarning: Liblinear failed to converge, increase the number of iterations.
  "the number of iterations.", ConvergenceWarning)





0.623

약 62.3%로 여태까지 한 차원 축소들 중에서는 가장 좋은 성능을 보이고 있지만 그래도 원본데이터에 비해서는 성능이 많이 떨어진다고 판단됩니다.

위에서 시각화 하였을 때도 t-SNE가 다른 차원 축소들보다 잘 군집이 나누어졌는데 그것의 효과를 보는 것 같습니다. (하지만 여전히 군집이 겹치는 부분도 많았기 때문에 성능이 원본에 비해서 떨어지는 것 같습니다.)

PCA -> t-SNE

  • X_pca_tsne_reduced : PCA기법으로 설명분산 비율을 95% 유지하면서 차원축소를 한후 t-SNE기법을 이용하여 데이터의 차원을 2차원으로 축소한 데이터입니다.

훈련세트와 테스트세트를 분류하겠습니다.

from sklearn.model_selection import train_test_split


X_train, X_test, y_train, y_test = train_test_split(X_pca_tsne_reduced, y, test_size=0.2, random_state=42)

위에서 찾은 최적의 모델 C=1인 LinearSVC 모델을 훈련시킵니다.

훈련 후 바로 정확도 성능을 확인해보겠습니다.

Lsvcc1.fit(X_train, y_train)

y_pred = Lsvcc1.predict(X_test)
accuracy_score(y_test, y_pred)
/usr/local/lib/python3.7/dist-packages/sklearn/svm/_base.py:947: ConvergenceWarning: Liblinear failed to converge, increase the number of iterations.
  "the number of iterations.", ConvergenceWarning)





0.427

약 42.7%로 t-SNE만 적용한 경우보다 약 20%가량 성능이 떨어졌습니다. 엄청 많이 떨어졌으므로 PCA기법을 먼저 적용하고 훈련하는 것보다 바로 훈련하는 것이 좋을 것 같습니다.

랜덤 포레스트

  • PCA를 먼저 적용한 후 해당 기법으로 차원축소를 한 경우는 해당 기법만으로 차원 축소를 한 경우보다 성능이 좋지 않았습니다.
  • 따라서 PCA기법을 먼저 적용한 경우는 제외하겠습니다.
  • 차원축소에 따른 분류기 성능을 보기 위함 입니다.

원본데이터(차원축소X)

일단 원본 데이터 세트를 이용하여 훈련시켜 성능을 보겠습니다. 먼저 데이터를 훈련세트와 테스트 세트로 나누었습니다.

from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

랜덤 포레스트 모델을 다음과 같이 훈련시켜 보겠습니다.

from sklearn.ensemble import RandomForestClassifier

rnd_clf = RandomForestClassifier(n_estimators=1000, max_leaf_nodes=17, random_state=42)
rnd_clf.fit(X_train, y_train)
RandomForestClassifier(bootstrap=True, ccp_alpha=0.0, class_weight=None,
                       criterion='gini', max_depth=None, max_features='auto',
                       max_leaf_nodes=17, max_samples=None,
                       min_impurity_decrease=0.0, min_impurity_split=None,
                       min_samples_leaf=1, min_samples_split=2,
                       min_weight_fraction_leaf=0.0, n_estimators=1000,
                       n_jobs=None, oob_score=False, random_state=42, verbose=0,
                       warm_start=False)

훈련은 다 했고 이제 정확도를 보겠습니다.

from sklearn.metrics import accuracy_score

y_pred = rnd_clf.predict(X_test)
accuracy_score(y_test, y_pred)
0.8585

약 85.8% 입니다.

PCA

1장에서 데이터를 모두 차원축소 시켰고 그 결과를 가지고 있으므로 바로 이용하겠습니다.

  • X_pca_reduced : PCA기법으로 차원을 2차원으로 축소한 데이터입니다.

먼저 데이터를 훈련세트와 테스트 세트로 분류하겠습니다.

from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(X_pca_reduced, y, test_size=0.2, random_state=42)

랜덤 포레스트 모델을 훈련시킵니다.

훈련 후 바로 정확도 성능을 확인해보겠습니다.

rnd_clf.fit(X_train, y_train)

y_pred = rnd_clf.predict(X_test)
accuracy_score(y_test, y_pred)
0.4525

약 45.2%로 성능이 저하가 많이 일어났습니다.

LLE

  • X_lle_reduced : LLE기법을 이용하여 데이터의 차원을 2차원으로 축소한 데이터입니다.

훈련세트와 테스트세트를 분류하겠습니다.

from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(X_lle_reduced, y, test_size=0.2, random_state=42)

랜덤포레스트 모델을 훈련시킵니다.

훈련 후 바로 정확도 성능을 확인해보겠습니다.

rnd_clf.fit(X_train, y_train)

y_pred = rnd_clf.predict(X_test)
accuracy_score(y_test, y_pred)
0.846

이번엔 약 84.6%로 원본데이터와 성능 차이가 거의 없습니다. 약 0.8% 떨어집니다.

MDS

  • X_mds_reduced : MDS기법을 이용하여 데이터의 차원을 2차원으로 축소한 데이터입니다.
  • MDS를 이용할 때 시간상의 이유로 데이터를 2000개만 썼으므로 레이블도 2000개만 사용합니다.

훈련세트와 테스트세트를 분류하겠습니다.

from sklearn.model_selection import train_test_split

y_mds = y[:m]

X_train, X_test, y_train, y_test = train_test_split(X_mds_reduced, y_mds, test_size=0.2, random_state=42)

랜덤 포레스트 모델을 훈련시킵니다.

훈련 후 바로 정확도 성능을 확인해보겠습니다.

rnd_clf.fit(X_train, y_train)

y_pred = rnd_clf.predict(X_test)
accuracy_score(y_test, y_pred)
0.485

이번에는 48.5%로 원본 데이터에 비해 상당히 떨어지는 것이 확인됩니다.

LDA

  • X_lda_reduced : LDA기법을 이용하여 데이터의 차원을 2차원으로 축소한 데이터입니다.

훈련세트와 테스트세트를 분류하겠습니다.

from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(X_lda_reduced, y, test_size=0.2, random_state=42)

랜덤포레스트 모델을 훈련시킵니다.

훈련 후 바로 정확도 성능을 확인해보겠습니다.

rnd_clf.fit(X_train, y_train)

y_pred = rnd_clf.predict(X_test)
accuracy_score(y_test, y_pred)
0.5885

이번엔 약 58.8%로 여태까지 MDS보다는 좋아졌지만 그래도 원본 데이터에 비해 성능이 매우 좋지 않습니다.

t-SNE

  • X_tsne_reduced : t-SNE기법을 이용하여 데이터의 차원을 2차원으로 축소한 데이터입니다.

훈련세트와 테스트세트를 분류하겠습니다.

from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(X_tsne_reduced, y, test_size=0.2, random_state=42)

랜덤 포레스트 모델을 훈련시킵니다.

훈련 후 바로 정확도 성능을 확인해보겠습니다.

rnd_clf.fit(X_train, y_train)

y_pred = rnd_clf.predict(X_test)
accuracy_score(y_test, y_pred)
0.914

약 91.4%로 여태까지 한 차원 축소들 중에서는 가장 좋은 성능을 보이는 뿐만 아니라 원본데이터를 이용했을 때보다 성능이 더 높게 나왔습니다.

위에서 시각화 하였을 때도 t-SNE가 다른 차원 축소들보다 잘 군집이 나누어졌는데 그것의 효과를 보는 것 같습니다.

3.다양한 3차원 차원축소 : 훈련시간과 시각화

  • PCA, LLE, MDS t-SNE 기법 알고리즘으로 이번에는 데이터세트를 3차원으로 차원 축소를 해보도록 하겠습니다.
  • 2차원 차원축소의 경우를 살펴보면 PCA 기법으로 먼저 차원 축소를 한 후 다시 해당 기법으로 차원을 축소하는 경우보다 바로 해당 기법을 훈련한 경우가 성능이 좋았기 때문에 PCA기법을 먼저 사용하는 경우는 배제하겠습니다.
  • 차원 축소 기법에 따른 분류기 성능을 비교하기 위한 실습입니다.

PCA

  • PCA 기법을 이용하여 3차원으로 축소하고 훈련시간을 측정해보았습니다.
from sklearn.decomposition import PCA
import time

t0 = time.time()
X_pca_reduced3 = PCA(n_components=3, random_state=42).fit_transform(X)
t1 = time.time()
print("PCA took {:.1f}s.".format(t1 - t0))

PCA took 1.2s.

3차원으로 하더라도 PCA 기법은 훈련시간이 빠릅니다.

LLE

  • LLE 기법을 이용하여 3차원으로 차원 축소하고 훈련시간을 측정해보았습니다.
from sklearn.manifold import LocallyLinearEmbedding

t0 = time.time()
X_lle_reduced3 = LocallyLinearEmbedding(n_components=3, random_state=42).fit_transform(X)
t1 = time.time()
print("LLE took {:.1f}s.".format(t1 - t0))

LLE took 176.4s.

꽤 시간이 걸렸습니다.

MDS

  • 10000개를 모두 돌리면 너무 오래 걸리므로, 2000개만 해보도록 하겠습니다. 3차원으로 축소합니다.
from sklearn.manifold import MDS

m = 2000
t0 = time.time()
X_mds_reduced3 = MDS(n_components=3, random_state=42).fit_transform(X[:m])
t1 = time.time()
print("MDS took {:.1f}s (on just 2,000 MNIST images instead of 10,000).".format(t1 - t0))

MDS took 155.1s (on just 2,000 MNIST images instead of 10,000).

이번에도 꽤 시간이 걸려서 훈련을 완료하였습니다.

LDA

  • 이번에도 3차원으로 축소합니다.
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis

t0 = time.time()
X_lda_reduced3 = LinearDiscriminantAnalysis(n_components=3).fit_transform(X, y)
t1 = time.time()
print("LDA took {:.1f}s.".format(t1 - t0))

LDA took 3.1s.

이번에는 앞의 경우들과 비교했을 때 꽤 빨리 되었습니다.

t-SNE

  • 3차원으로 차원 축소합니다.
from sklearn.manifold import TSNE

t0 = time.time()
X_tsne_reduced3 = TSNE(n_components=3, random_state=42).fit_transform(X)
t1 = time.time()
print("t-SNE took {:.1f}s.".format(t1 - t0))

t-SNE took 596.8s.

너무 오래 걸렸습니다. 차원 축소는 완료 되었습니다.

4.차원축소 데이터(3차원) 분류기 훈련

선형 SVC

  • PCA를 먼저 적용한 후 해당 기법으로 차원축소를 한 경우는 해당 기법만으로 차원 축소를 한 경우보다 성능이 좋지 않았습니다.
  • 따라서 PCA기법을 먼저 적용한 경우는 제외하겠습니다.
  • 차원축소에 따른 분류기 성능을 보기 위함 입니다.

  • 선형 SVC 모델은 앞에서 2차원에서 썼던 모델과 같은 Lsvcc1을 사용하겠습니다.

원본데이터(차원축소X)

원본 데이터에 대한 성능은 위에서 측정하였기에 그 값만 기억하겠습니다.

  • 원본 데이터에 대한 랜덤 포레스트 모델 성능 : 약 86.2%

PCA

3장에서 데이터를 모두 차원축소 시켰고 그 결과를 가지고 있으므로 바로 이용하겠습니다.

  • X_pca_reduced3 : PCA기법으로 차원을 3차원으로 축소한 데이터입니다.

먼저 데이터를 훈련세트와 테스트 세트로 분류하겠습니다.

from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(X_pca_reduced3, y, test_size=0.2, random_state=42)

선형 SVC 모델을 훈련시킵니다.

훈련 후 바로 정확도 성능을 확인해보겠습니다.

Lsvcc1.fit(X_train, y_train)

y_pred = Lsvcc1.predict(X_test)
accuracy_score(y_test, y_pred)
/usr/local/lib/python3.7/dist-packages/sklearn/svm/_base.py:947: ConvergenceWarning: Liblinear failed to converge, increase the number of iterations.
  "the number of iterations.", ConvergenceWarning)





0.1895

약 18.9%로 성능이 저하가 많이 일어났습니다.

LLE

  • X_lle_reduced3 : LLE기법을 이용하여 데이터의 차원을 3차원으로 축소한 데이터입니다.

훈련세트와 테스트세트를 분류하겠습니다.

from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(X_lle_reduced3, y, test_size=0.2, random_state=42)

선형 SVC모델을 훈련시킵니다.

훈련 후 바로 정확도 성능을 확인해보겠습니다.

Lsvcc1.fit(X_train, y_train)

y_pred = Lsvcc1.predict(X_test)
accuracy_score(y_test, y_pred)
/usr/local/lib/python3.7/dist-packages/sklearn/svm/_base.py:947: ConvergenceWarning: Liblinear failed to converge, increase the number of iterations.
  "the number of iterations.", ConvergenceWarning)





0.4995

이번엔 약 49.95%로 PCA 경우 보다는 성능이 좋지만 원본데이터에 비하면 엄청난 성능 저하입니다.

MDS

  • X_mds_reduced3 : MDS기법을 이용하여 데이터의 차원을 3차원으로 축소한 데이터입니다.
  • MDS를 이용할 때 시간상의 이유로 데이터를 2000개만 썼으므로 레이블도 2000개만 사용합니다.

훈련세트와 테스트세트를 분류하겠습니다.

from sklearn.model_selection import train_test_split

y_mds = y[:m]

X_train, X_test, y_train, y_test = train_test_split(X_mds_reduced3, y_mds, test_size=0.2, random_state=42)

선형 SVC모델을 훈련시킵니다.

훈련 후 바로 정확도 성능을 확인해보겠습니다.

Lsvcc1.fit(X_train, y_train)

y_pred = Lsvcc1.predict(X_test)
accuracy_score(y_test, y_pred)
/usr/local/lib/python3.7/dist-packages/sklearn/svm/_base.py:947: ConvergenceWarning: Liblinear failed to converge, increase the number of iterations.
  "the number of iterations.", ConvergenceWarning)





0.0925

이번에는 9.2%로 사용하기에 최악의 수준의 성능입니다.

LDA

  • X_lda_reduced3 : LDA기법을 이용하여 데이터의 차원을 3차원으로 축소한 데이터입니다.

훈련세트와 테스트세트를 분류하겠습니다.

from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(X_lda_reduced3, y, test_size=0.2, random_state=42)

선형 SVC 모델을 훈련시킵니다.

훈련 후 바로 정확도 성능을 확인해보겠습니다.

Lsvcc1.fit(X_train, y_train)

y_pred = Lsvcc1.predict(X_test)
accuracy_score(y_test, y_pred)
/usr/local/lib/python3.7/dist-packages/sklearn/svm/_base.py:947: ConvergenceWarning: Liblinear failed to converge, increase the number of iterations.
  "the number of iterations.", ConvergenceWarning)





0.592

이번엔 약 59.2%로 여태까지 중에서는 가장 나아 보이지만 여전히 성능이 좋지 않습니다.

t-SNE

  • X_tsne_reduced3 : t-SNE기법을 이용하여 데이터의 차원을 3차원으로 축소한 데이터입니다.

훈련세트와 테스트세트를 분류하겠습니다.

from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(X_tsne_reduced3, y, test_size=0.2, random_state=42)

선형 SVC 모델을 훈련시킵니다.

훈련 후 바로 정확도 성능을 확인해보겠습니다.

Lsvcc1.fit(X_train, y_train)

y_pred = Lsvcc1.predict(X_test)
accuracy_score(y_test, y_pred)
/usr/local/lib/python3.7/dist-packages/sklearn/svm/_base.py:947: ConvergenceWarning: Liblinear failed to converge, increase the number of iterations.
  "the number of iterations.", ConvergenceWarning)





0.8255

약 82.5%로 여태까지 한 차원 축소들 중에서는 가장 좋은 성능을 보이며 원본 데이터와도 약 4% 차이 정도밖에 나지 않습니다.

위에서 시각화 하였을 때도 t-SNE가 다른 차원 축소들보다 잘 군집이 나누어졌는데 그것의 효과를 보는 것 같습니다.

랜덤 포레스트

  • PCA를 먼저 적용한 후 해당 기법으로 차원축소를 한 경우는 해당 기법만으로 차원 축소를 한 경우보다 성능이 좋지 않았습니다.
  • 따라서 PCA기법을 먼저 적용한 경우는 제외하겠습니다.
  • 차원축소에 따른 분류기 성능을 보기 위함 입니다.

원본데이터(차원축소X)

원본 데이터에 대한 성능은 위에서 측정하였기에 그 값만 기억하겠습니다.

  • 원본 데이터에 대한 랜덤 포레스트 모델 성능 : 약 85.8%

PCA

3장에서 데이터를 모두 차원축소 시켰고 그 결과를 가지고 있으므로 바로 이용하겠습니다.

  • X_pca_reduced3 : PCA기법으로 차원을 3차원으로 축소한 데이터입니다.

먼저 데이터를 훈련세트와 테스트 세트로 분류하겠습니다.

from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(X_pca_reduced3, y, test_size=0.2, random_state=42)

랜덤 포레스트 모델을 훈련시킵니다.

훈련 후 바로 정확도 성능을 확인해보겠습니다.

rnd_clf.fit(X_train, y_train)

y_pred = rnd_clf.predict(X_test)
accuracy_score(y_test, y_pred)
0.4715

약 47.1%로 성능이 저하가 많이 일어났습니다.

LLE

  • X_lle_reduced3 : LLE기법을 이용하여 데이터의 차원을 3차원으로 축소한 데이터입니다.

훈련세트와 테스트세트를 분류하겠습니다.

from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(X_lle_reduced3, y, test_size=0.2, random_state=42)

랜덤포레스트 모델을 훈련시킵니다.

훈련 후 바로 정확도 성능을 확인해보겠습니다.

rnd_clf.fit(X_train, y_train)

y_pred = rnd_clf.predict(X_test)
accuracy_score(y_test, y_pred)
0.855

이번엔 약 85.5%로 원본데이터와 성능 차이가 거의 없습니다. 약 0.3% 떨어집니다.

MDS

  • X_mds_reduced3 : MDS기법을 이용하여 데이터의 차원을 3차원으로 축소한 데이터입니다.
  • MDS를 이용할 때 시간상의 이유로 데이터를 2000개만 썼으므로 레이블도 2000개만 사용합니다.

훈련세트와 테스트세트를 분류하겠습니다.

from sklearn.model_selection import train_test_split

y_mds = y[:m]

X_train, X_test, y_train, y_test = train_test_split(X_mds_reduced3, y_mds, test_size=0.2, random_state=42)

랜덤 포레스트 모델을 훈련시킵니다.

훈련 후 바로 정확도 성능을 확인해보겠습니다.

rnd_clf.fit(X_train, y_train)

y_pred = rnd_clf.predict(X_test)
accuracy_score(y_test, y_pred)
0.575

이번에는 57.5%로 원본 데이터에 비해 상당히 떨어지는 것이 확인됩니다.

LDA

  • X_lda_reduced3 : LDA기법을 이용하여 데이터의 차원을 3차원으로 축소한 데이터입니다.

훈련세트와 테스트세트를 분류하겠습니다.

from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(X_lda_reduced3, y, test_size=0.2, random_state=42)

랜덤포레스트 모델을 훈련시킵니다.

훈련 후 바로 정확도 성능을 확인해보겠습니다.

rnd_clf.fit(X_train, y_train)

y_pred = rnd_clf.predict(X_test)
accuracy_score(y_test, y_pred)
0.7535

이번엔 약 75.3%로 MDS보다는 좋아졌지만 그래도 원본 데이터에 비해 성능이 약 10% 가량 좋지 않습니다.

t-SNE

  • X_tsne_reduced3 : t-SNE기법을 이용하여 데이터의 차원을 3차원으로 축소한 데이터입니다.

훈련세트와 테스트세트를 분류하겠습니다.

from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(X_tsne_reduced3, y, test_size=0.2, random_state=42)

랜덤 포레스트 모델을 훈련시킵니다.

훈련 후 바로 정확도 성능을 확인해보겠습니다.

rnd_clf.fit(X_train, y_train)

y_pred = rnd_clf.predict(X_test)
accuracy_score(y_test, y_pred)
0.924

약 92.4%로 여태까지 한 차원 축소들 중에서는 가장 좋은 성능을 보이는 뿐만 아니라 원본데이터를 이용했을 때보다 성능이 더 높게 나왔습니다.

위에서 시각화 하였을 때도 t-SNE가 다른 차원 축소들보다 잘 군집이 나누어졌는데 그것의 효과를 보는 것 같습니다.

최종 성능 비교

  • 원본데이터와 2차원축소, 3차원 축소
  • 선형 SVC와 랜덤 포레스트

이 기준들에 따라 성능을 보겠습니다.

1. 선형 SVC


원본 데이터 : 86.2 %

  • (2차원 일 때 - 3차원 일 때)
  • PCA : 18.35 % , 18.95 % (3차원 성능 좋음)
  • LLE : 40.95 % , 49.95 % (3차원 성능 좋음)
  • MDS : 12.50 % , 9.25 % (2차원 성능 좋음)
  • LDA : 38.60 % , 59.2 % (3차원 성능 좋음)
  • t-SNE : 62.3 % , 82.55 % (3차원 성능 좋음)

    성능 순

  • 2차원 : t-SNE , LLE , LDA , PCA , MDS
  • 3차원 : t-SNE , LDA , LLE , PCA , MDS (LDA와 LLE 뒤바뀜)

    결론

    1. 원본 데이터의 경우에 비해 모든 경우 성능 감소
    2. 일반적으로 차원이 높을수록 더 좋은 성능을 가진다.(MDS경우가 예외에 해당)
    3. t-SNE가 다른 것에 비해 눈에 띄게 성능이 좋았는데, 그 원인은 시각화에서 보았듯이 다른 것에 비해서 군집이 비교적 상당히 잘 되는 것과 관련이 있다고 판단된다.

      선형 SVC는 즉 데이터의 정보를 더 많이 보존할 수록 성능은 더 좋게 나온다고 판단된다.

2. 랜덤 포레스트


원본 데이터 : 85.85 %

  • (2차원 일 때 - 3차원 일 때)
  • PCA : 45.25 % , 47.15 % (3차원 성능 좋음)
  • LLE : 84.60 % , 85.50 % (3차원 성능 좋음)
  • MDS : 48.50 % , 57.50 % (3차원 성능 좋음)
  • LDA : 58.85 % , 75.35 % (3차원 성능 좋음)
  • t-SNE : 91.40 % , 92.40 % (3차원 성능 좋음)

    성능 순

  • 2차원 : t-SNE , LLE , LDA , MDS , PCA
  • 3차원 : t-SNE , LLE , LDA , MDS , PCA

    결론

    1. 일부의 경우 원본 데이터의 경우에 비해 성능이 더 향상된다.(t-SNE)
    2. 일반적으로 차원이 높을수록 더 좋은 성능을 가진다.
      1. t-SNE가 다른 것에 비해 눈에 띄게 성능이 좋았는데 심지어 원본 데이터보다 좋았는데, 그 원인은 시각화에서 보았듯이 다른 것에 비해서 군집이 비교적 상당히 잘 되는 것과 관련이 있다고 판단된다.

        랜덤포레스트는 노드를 나눌 때 특성을 하나만 사용하므로 반드시 많은 특성을 가지는 것이 성능이 좋지만은 않다. 적절하게 줄여 준다면 오히려 더 좋은 성능을 보인다.

Updated: