#!/usr/bin/env python3


1. PCA -- eigen face


PCA는 원본 데이터 표현보다 분석하기에 더 적합한 표현을 찾을 수 있으리란 생각에서 출발

이미지는 RGB의 강도가 기록된 픽셀로 구성

PCA를 이용하여 LFW(Labeled Faces in the Wild) 데이터셋의 이미지에서 특성을 추출


# library import

from sklearn.datasets import fetch_lfw_people # fetch_lfw_people library

import matplotlib.pyplot as plt

import matplotlib

import numpy as np


# matplotlib 설정

matplotlib.rc('font', family='AppleGothic'# 한글출력

plt.rcParams['axes.unicode_minus'] = False # 축 - 표시


people = fetch_lfw_people(min_faces_per_person=20, resize=0.7, color=False# 추출된 사진의 서로 다른 얼굴의 수, 사진 비율, 흑백여부

image_shape = people.images[0].shape # people객체 image의 첫번째 원소의 모양

print('people.images의 형태 \n{}'.format(people.images.shape)) # people객체의 image 형태: (3023, 87, 65)

print('class 갯수 \n{}'.format(len(people.target_names))) # people객체의 class 갯수, 62


fig, axes = plt.subplots(2, 5, # figure객체와 2x5의 plot객체를 각각 할당

                         subplot_kw={'xticks': (), 'yticks': ()}) # subplot의 축 설정; x축 눈굼없게, y축 눈금없게


# axes.ravel() : 리스트를 1차원으로

for target, image, ax in zip(people.target, people.images, axes.ravel()): # people.target, people.images, axes.ravel()에서 하나씩 원소 할당

    ax.imshow(image) # imshow로 그림 출력

    ax.set_title(people.target_names[target]) # 각 subplot의 타이틀

plt.gray() # 그림 흑백

plt.show() # 그래프 출력

LFW 데이터셋에 있는 이미지의 샘플



1 -1 people 객체 분석

# 각 target이 나타난 횟수 계산

counts = np.bincount(people.target) # people.target의 빈도 계산


# target별 이름과 횟수 출력

### enumerate() : 각 원소에 인덱스 부여

### print('{0:25}, {1:3}').format(var1, var2):  첫번째 {}에 var1과 25자리까지, 두번째{}에 var2와 3자리를 부여

### print({0!s}.format(var1)): print문에 전달된 형식이 숫자라도 문자로 처리

print('frequency')

for i, (count, name) in enumerate(zip(counts, people.target_names)):

    print('{0:25} {1:3}'.format(name, count), end= '\t'# name에서 25자리, count에서 3자리, 끝은 탭

    if (i + 1) % 3 == 0: # 3의 배수이면, 즉 4번째 원소부터

        print() # 개행처리


# Geoge W Bush와 Colin Powell의 이미지가 많음을 확인


### 데이터셋의 편중을 막기 위해 50개의 이미지만 선택

mask = np.zeros(people.target.shape, dtype=np.bool) # 3023개의 boolean타입 False 생성


people_unique = np.unique(people.target) # 중복된 값 제외

for target in people_unique: # 중복을 제거한 target리스트에서 한개의 원소 선택

# people.target(3023개의 리스트)중 선택된 원소와 같은 것만 출력 ==> [0] 리스트의 원소로 접근 ==> False의 갯수 50개까지 출력

# 이 논리 값을 mask의 인덱스로 사용 후 True로 변환

    mask[np.where(people.target == target)[0][:50]] = 1 

x_people = people.data[mask] # 훈련 데이터 생성

y_people = people.target[mask] # 테스트 데이터 생성


# 전처리 메소드 import

from sklearn.preprocessing import MinMaxScaler


scaler = MinMaxScaler()

x_people_scaled = scaler.fit_transform(x_people) # 전처리 메소드 적용


# 머신 러닝 library import

from sklearn.neighbors import KNeighborsClassifier

from sklearn.model_selection import train_test_split


# 전처리한 데이터를 분할

x_train, x_test, y_train, y_test = \

  train_test_split(x_people_scaled, y_people, # 분할할 데이터

                   stratify=y_people, random_state=0) # 그룹화할 데이터, 랜덤상태


# 머신 러닝 라이브러리 import

knn = KNeighborsClassifier(n_neighbors=1) # 이웃의 수

knn.fit(x_train, y_train) # 모델 학습


print('knn.score(x_test, y_test) \n최근접이웃의 일반화 세트 점수: {:.3f}'.format(

    knn.score(x_test, y_test))) # 0.248

정확도가 24.8%, 무작위로 분류하는 정확도는 1/62 = 1.6%


얼굴의 유사도를 측정하기 위해 원본 픽셀 공간에서 거리를 계산하는 것은 비효율적

각 픽셀의 회색톤 값을 다른 이미지에서 동일한 위치에 있는 픽셀 값과 비교. 이런 방식은 사람이 얼굴 이미지를 인식하는 것과는 많이 다르고, 픽셀을 있는 그대로 비교하는 방식으로는 얼굴의 특징을 잡아내기 어려움


2. PCA whitening 분석


픽셀을 비교할 때 얼굴 위치가 한 픽셀만 오른쪽으로 이동해도 큰 차이를 만들어 완전히 다른얼굴로 인식

주성분으로 변환하여 거리를 계산하여 정확도를 높이는 방법을 사용, PCA whitening 옵션을 사용하여 주성분의 스케일이 같아지도록 조정 ==> whitening 옵션 없이 변환 후 StandardScaler를 적용하는 것과 같음


# library import

import mglearn

mglearn.plots.plot_pca_whitening()

plt.show()

whitening옵션을 사용한 PCA 데이터 변환


데이터가 회전하는 것뿐만 아니라 스케일도 조정되어 그래프가 원 모양으로 바뀜


2-1. PCA  머신 러닝

# library import

from sklearn.decomposition import PCA


# PCA 모델 생성 및 적용

pca = PCA(n_components=100, whiten=True, random_state=0) # 주성분 갯수, whitening option, 랜덤상태

pca.fit(x_train) # PCA 학습

x_train_pca = pca.transform(x_train) # PCA를 데이터에 적용

x_test_pca = pca.transform(x_test)


# PCA를 적용한 데이터 형태

print('x_train_pca.shape \ntrain형태:{}'.format(x_train_pca.shape)) # (1547, 100)

print('x_test_pca.shape \ntest형태:{}'.format(x_test_pca.shape)) # (516, 100)


# 머신 러닝 모델 생성 및 학습

knn = KNeighborsClassifier(n_neighbors=1) # 이웃의 수

knn.fit(x_train_pca, y_train) # 모델 학습

print('테스트 세트 정확도: \n{:.3f}'.format(knn.score(x_test_pca, y_test))) # 0.314


모델의 정확도가 23%에서 31%로 상승


이미지 데이터일 경우엔 계산한 주성분을 쉽게 시각화 가능

주성분이 나타내는 것은 입력 데이터 공간에서의 어떤 방향임을 기억

입력 차원이 87 x 65픽셀의 흑백 이미지이고 따라서 주성분또한 87 x 65


print('pca.components_.shape \n{}'.format(pca.components_.shape)) # (100, 5655)


fig, axes = plt.subplots(3, 5, # subplot 3x5를 axes에 할당

                         subplot_kw={'xticks': (), 'yticks': ()}) # subplot 축 설정


for i, (comp, ax) in enumerate(zip(pca.components_, axes.ravel())): # pca.components_와 axes.ravel()을 하나씩 순서대로 할당한 후 인덱스 부여

    ax.imshow(comp.reshape(image_shape)) # image_shape= (87, 65)

    ax.set_title('pricipal component {}'.format(i+1)) # image title

plt.gray() # 사진 흑백

plt.show() # 사진 출력

얼굴 데이터셋의 pricipal component중 처음 15개


첫 번째 주성분은 얼굴과 배경의 명암차이를 기록한 것으로 추정

두번째 주성분은 오른쪽과 왼쪽 조명의 차이를 담고 있는 것으로 보임

이런 방식이 원본 픽셀 값을 사용하는 것보다 더 의미 있지만, 사람이 얼굴을 인식하는 방식과는 거리가 멈

알고리즘이 데이터를 해석하는 방식은 사람의 방식과는 상당히 다름


PCA 모델을 이해하기 위해 몇개의 주성분을 사용해 원본 데이터를 재구성

몇 개의 주성분으로 데이터를 줄이고 원래 공간으로 되돌릴 수 있음

원래 특성 공간으로 되돌리는 작업은 inverse_transform 메소드를 사용


mglearn.plots.plot_pca_faces(x_train, x_test, image_shape) # 훈련데이터, 테스트데이터, 이미지크기(87x65)

plt.gray() # 그림 흑백

plt.show() # 그림 출력

주성분 갯수에 따른 세 얼굴 이미지의 재구성



'python 머신러닝 -- 비지도학습 > PCA(주성분 분석)' 카테고리의 다른 글

PCA  (0) 2018.03.19

#!/usr/bin/env python3


Ridge


Ridge는 linear model이므로 OLS(Ordinary Least Square)를 사용합니다.

Ridge Regression에서 가중치(w) 선택은 추가 제약 조건을 생성하여

가중치(w)의 절댓값을 가능학 작게 만드는 것(0으로 만드는 것이 아님)입니다.


기하학적으로 모든 특성의 기울기를 0에 가깝게 만드는 것이고 이 것을 regularization이라 합니다.

즉 model을 overfitting 하지 않도록 강제로 제한하는 것입니다.


Ridge Regression에 사용하는 regularization을 L2 regularization이라고도 합니다.


보스턴 주택가격으로 Ridge Regression과 linear regression을 사용하여 비교해보겠습니다.

from mglearn.datasets import load_extended_boston

from sklearn.linear_model import Ridge, LinearRegression

from sklearn.model_selection import train_test_split


boston_data, boston_target = load_extended_boston()

x_train, x_test, y_train, y_test = \

  train_test_split(boston_data, boston_target,

                   random_state=0, test_size=0.3)


ridge = Ridge()

ridge.fit(x_train, y_train)

lr = LinearRegression()

lr.fit(x_train, y_train)


print('{:.3f}'.format(ridge.score(x_train, y_train)))

# 0.882

print('{:.3f}'.format(lr.score(x_train, y_train)))

# 0.952

print('{:.3f}'.format(ridge.score(x_test, y_test)))

# 0.783

print('{:.3f}'.format(lr.score(x_test, y_test)))

# 0.645

train set정확도는 Ridge Reg. < Linear Reg.

test set정확도는 Ridge Reg. > Linear Reg. 입니다.


Linear Reg는 train set과 test set의 차이가 많이나므로 overfittng이 되지만

Ridge Reg는 regularization이 적용되기 때문에 train set과 test set의 차이가 적습니다.

따라서 model의 complexity가 낮아지게 되고 test set의 정확도는 상승합니다.



다음으로 Ridge의 Regularization에 대해서 알아보겠습니다.

Ridge Reg.는 alpha parameter로 model을 얼마나 단순화할지를 결정합니다.

default 값은 1이며 높을수록 Regularization을 강화하여 계수를 0에 가깝게 만듭니다.


alpha값에 따른 정확도비교는 아래코드로 확인할 수 있습니다.

alpha_train_score = []

alpha_test_score = []

alpha_set = [0.1, 1 ,10]


for i in alpha_set:

    ridge=Ridge(alpha=i)

    ridge.fit(x_train, y_train)


    ridge_tr_score = round(ridge.score(x_train, y_train), 3)

    ridge_te_score = round(ridge.score(x_test, y_test), 3)


    alpha_train_score.append(ridge_tr_score)

    alpha_test_score.append(ridge_te_score)


print(alpha_set)

# [0.1, 1, 10]


print(alpha_train_score)

# [0.927, 0.882, 0.78]


print(alpha_test_score)

# [0.797, 0.783, 0.678]

alpha값이 커질수록(규제가 강화될수록) 정확도는 낮아지는 것을 볼 수 있습니다.



Ridge도 Linear_model이므로 속성(coef_, intercept_)가 존재합니다.

Ridge의 alpha값에 따른 coef_를 조사하면

import numpy as np

import matplotlib.pyplot as plt


n_feature = boston_data.shape[1]

line = np.linspace(0, n_feature, num=n_feature).reshape(-1, 1)


lr = LinearRegression().fit(x_train, y_train)

plt.scatter(line, lr.coef_, marker='s', label='Linear Reg.') # marker = 's'  => square


alpha_set = [0.1, 1 ,10]

marker_set = ['o', '^', 'v']

for i, m in zip(alpha_set, marker_set):

    ridge = Ridge(alpha=i)

    ridge.fit(x_train, y_train)

    plt.scatter(line, ridge.coef_, marker=m, label='alpha={}'.format(i))


plt.ylim(-30, 30)

plt.hlines(y=0, xmin=0, xmax=n_feature)

plt.legend(loc=(0.01, 1.01))

plt.show()

Linar Regression과 몇 가지 alpha 값을 가진 Ridge Regression의 coefficient 비교

x축은 coef_의 원소를 위치대로 나열한 것입니다. 즉 x=0, x=1은 각각 첫번째 특성과 두번째 특성을 나타내는 것입니다.

alpha=10일 때(빨강 역삼각형)은 대부분 y=0에 위치하며

alpha=1(초록 정삼각형)은 alpha=10일 때보다는 약간 퍼진 상태입니다.

alpha=0.1(주황 원)은 매우 크게 확장되었으며

Linear Reg.(파랑 정사각형)은 자유롭게 퍼져있는 것을 확인할 수 있습니다.



이번엔 learning curve(데이터셋의 크기에 따른 모델의 성능 변화)를 알아보겠습니다.

train_ridge_set = []

train_linear_set = []

test_ridge_set = []

test_linear_set = []


for i in test_size_set:

    x_train, x_test, y_train, y_test = \

      train_test_split(boston_data, boston_target,

                       random_state=35, test_size=i)

    ridge = Ridge(alpha=1).fit(x_train, y_train)

    lr = LinearRegression(n_jobs=-1).fit(x_train, y_train) # n_jobs = 사용할 코어의 수, -1은 모든 코어사용


    rid_tr_score = ridge.score(x_train, y_train)

    rid_te_score = ridge.score(x_test, y_test)

    lr_tr_score = lr.score(x_train, y_train)

    lr_te_score = lr.score(x_test, y_test)


    train_ridge_set.append(rid_tr_score)

    train_linear_set.append(lr_tr_score)

    test_ridge_set.append(rid_te_score)

    test_linear_set.append(lr_te_score)


plt.plot(x_ticks, train_ridge_set, c='lightblue', ls='--', label='train ridge'# c = color, ls = linestyle

plt.plot(x_ticks, train_linear_set, c='orange', ls='--',label='train Linear_Reg')

plt.plot(x_ticks, test_ridge_set, c='lightblue', label='test ridge')

plt.plot(x_ticks, test_linear_set, c='orange', label='test Linear_Reg')


plt.legend(loc=(0.01, 1.01))

plt.ylim(0, 1.1)

plt.show()

보스턴 주택가격 데이터셋에 대한 Ridge vs Linear Reg,

train 데이터(점선)가 test 데이터(line)보다 높음을 알 수 있습니다.

Ridge에는 regularization이 적용되므로 Linear Reg보다 낮습니다.


일반화 데이터에서는 Ridge의 점수가 더 높으며, 데이터셋이 작을수록 두드러집니다.

데이터셋의 크기가 작을수록 Linear Reg.는 어떤 것도 학습하지 못합니다.


데이터가 충분히 크면 regularization이 덜 중요해지고(두 모델의 차이가 줄어듭니다.)

Linear_Reg의 경우 데이터셋이 클수록 train 데이터 성능이 감소합니다. 이는 데이터가 많아질수록 overfitting 하기가 어려움을 시사합니다




참고 자료: 

[1]Introduction to Machine Learning with Python, Sarah Guido

'python 머신러닝 -- 지도학습 > Regression' 카테고리의 다른 글

Decision Tree Regressor  (0) 2018.03.14
Lasso  (0) 2018.03.13
LinearRegression  (0) 2018.03.12
k_NN(k-최근접 이웃) Regression  (1) 2018.03.12

+ Recent posts