
머신러닝, Scikit-learn, 실전 머신러닝 문제 실습 (1)
주요 단계는 다음과 같다.
아래의 내용은 1990년 캘리포니아 인구조사 데이터를 기반으로 한 데이터 셋을 이용해 강의 실습에서 진행한 내용
$ export ML_PATH="$HOME/ml" # You can change the path if you prefer
$ mkdir -p $ML_PATH
$ python3 -m pip --version
pip 19.3.1 from [...]/lib/python3.7/site-packages/pip (python 3.7)
$ python3 -m pip install --user -U pip
Collecting pip
[...]
Successfully installed pip-19.3.1
$ python3 -m pip install --user -U virtualenv
Collecting virtualenv
[...]
Successfully installed virtualenv-16.7.6
$ cd $ML_PATH
$ python3 -m virtualenv my_env
Using base prefix '[...]'
New python executable in [...]/ml/my_env/bin/python3
Also creating executable in [...]/ml/my_env/
$ cd $ML_PATH
$ source my_env/bin/activate # on Linux or macOS
$ .\my_env\Scripts\activate # on Windows
$ python3 -m pip install -U jupyter matplotlib numpy pandas scipy scikit-learn
Collecting jupyter
Downloading https://[...]/jupyter-1.0.0-py2.py3-none-any.whl
Collecting matplotlib
[...]
$ python3 -m ipykernel install --user --name=python3
$ jupyter notebook
[...] Serving notebooks from local directory: [...]/ml
[...] The Jupyter Notebook is running at:
[...] http://localhost:8888/?token=60995e108e44ac8d8865a[...]
[...] or http://127.0.0.1:8889/?token=60995e108e44ac8d8865a[...]
[...] Use Control-C to stop this server and shut down all kernels [...]
# Python ≥3.5 is required
import sys
assert sys.version_info >= (3, 5)
# Scikit-Learn ≥0.20 is required
import sklearn
assert sklearn.__version__ >= "0.20"
# Common imports
import numpy as np
import os
# To plot pretty figures
%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)
# Where to save the figures
PROJECT_ROOT_DIR = "."
CHAPTER_ID = "end_to_end_project"
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)
# Ignore useless warnings (see SciPy issue #5998)
import warnings
warnings.filterwarnings(action="ignore", message="^internal gelsd")
import os
import tarfile
import urllib
DOWNLOAD_ROOT = "https://raw.githubusercontent.com/ageron/handson-ml2/master/"
HOUSING_PATH = os.path.join("datasets", "housing")
HOUSING_URL = DOWNLOAD_ROOT + "datasets/housing/housing.tgz"
def fetch_housing_data(housing_url=HOUSING_URL, housing_path=HOUSING_PATH):
if not os.path.isdir(housing_path):
os.makedirs(housing_path)
tgz_path = os.path.join(housing_path, "housing.tgz")
urllib.request.urlretrieve(housing_url, tgz_path)
housing_tgz = tarfile.open(tgz_path)
housing_tgz.extractall(path=housing_path)
housing_tgz.close()
fetch_housing_data를 호출하면 현재 작업공간에 datasets/housing 디렉토리를 만들고 housing.tgz 파일을 내려받고 압축을 풀어 housing.csv 파일을 만든다.
import pandas as pd
def load_housing_data(housing_path=HOUSING_PATH):
csv_path = os.path.join(housing_path, "housing.csv")
return pd.read_csv(csv_path)
# to make this notebook's output identical at every run
np.random.seed(42)
import numpy as np
# For illustration only. Sklearn has train_test_split()
def split_train_test(data, test_ratio):
shuffled_indices = np.random.permutation(len(data))
test_set_size = int(len(data) * test_ratio)
test_indices = shuffled_indices[:test_set_size]
train_indices = shuffled_indices[test_set_size:]
return data.iloc[train_indices], data.iloc[test_indices]
train_set, test_set = split_train_test(housing, 0.2)
from zlib import crc32
def test_set_check(identifier, test_ratio):
return crc32(np.int64(identifier)) & 0xffffffff < test_ratio * 2**32
def split_train_test_by_id(data, test_ratio, id_column):
ids = data[id_column]
in_test_set = ids.apply(lambda id_: test_set_check(id_, test_ratio))
return data.loc[~in_test_set], data.loc[in_test_set]
인덱스를 id로 추가
housing_with_id = housing.reset_index() # adds an `index` column
train_set, test_set = split_train_test_by_id(housing_with_id, 0.2, "index")
housing_with_id["id"] = housing["longitude"] * 1000 + housing["latitude"]
train_set, test_set = split_train_test_by_id(housing_with_id, 0.2, "id")
from sklearn.model_selection import train_test_split
train_set, test_set = train_test_split(housing, test_size=0.2, random_state=42)
# 데이터 복사본 만들기 (훈련데이터를 손상시키지 않기 위해)
housing = strat_train_set.copy()
housing.plot(kind="scatter", x="longitude", y="latitude")
save_fig("bad_visualization_plot")
밀집된 영역 표시 : alpha옵션
housing.plot(kind="scatter", x="longitude", y="latitude", alpha=0.1)
save_fig("better_visualization_plot")
s : 원의 반지름 => 인구
c : 색상 => 가격
housing.plot(kind="scatter", x="longitude", y="latitude", alpha=0.4,
s=housing["population"]/100, label="population", figsize=(10,7),
c="median_house_value", cmap=plt.get_cmap("jet"), colorbar=True,
sharex=False)
plt.legend()
save_fig("housing_prices_scatterplot")
상관관계(Correlations) 관찰하기
corr_matrix = housing.corr()
corr_matrix["median_house_value"].sort_values(ascending=False)
housing["rooms_per_household"] = housing["total_rooms"]/housing["households"]
housing["bedrooms_per_room"] = housing["total_bedrooms"]/housing["total_rooms"]
housing["population_per_household"]=housing["population"]/housing["households"]
corr_matrix = housing.corr()
corr_matrix["median_house_value"].sort_values(ascending=False)
데이터 준비는 데이터 변환(data transformation)과정으로 볼 수 있다.
데이터 수동변환 vs. 자동변환(함수만들기)
누락된 특성(missing features) 다루는 방법들
추정기(estimator) : 데이터셋을 기반으로 모델 파라미터들을 추정하는 객체(e.g.) imputer). 추정자체는 fit() method에 의해서 수행되고 하나의 데이터셋을 매개변수로 전달받음(지도학습의 경우 label을 담고 있는 데이터셋을 추가적인 매개변수로 전달)
변환기(transformer) : (imputer같이) 데이터셋을 변환하는 추정기. 변환은 transform() method가 수행하고 변환된 데이터셋을 반환
예측기(predictor) : 일부 추정기는 주어진 새로운 데이터셋에 대해 예측값을 생성.(e.g.) LinearRegression) 예측기의 predict() method는 새로운 데이터셋을 받아 예측값을 반환하고고 score() method는 예측값에 대한 평가지표를 반환
반드시 구현해야 할 method들
훈련 데이터셋의 RMSE가 이 경우처럼 큰 경우 => 과소적합(under-fitting)
과소적합이 일어나는 이유
모델 평가
(는 번째 행에 해당)
w = 0 + 1 + 22 + ... =
주어진 w에 대한 함수값 와 데이터 사이의 차이
w = w를 최소화시키는 w를 구하는 것이 목표
= 0, 1일 경우, 과소적합한 오차함수를 만들어 내었고, = 9일 경우, 과대적합되었다고 말할 수 있음
과소/과대적합은 모델의 일반화, 새로운 데이터에 관한 문제
-> 새로운 데이터가 들어왔을 때 오차가 클 것
이를 확인하기 위해서는 Test 데이터에 대해 오차를 구해보면 됨
=
이 증가함에 따라 에러가 줄어들다가 9가 되었을 때 Training 데이터에 대해서는 오차가 0이 된 반면, Test 데이터에 대해서는 오차가 갑자기 커짐을 볼 수 있음
-> 과대적합 : Training 데이터와 Test 데이터간의 오차가 크다.
아래는 이 9일 때 값(샘플 수)을 변경 했을 때의 결과이다.
값이 커지면(샘플 수가 많아지면) 점점 근사하게 됨
많은 샘플 수를 확보하지 못했을 때 사용
위의 그림은 값마다의 최적의 파라미터 값이다.
이 커져감에 따라 의 값의 절대값이 커져감
이를 해결하기 위해 규제화를 이용하는데 가장 간단한 규제화의 방법 중 하나는 오차함수에 대입하는 것
새로운 오차함수를 정의한다.
w = w ww
왼쪽은 어느 정도 규제화를 적용한 결과이고, 오른쪽은 기존의 문제와 동일한 경우이다.
값을 너무 과하게 설정하면 역효과가 난다.