์ผ | ์ | ํ | ์ | ๋ชฉ | ๊ธ | ํ |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- backfill
- aws
- mysql
- Dag
- Spark Caching
- redshift
- topic
- disk spill
- spark executor memory
- Speculative Execution
- Spark ์ค์ต
- k8s
- etl
- Spark
- CI/CD
- off heap memory
- DataFrame Hint
- Spark Partitioning
- colab
- SQL
- Spark SQL
- ๋น ๋ฐ์ดํฐ
- Docker
- KDT_TIL
- Kafka
- Kubernetes
- ๋ฐ์ดํฐ ํ์ดํ๋ผ์ธ
- AQE
- Salting
- Airflow
- Today
- Total
JUST DO IT!
jupyter์์ ๋จธ์ ๋ฌ๋ End to End ์ค์ตํด๋ณด๊ธฐ - TIL230717 ๋ณธ๋ฌธ
jupyter์์ ๋จธ์ ๋ฌ๋ End to End ์ค์ตํด๋ณด๊ธฐ - TIL230717
sunhokimDev 2023. 7. 20. 00:56๐ KDT WEEK 16 DAY 1 TIL
- ๋จธ์ ๋ฌ๋ E2E ์ค์ต
- 0. ์ค์ต ํ๊ฒฝ ์ค์
- 1. ํ ์คํธ ๋ฐ์ดํฐ์ ๋ง๋ค๊ธฐ
- 2. ๋ฐ์ดํฐ ์ ์
- 3. ๋ชจ๋ธ ํ๋ จ
- 4. ๋ชจ๋ธ ์ธ๋ถ ํ๋
- 5. ํ ์คํธ ๋ฐ์ดํฐ์ ํ๊ฐ
- 6. ์์ฉํ๋ฅผ ์ํ ๋ชจ๋ธ ์ ์ฅ
๐ฅ ๋จธ์ ๋ฌ๋ End to End ์ค์ต
Machine Learning(๊ธฐ๊ณํ์ต) : ๊ฒฝํ์ ํตํด ์๋์ผ๋ก ๊ฐ์ ํ๋ ์ปดํจํฐ ์๊ณ ๋ฆฌ์ฆ ์ฐ๊ตฌ
์บ๋ฆฌํฌ๋์ ์ธ๊ตฌ์กฐ์ฌ ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํด ์บ๋ฆฌํฌ๋์ ์ฃผํ ๊ฐ๊ฒฉ ์์ธก๋ชจ๋ธ ๋ง๋ค๊ธฐ
โ๏ธ 0. ์ค์ต ํ๊ฒฝ ์ค์
virtualenv๋ฅผ ์ฌ์ฉํ์ฌ ๊ฐ์ํ๊ฒฝ์์์ ์์ ํ๋๋ก ํ๋ค.
# ์ํ๋ ํด๋์์์ ์์
pip install virtualenv # ๊ฐ์ํ๊ฒฝ
virtualenv my_env # ์ํ๋ ์ด๋ฆ ์ค์
# ๊ฐ์ํ๊ฒฝ ์คํ
source my_env/bin/activate # on Linux or macOS
.\my_env\Scripts\activate # on Windows
๋์ ๊ฒฝ์ฐ์๋ ์๋์ฐ Powershell์ ํตํด ์์ ํ๋๋ฐ, activate๋ฅผ ์ฌ์ฉํด๋ ๊ฐ์ํ๊ฒฝ์ด ์คํ๋์ง ์์๋ค.
์ด์ ๋ Powershell์ด ๊ธฐ๋ณธ์ ์ผ๋ก ๊ฐ์ํ๊ฒฝ ์คํ์ ๋ฐฉ์งํ๊ธฐ ๋๋ฌธ์ด๋ค.
๋ค์์ ๋ช ๋ น์ด๋ฅผ Powershell์์ ์ฌ์ฉํ๋ฉด ์ด ์ค์ ์ ์ ํ์์์ผ๋ก ๋ฐ๊ฟ์ค ์ ์๋ค.
Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Scope CurrentUser
์ ์์ ์ผ๋ก ๊ฐ์ํ๊ฒฝ์ด ์คํ๋๋ค๋ฉด, (my_env)์ฒ๋ผ ์ค์ ํ ๊ฐ์ํ๊ฒฝ์ด๋ฆ์ผ๋ก ๊ดํธ์์ ๋ค์ด๊ฐ ์ ์๋๋ค.
๊ทธ๋ฆฌ๊ณ ๊ฐ์ํ๊ฒฝ์์ ๋ค์์ ํจํค์ง๋ค์ ์ค์นํ๋ค. ๊ทธ๋ฆฌ๊ณ ์ค์ต์ jupyter์์ ์งํํ๋ค.
python -m pip install -U jupyter matplotlib numpy pandas scipy scikit-learn
# ์ค์น๊ฐ ๋๋๋ฉด jupyter ๋
ธํธ๋ถ ์คํ
jupyter notebook
๋ฐ์ดํฐ์ ์ ์บ๋ฆฌํฌ๋์ ์ธ๊ตฌ์กฐ์ฌ ๋ฐ์ดํฐ๋ฅผ ์ฌ์ฉํ๋ค. (๊ต์ฅํ ์ค๋๋ ๋ฐ์ดํฐ๋ก, ํ์ต์ฉ์ด๋ค)
import pandas as pd
# housing.csv ํ์ผ pandas๋ก ๋ถ๋ฌ์ค๊ธฐ
def load_housing_data(housing_path=HOUSING_PATH):
csv_path = os.path.join(housing_path, "housing.csv")
return pd.read_csv(csv_path)
datasets/housing/housing.csv
์๋์ ๊ฒฝ๋๋ณ ๊ฐ๊ตฌ์ ํ๊ท ๋์ด, ๋ฐฉ์ ๊ฐ์๋ถํฐ ํ๊ท ์์ , ํ๊ท ์ฃผํ ๊ฐ์น๋ฑ์ ์ ์ ์๋ค.
ocean_proximity๋ ํด์๊ฐ์ ๊ฐ๊น์ด์ง ๋ํ๋ด๋ ์ปฌ๋ผ์ด๋ค.
๐๏ธ 1. ํ ์คํธ ๋ฐ์ดํฐ์ ๋ง๋ค๊ธฐ
์ข์ ๋ชจ๋ธ์ ๋ง๋ค๊ธฐ ์ํด์๋ ํ๋ จ์ ์ฌ์ฉ๋์ง ์๊ณ ๋ชจ๋ธ ํ๊ฐ๋ง์ ์ํ ํ ์คํธ ๋ฐ์ดํฐ์ ์ ๊ตฌ๋ถํ๋ ๊ฒ์ด ์ข๋ค.
import numpy as np
np.random.seed(42) # ๋๋ค ํ
์คํธ ์๋ ์์ฑ
# ๋ฐ์ดํฐ์ ํ
์คํธ ๋น์จ์ ์
๋ ฅ๋ฐ์ ํ
์คํธ ๋ฐ์ดํฐ์
์์ฑ
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]
# housing ๋ฐ์ดํฐ๋ฅผ 20ํผ์ผํธ ๋น์จ๋ก ํ
์คํฐ ๋ฐ์ดํฐ์
์์ฑ
# housing์ csvํ์ผ์ pandas.read_csv๋ก ๋ถ๋ฌ์จ ํํ์ ๋ฐ์ดํฐ
train_set, test_set = split_train_test(housing, 0.2)
or
sklearn์์ ์ ๊ณตํ๋ ๋ถํ ํจ์ ์ฌ์ฉ
from sklearn.model_selection import train_test_split
train_set, test_set = train_test_split(housing, test_size=0.2, random_state=42)
์ฌ๊ธฐ์ ๊ณ์ธต์ ์ํ๋ง์ ํด์ฃผ๋ ๊ฒ์ด ํ ์คํธ ๋ฐ์ดํฐ๊ฐ ์ ์ฒด ๋ฐ์ดํฐ๋ฅผ ๋ํํ๊ธฐ์ ์ข๋ค.
์ด ๊ฒฝ์ฐ์๋ sklearn์์ ์ ๊ณตํ๋ StratifiedShuffleSplit์ ์ฌ์ฉํ๋ค.
from sklearn.model_selection import StratifiedShuffleSplit
split = StratifiedShuffleSplit(n_splits=1, test_size=0.2, random_state=42)
for train_index, test_index in split.split(housing, housing["income_cat"]):
strat_train_set = housing.loc[train_index]
strat_test_set = housing.loc[test_index]
์ด์ ํ๋ จ ๋ฐ์ดํฐ ์ ์ strat_train_set์ ์ฌ์ฉํ๊ณ , ํ ์คํธ์ ์ strat_test_set์ ์ฌ์ฉํ๋ค.
๐ช 2. ๋ฐ์ดํฐ ์ ์
1) ๋๋ฝ๋ ํน์ฑ(missing features) ๋ค๋ฃจ๊ธฐ
- ํด๋น ๊ตฌ์ญ์ ์ ๊ฑฐ(ํ์ ์ ๊ฑฐ)
- ํด๋น ํน์ฑ์ ์ ๊ฑฐ(์ด์ ์ ๊ฑฐ)
- ์ด๋ค ๊ฐ์ผ๋ก ์ฑ์ฐ๊ธฐ(0, ํ๊ท , ์ค๊ฐ๊ฐ ๋ฑ)
ํ๋ จ์๋ ๊ฐ์ด ์ฑ์์ง๋ ๊ฒ์ด ์ข์ผ๋ ๋ฐ์ดํฐ์ ํน์ฑ์ ๋ฐ๋ผ ์ ์ ํ๊ฒ ์ฑ์์ผ๋ง ํ๋ค.
์ ๊ทธ ๋ฐ์ดํฐ๊ฐ ๋๋ฝ๋ฌ๋์ง๋ฅผ ํ์ ํด์ผ ์ ์ ํ ๊ฐ์ ์ฑ์ธ ์ ์์ ๊ฒ์ด๋ค.
๋จผ์ , ํ๋ จ ๋ฐ์ดํฐ์ ์ ๋ผ๋ฒจ์ ๋ฐ๋ก ๋ณต์ฌํด๋๋ค.
housing = strat_train_set.drop("median_house_value", axis=1) # drop labels for training set
housing_labels = strat_train_set["median_house_value"].copy()
๊ฐ์ ๋๋ฝ ํ์ธ
sample_incomplete_rows = housing[housing.isnull().any(axis=1)].head() # True if there is a null feature
sample_incomplete_rows
total_bedrooms ํ์ ๊ฐ์ด ๋๋ฝ๋ ๋ฐ์ดํฐ๊ฐ ๋ณด์ธ๋ค.
์ด ๋ฐ์ดํฐ์ ์ ์ ๋ฅผ ์ํด ์๊น์ ์ค๋ช ํ ์ธ ๊ฐ์ง ๋ฐฉ๋ฒ์ ์ฌ์ฉํด๋ณด์.
sample_incomplete_rows.dropna(subset=["total_bedrooms"]) # total_bedrooms๊ฐ ๋๋ฝ๋ ํ ์ ๊ฑฐ
sample_incomplete_rows.drop("total_bedrooms", axis=1) # total_bedrooms ํ ์์ฒด๋ฅผ ์ ๊ฑฐ
# total_bedrooms๊ฐ ๋๋ฝ๋์ง ์์ ๊ฐ๋ค ์ค์์ ์ค๊ฐ ๊ฐ์ ๊ณ์ฐํ์ฌ ์ฑ์๋ฃ๊ธฐ
# .fillna๋ฅผ ์ฌ์ฉํ๋ฉด ๋๋ฝ๋ ๊ฐ์ ํด๋น ๊ฐ์ด ์ฑ์์ง๋ค.
median = housing["total_bedrooms"].median()
sample_incomplete_rows["total_bedrooms"].fillna(median, inplace=True)
sklearn์ด ์ ๊ณตํ๋ SimpleImputer ์ฌ์ฉํ๊ธฐ
from sklearn.impute import SimpleImputer
imputer = SimpleImputer(strategy="median")
# ์ค๊ฐ๊ฐ์ ์์นํ ํน์ฑ์์๋ง ๊ณ์ฐ๋ ์ ์๊ธฐ ๋๋ฌธ์ ํ
์คํธ ํน์ฑ์ ์ ์ธํ ๋ณต์ฌ๋ณธ์ ์์ฑ
housing_num = housing.drop("ocean_proximity", axis=1)
imputer.fit(housing_num) # .fit ํจ์๋ก ์ธ์๋ก ๋ฃ์ ๋ฐ์ดํฐ์ ์ค์ ๊ฐ(median)์ด imputer์ ๋ค์ด๊ฐ๋ค.
X = imputer.transform(housing_num) # ๋๋ฝ๋ ๊ฐ ์ฑ์๋ฃ๊ธฐ, X๋ NumPy array๊ฐ ๋๋ค.
housing_tr = pd.DataFrame(X, columns=housing_num.columns, index=housing.index) # pandas DataFrame์ผ๋ก ๋๋๋ฆฌ๊ธฐ
๊ฒฐ๊ณผ
์ด๋ฐ ์ซ์ํ ๋ฐ์ดํฐ๋ ์ด๋ ๊ฒ ๋ค๋ฃจ๋ฉด ๋์ง๋ง, ํ ์คํธ์ ๋ฒ์ฃผํ ๋ฐ์ดํฐ๋ ์ด๋ป๊ฒ ๋ค๋ฃจ๊ณ ํ์ต์์ผ์ผํ ๊น?
2) ํ ์คํธ์ ๋ฒ์ฃผํ ๋ฐ์ดํฐ ๋ค๋ฃจ๊ธฐ
๋ชจ๋์ ์ฌ์ฉํ์ฌ ๊ฐ๋จํ๊ฒ ํ ์คํธ๋ฅผ ์ซ์ํํ๋ก ๋ฐ๊ฟ ์ ์๋ค.
from sklearn.preprocessing import OrdinalEncoder
ordinal_encoder = OrdinalEncoder()
housing_cat_encoded = ordinal_encoder.fit_transform(housing_cat) # fit_transform ํจ์๋ ๊ฐ๊ฐ์ ํ
์คํธ๋ฅผ ์ซ์๋ก ๋งคํํ๊ณ ๋ณํํ๋ค.
housing_cat_encoded[:10]
๊ฒฐ๊ณผ
ํ์ง๋ง ๋จ์ํ ๋ฐฐ์ด๋ก ๋ํ๋ด์ ํด๋นํ๋ ์์๋ฅผ ๋ฃ์์ ๋ฟ์ด๋ค.
๋ชจ๋ธ์ด ๋ ๋์ ํ์ต์ ํ๋ ค๋ฉด ๋ฐ๋ค์ ๊ฐ๊น์ด ์์น๋ถํฐ ๋์ดํด์ ์ซ์๊ฐ ๋ฎ์์๋ก ๋ฐ๋ค์ ๊ฐ๊น๋ค๋ ์๋ฏธ๋ฅผ ๋ฃ์ผ๋ฉด ์ข์ ๊ฒ ๊ฐ๋ค.
๊ฐ ์นดํ ๊ณ ๋ฆฌ๋ณ๋ก ์ปฌ๋ผ์ผ๋ก ๋๋ ๋ฒ๋ฆฌ๋ ๋ฐฉ๋ฒ๋ ์๋ค. (One-hot encoding)
from sklearn.preprocessing import OneHotEncoder
cat_encoder = OneHotEncoder()
housing_cat_1hot = cat_encoder.fit_transform(housing_cat)
housing_cat_1hot.toarray()
๋ชจ๋ธ์๊ฒ๋ ํ๋ผ๋ฏธํฐ๋ฅผ ์ฌ๋ฌ ๊ฐ ์ฃผ๋ ๊ฒ์ด ํ์ต์ ์ข๋ค๊ณ ํ๋, ์ด๋ฌํ ๋ฐฉ๋ฒ๋ ์ข์ ๊ฒ ๊ฐ๋ค.
3) ๋๋ง์ ๋ณํ๊ธฐ(Custom Transformer)๋ก ๋ง๋ค๊ธฐ
sklearn์ด ์ ๊ณตํ๋ BaseEstimator, TransformerMixin์ ์ฌ์ฉํด์ ์ปค์คํ ์ผ๋ก ์ ์ํด๋ณด์.
๋ณํ๊ธฐ์๋ fit()๊ณผ transform()์ ๊ผญ ๊ตฌํํด์ผํ๋ค.
rooms_per_household, population_per_household ๋ ๊ฐ์ ์๋ก์ด ํน์ฑ์ ๋ฐ์ดํฐ์ ์ ์ถ๊ฐํ๋ฉฐ add_bedrooms_per_room = True๋ก ์ฃผ์ด์ง๋ฉด bedrooms_per_room ํน์ฑ๊น์ง ์ถ๊ฐํ๋๋ก ๊ตฌํํ๋ค.
from sklearn.base import BaseEstimator, TransformerMixin
# column index
rooms_ix, bedrooms_ix, population_ix, households_ix = 3, 4, 5, 6
class CombinedAttributesAdder(BaseEstimator, TransformerMixin):
def __init__(self, add_bedrooms_per_room = True): # no *args or **kargs
self.add_bedrooms_per_room = add_bedrooms_per_room
def fit(self, X, y=None):
return self # nothing else to do
def transform(self, X):
rooms_per_household = X[:, rooms_ix] / X[:, households_ix] # ํด๋น ์ด๋ผ๋ฆฌ ๋๋๊ธฐ > ๊ฐ ์์๋ผ๋ฆฌ ๋๋ ์ง
population_per_household = X[:, population_ix] / X[:, households_ix]
if self.add_bedrooms_per_room:
bedrooms_per_room = X[:, bedrooms_ix] / X[:, rooms_ix]
return np.c_[X, rooms_per_household, population_per_household,
bedrooms_per_room]
else:
return np.c_[X, rooms_per_household, population_per_household]
attr_adder = CombinedAttributesAdder(add_bedrooms_per_room=False)
housing_extra_attribs = attr_adder.transform(housing.values)
์ ๋ ฅ์ด Numpy ํํ(housing.values)๋ก ๋ค์ด๊ฐ์ Numpyํํ๋ก ๋ฆฌํด๋์๊ธฐ ๋๋ฌธ์ DataFrame์ผ๋ก ๋ณํํด์ผ ํ๋ค.
housing_extra_attribs = pd.DataFrame(
housing_extra_attribs,
columns=list(housing.columns)+["rooms_per_household", "population_per_household"],
index=housing.index)
housing_extra_attribs.head()
์ฌ๋ฌ ๊ฐ์ ๋ณํ์ด ์์ฐจ์ ์ผ๋ก ์ด๋ฃจ์ด์ ธ์ผ ํ ๊ฒฝ์ฐ Pipeline class๋ฅผ ์ฌ์ฉํ๋ฉด ํธํ๋ค.
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
# StandardScaler๋ ๊ฐ์ ํ์คํ(ํ๊ท ์ด 0, ๋ถ์ฐ์ด 1)
num_pipeline = Pipeline([
('imputer', SimpleImputer(strategy="median")),
('attribs_adder', CombinedAttributesAdder()),
('std_scaler', StandardScaler()),
])
housing_num_tr = num_pipeline.fit_transform(housing_num)
Pipeline ํน์ฑ์ ๋ค์๊ณผ ๊ฐ๋ค.
- ์ด๋ฆ, ์ถ์ ๊ธฐ ์์ ๋ชฉ๋กํํ๋ก Pipeline์ ๊ตฌํํ๋ค.
- ๋ง์ง๋ง ๋จ๊ณ๋ฅผ ์ ์ธํ๊ณ ๋ชจ๋ ๋ณํ๊ธฐ์ฌ์ผ ํ๋ค.(fit_transform() method๋ฅผ ๊ฐ์ง๊ณ ์์ด์ผ ํจ)
- ํ์ดํ๋ผ์ธ์ fit() method๋ฅผ ํธ์ถํ๋ฉด ๋ชจ๋ ๋ณํ๊ธฐ์ fit_transform() method๋ฅผ ์์๋๋ก ํธ์ถํ๋ฉด์ ํ ๋จ๊ณ์ ์ถ๋ ฅ์ ๋ค์ ๋จ๊ณ์ ์ ๋ ฅ์ผ๋ก ์ ๋ฌํ๊ณ , ๋ง์ง๋ง ๋จ๊ณ์์๋ fit() method๋ง ํธ์ถํ๋ค.
๋ชจ๋ ์ด์ด ์๋ ๊ฐ ์ด๋ง๋ค ๋ค๋ฅธ ํ์ดํ๋ผ์ธ์ ์ ์ฉํ ์๋ ์๋ค.
sklearn์ ColumnTransformer๋ฅผ ์ฌ์ฉํ๋ฉด ๋๋ค.
from sklearn.compose import ColumnTransformer
num_attribs = list(housing_num) # housing_num์ ๋ชจ๋ ํน์ฑ ๋ฆฌ์คํธ๋ฅผ ์ ์ฅ
cat_attribs = ["ocean_proximity"] # ocean_proximity ํน์ฑ๋ง์ ๋ฆฌ์คํธ๋ก ์ ์ฅ
# ์ธ๋ฒ์งธ ์ธ์๋ก ํน์ฑ์ด ๋ด๊ธด ๋ฆฌ์คํธ๋ฅผ ๋๊น์ผ๋ก์จ ๊ฐ ์ด๋ง๋ค ๋ค๋ฅธ Transform ํจ์ ์ ์ฉ ๊ฐ๋ฅ
full_pipeline = ColumnTransformer([
("num", num_pipeline, num_attribs),
("cat", OneHotEncoder(), cat_attribs),
])
housing_prepared = full_pipeline.fit_transform(housing)
๐โ๏ธ 3. ๋ชจ๋ธ ํ๋ จ
1) ์ ํ ํ๊ท ๋ชจ๋ธ
sklearn์ LinearRegression์ ์ฌ์ฉํ๋ฉด ์ฝ๊ฒ ๊ตฌํํ ์ ์๋ค.
from sklearn.linear_model import LinearRegression
lin_reg = LinearRegression()
lin_reg.fit(housing_prepared, housing_labels)
ํ์ต๋ ๋ชจ๋ธ์ w๊ฐ, ์ฆ ์์ธก์ ํ์ํ ์์น๋ฅผ ์ง์ ํ์ธํด ๋ณผ ์๋ ์๋ค.
ํ์ต๋ ๋ชจ๋ธ์ ํ ๋๋ก ๋ช ๊ฐ์ ๋ฐ์ดํฐ๋ฅผ ์์ธก์์ผ ์ผ๋ง๋ ์ ์์ธก๋๋์ง ํ์ธํด๋ณด์.
# ๋ช ๊ฐ์ ์ํ์ ๋ํด ๋ฐ์ดํฐ๋ณํ ๋ฐ ์์ธก์ ํด๋ณด์
some_data = housing.iloc[:5]
some_labels = housing_labels.iloc[:5]
some_data_prepared = full_pipeline.transform(some_data)
# ์ ํ ํ๊ท ๋ชจ๋ธ์ Predict ํจ์๋ฅผ ์ฌ์ฉํด์ ์์ธก
print("Predictions:", lin_reg.predict(some_data_prepared).round(decimals=1))
print("Labels:", list(some_labels)) # ์ ๋ต
์ ์ฒด ๋ฐ์ดํฐ์ ๋ํด ์์ธก๊ฐ์ด ์ผ๋ง๋ ๋ฒ์ด๋ฌ๋์ง ํ์ธํ ์๋ฌ๊ฐ(RMSE)๋ ์ธก์ ํ ์ ์๋ค.
# ํ๊ท ์๋ฌ๊ฐ ๊ณ์ฐ (ํ๋ จ ๋ฐ์ดํฐ์
์ ๋ํด)
from sklearn.metrics import mean_squared_error
housing_predictions = lin_reg.predict(housing_prepared)
lin_mse = mean_squared_error(housing_labels, housing_predictions)
lin_rmse = np.sqrt(lin_mse)
RMSE๊ฐ์ด ํฌ๊ฒ ๋์ค๋ ๊ฒฝ์ฐ, ์ด๋ฅผ ๊ณผ์์ ํฉ์ด๋ผ๊ณ ํ๋ค.
ํน์ฑ๋ค์ด ์ถฉ๋ถํ ์ ๋ณด๋ฅผ ์ ๊ณตํ์ง ๋ชปํ๊ฑฐ๋, ๋ชจ๋ธ์ด ๊ฐ๋ ฅํ์ง ๋ชปํ๋ฉด ์ด๋ฌํ ๊ฒฐ๊ณผ๊ฐ ๋์จ๋ค.
2) DecisionTreeRegressor
์ด๋ฒ์๋ ๋น์ ํ๋ชจ๋ธ์ธ DecisionTreeRegressor ๋ชจ๋ธ์ ์ฌ์ฉํด์ ํ์ต์์ผ๋ณด์.
์ด ๋ชจ๋ธ๋ sklearn์ ์ฌ์ฉํ๋ฉด ๊ฐ๋จํ ์ฝ๋๋ก ํ์ต์ํฌ ์๊ฐ ์๋ค.
from sklearn.tree import DecisionTreeRegressor
tree_reg = DecisionTreeRegressor(random_state=42)
tree_reg.fit(housing_prepared, housing_labels)
์ด๋ฒ์๋ ํ์ต๋ฐ์ดํฐ์ ๋ํด ์๋ฌ๊ฐ์ ์ธก์ ํด๋ณด์.
# ์์ธก
housing_predictions = tree_reg.predict(housing_prepared)
# ์๋ฌ, ํ์ต๋ฐ์ดํฐ์ ๋ํด์๋ ์๋ฌ x
tree_mse = mean_squared_error(housing_labels, housing_predictions)
tree_rmse = np.sqrt(tree_mse)
0์ด ๋์์ง๋ง ์ด๋ ํ์ต๋ฐ์ดํฐ์ ๋ํ ์๋ฌ๊ฐ์ด๊ธฐ ๋๋ฌธ์ ๊ทธ๋ฅ ๋ชจ๋ธ์ด ํ์ต๋ฐ์ดํฐ์ ๋ํด์๋ง ์๋ฒฝํ ์ ์ํ ๊ฒ์ด๋ค.
์ข ๋ ์ ํํ ํ ์คํธ๋ฅผ ์ํด์๋ ํ์ต์ ์ฌ์ฉํ์ง ์์ ํ ์คํธ ๋ฐ์ดํฐ์ ๊ฒ์ฆ์ด๋, ๊ต์ฐจ ๊ฒ์ฆ์ ์ฌ์ฉํ๋ฉด ๋๋ค.
ํ ์คํธ ๋ฐ์ดํฐ์ ๊ฒ์ฆ์ ์์ ๋์ผํ๊ฒ ์ํํ๋ฉด ๋๋ฏ๋ก ํจ์คํ๊ณ , ๊ต์ฐจ ๊ฒ์ฆ์ ํด๋ณด์.
๊ต์ฐจ ๊ฒ์ฆ์ ํ์ต๋ฐ์ดํฐ์ ์ ์ผ๋ถ๋ฅผ ํ์ต์์ ์ ์ธ์ํจ ๋ค ์๋ฌ ๊ฒ์ฆ์ ์ฌ์ฉํ๋ ์์ ์ ๋ฐ๋ณตํ๋ ๋ฐฉ๋ฒ์ด๋ค.
์๋ ๊ทธ๋ฆผ์์๋ ๋งค Iteration๋ง๋ค ๊ฐ๊ธฐ ๋ค๋ฅธ ๋ฐ์ดํฐ 5๋ถ์ 1์ ๊ฒ์ฆ๋ฐ์ดํฐ๋ก ์ฌ์ฉํ์ฌ ์ด๋ค์ ํ๊ท ์๋ฌ๊ฐ์ ๊ณ์ฐํ๋ค.
sklearn์์ ์ ๊ณตํ๋ cross_val_score์ ์ฌ์ฉํ๋ฉด ๊ฐ๋จํ๊ฒ ๊ณ์ฐํ ์ ์๋ค.
cv๊ฐ์ ์กฐ์ ํ์ฌ ๋ฐ์ดํฐ ์กฐ๊ฐ ๊ฐ์(๋ฐ๋ณต ํ์)๋ฅผ ์ง์ ์ ํ๋ฉด ๋๋ค.
# ๊ต์ฐจ๊ฒ์ฆ
# sklearn์ cross_val_score ์ฌ์ฉ, cv๋ก ๋ฐ์ดํฐ ์กฐ๊ฐ ๊ฐ์ ์ ํ๊ธฐ
def display_scores(scores):
print("Scores:", scores)
print("Mean:", scores.mean())
print("Standard deviation:", scores.std())
from sklearn.model_selection import cross_val_score
scores = cross_val_score(tree_reg, housing_prepared, housing_labels, scoring="neg_mean_squared_error", cv=10)
tree_rmse_scores = np.sqrt(-scores)
display_scores(tree_rmse_scores)
๊ต์ฐจ ๊ฒ์ฆ์ ํ๋๋ ์๋ฌ๊ฐ์ด ๊ฝค ํฐ ๊ฐ์ผ๋ก ๋์๋ค.
3) RandomForestPrediction ๋ชจ๋ธ
์ด ๋ชจ๋ธ์ ํธ๋ฆฌ ๊ตฌ์กฐ์ ์์ธก๊ธฐ๋ฅผ ์ฌ๋ฌ ๊ฐ ์ฌ์ฉํ์ฌ ๊ทธ ์์ธก๊ฐ์ ํ๊ท ์ ์ฌ์ฉํ๋ ๋ชจ๋ธ์ด๋ค.
์ผ๋ฐ์ ์ผ๋ก ํ๋์ ํธ๋ฆฌ ๊ตฌ์กฐ๋ฅผ ์ฌ์ฉํ ๋ชจ๋ธ๋ณด๋ค ์ฌ๋ฌ ๊ฐ๋ฅผ ์ฌ์ฉํ ๋ชจ๋ธ์ ์ฑ๋ฅ์ด ๋๋ค๊ณ ํ๋ค.
์ด ๋ชจ๋ธ ๋ํ sklearn์ ์ฌ์ฉํ๋ฉด ๋จ์ํ๊ฒ ๊ตฌํ์ด ๊ฐ๋ฅํ๋ค.
# Tree๊ฐ ์ฌ๋ฌ ๊ฐ์ธ ํํ
from sklearn.ensemble import RandomForestRegressor
# 100๊ฐ์ ํธ๋ฆฌ๋ฅผ ์ฌ์ฉ
forest_reg = RandomForestRegressor(n_estimators=100, random_state=42)
forest_reg.fit(housing_prepared, housing_labels)
๊ทธ๋ฆฌ๊ณ ์ฑ๋ฅ ๊ฒ์ฆ์ ์ํด ๊ต์ฐจ ๊ฒ์ฆ์ ์ํํด๋ณด์๋ค.
์์์ DecisionTreeRegressor ๋ชจ๋ธ์ ๊ต์ฐจ ๊ฒ์ฆํ๋ ์์น(71629)๋ณด๋ค ๋ ์ ๊ฒ(50435) ๋์๋ค.
๊ทธ๋ ๋ค๋๊ฑด, ๋ ์ข์ ๋ชจ๋ธ์ด๋ผ๊ณ ํ ์ ์๋ ๊ฒ์ด๋ค.
๐ช 4. ๋ชจ๋ธ ์ธ๋ถ ํ๋
1) GridSearhCV
๋ชจ๋ธ์ด ์์น๋ฅผ ์กฐ์ ํ๋ ๊ฒ์ด ์๋๋ผ, ์ฌ๋์ด ์ง์ ์์น๋ฅผ ์กฐ์ ํ์ฌ ๋ชจ๋ธ์ ์ฑ๋ฅ์ ์ฌ๋ฆด ์๋ ์๋ค.
์ด๋, ์ฌ๋์ด ์ง์ ์ธํ ํ ๊ฐ์ ํ์ดํผํ๋ผ๋ฏธํฐ๋ผ๊ณ ํ๋ค.
ํ์ง๋ง ์ฌ๋ฌ ๊ฐ์ ์์น๋ฅผ ๋งค๋ฒ ์กฐ์ ํ์ฌ ๋ชจ๋ธ์ ํ์ต์ํค๊ธฐ์๋ ๊ต์ฅํ ๋ ธ๋ ฅ์ด ํ์ํ ๊ฒ์ด๋ค.
์ด๋ฌํ ์๊ณ ๋ฅผ ๋์ด์ฃผ๋ ๊ธฐ๋ฅ๋ sklearn์ GridSearchCV์ ์ฌ์ฉํ๋ฉด ์ฝ๋ค.
# ํ์ดํผํ๋ผ๋ฏธํฐ ํ๋
# sklearn์ GridSearchCV์ ์ฌ์ฉํ๋ฉด ํ์ดํผํ๋ผ๋ฏธํฐ ์กฐํฉ์ ๋ชจ๋ธ์ ์ ๋ฌํด์ฃผ์ด ์์์ ํ์ดํผํ๋ผ๋ฏธํฐ ํ๋ํด์ค
from sklearn.model_selection import GridSearchCV
param_grid = [
# try 12 (3×4) combinations of hyperparameters
{'n_estimators': [3, 10, 30], 'max_features': [2, 4, 6, 8]},
# then try 6 (2×3) combinations with bootstrap set as False
{'bootstrap': [False], 'n_estimators': [3, 10], 'max_features': [2, 3, 4]},
]
# ์๊น ์ฌ์ฉํ RandomForestRegressor ๋ชจ๋ธ๊ณผ ๋น๊ต๋ฅผ ์ํด ๋์ผํ ์์น
forest_reg = RandomForestRegressor(random_state=42)
# ์ค์ ํ ํ๋ผ๋ฏธํฐ์ ๋ํ ์ฌ๋ฌ ์๋์ ํ์ต๊ณผ, cv=5 ๋งํผ์ ๊ต์ฐจ๊ฒ์ฆ๊น์ง ์ํ
grid_search = GridSearchCV(forest_reg, param_grid, cv=5, scoring='neg_mean_squared_error', return_train_score=True)
grid_search.fit(housing_prepared, housing_labels)
params_grid ๋ฆฌ์คํธ์์ dictionary ๋ณ๋ก ํ๋ผ๋ฏธํฐ๋ฅผ ์กฐํฉํ์ฌ ๋ชจ๋ธ์ ๋ง๋ค์ด๋ณธ๋ค.๋ฐ๋ผ์ ์ฒซ ๋ฒ์งธ dictionary์์ 3x4 = 12(n_estimators ์ x max_features ์)๊ฐ์ ์กฐํฉ์ ๋ง๋ค์ด๋ด๊ณ ,๋ ๋ฒ์งธ dictionary์์ bootstrap = False์ธ ์ํ์์ 2x3 = 6๊ฐ์ ์กฐํฉ์ ๋ง๋ค์ด๋ด์ด,์ด 12+6 = 18๊ฐ์ ๋ชจ๋ธ์ ๋ง๋ค๊ฒ๋๋ค.
๋ํ ๊ฐ ํ๋ผ๋ฏธํฐ๋ณ ๋ชจ๋ธ์ ๊ต์ฐจ ๊ฒ์ฆ๊น์ง ์ํํ์ฌ ์ด๋ค ํ๋ผ๋ฏธํฐ๋ฅผ ๊ฐ์ง ๋ชจ๋ธ์ ์ฑ๋ฅ์ด ์ข์์ง ํ๋จํ๊ฒ ๋๋ค.์ด๋ GridSearchCV ๋ชจ๋ธ์ ์ฌ์ฉํ๋ฉด์ ์ธ์๋ก cv ๊ฐ์ ์ ๋ ฅํ์ฌ ๋ฐ์ดํฐ ์กฐ๊ฐ์ ๊ฐ์๋ฅผ ์กฐ์ ํ ์ ์๋ค.
ํ์ต์ด ์๋ฃ๋์๋ค๋ฉด ๋ฒ ์คํธ ํ๋ผ๋ฏธํฐ๋ฅผ ๋ฝ์๋ณด์.
๋ํ ์ด๋ค ์กฐํฉ์์ ์ด๋ค ์ค์ฝ์ด๊ฐ ๋ํ๋ฌ๋์ง ํ์ธํ ์๋ ์๋ค.
2) Randomized Search
ํ์ดํผํ๋ผ๋ฏธํฐ ์กฐํฉ์ ์๊ฐ ํฐ ๊ฒฝ์ฐ์๋ ์ผ์ ๋ฒ์์์ ํ๋ผ๋ฏธํฐ๋ฅผ ์ง์ ํ ํ์๋งํผ ํ๊ฐํ๋ ๋ฐฉ๋ฒ์ด๋ค.
# ๋๋คํ๊ฒ ํ๋ผ๋ฏธํฐ๋ฅผ ์ค์ ํด์ ํ์ตํ๋๋ก ํจ
# ๋ช ๋ฒ์ ์๋ํ์ ๊ฐ์ฅ ์ข์ ํ๋ผ๋ฏธํฐ ์ฐพ๊ธฐ
from sklearn.model_selection import RandomizedSearchCV
from scipy.stats import randint
param_distribs = {
'n_estimators': randint(low=1, high=200),
'max_features': randint(low=1, high=8),
}
# n_iter๋ ์กฐํฉ์ ์, 10๊ฐ์ ๋๋คํ ์กฐํฉ์ ์๋ํด๋ด
forest_reg = RandomForestRegressor(random_state=42)
rnd_search = RandomizedSearchCV(forest_reg, param_distributions=param_distribs,
n_iter=10, cv=5, scoring='neg_mean_squared_error', random_state=42)
rnd_search.fit(housing_prepared, housing_labels)
๊ทธ๋ฆฌ๊ณ ์ด๋ฒ์๋ ์ด๋ค ์กฐํฉ์์ ์ด๋ค ์ค์ฝ์ด๊ฐ ๋ํ๋ฌ๋์ง ํ์ธํด๋ณด์.
๐ถ๏ธ 5. ํ ์คํธ ๋ฐ์ดํฐ์ ํ๊ฐ
๋ง์ง๋ง์ผ๋ก ํ ์คํธ ๋ฐ์ดํฐ์ ์ผ๋ก ์ต์ข ํ๊ฐ๋ฅผ ํด๋ณด์.
# ๊ฐ์ฅ ์ข์ ๋ชจ๋ธ์ final_model๋ก ์ง์
final_model = grid_search.best_estimator_
# ํ
์คํธ ๋ฐ์ดํฐ์
์ ๋ผ๋ฒจ ์ ๊ฑฐ : X_test
# ํ
์คํธ ๋ฐ์ดํฐ์
์ ์ ๋ต : y_test
X_test = strat_test_set.drop("median_house_value", axis=1)
y_test = strat_test_set["median_house_value"].copy()
# ๋ชจ๋ธ์ ๋ฃ๊ธฐ์ํด ํ์ต๋ฐ์ดํฐ์ ๊ฐ์ด ํ์ดํ๋ผ์ธ์ผ๋ก transform ์์
# transformํ final_model๋ก ์์ธก์์
X_test_prepared = full_pipeline.transform(X_test)
final_predictions = final_model.predict(X_test_prepared)
# ์๋ฌ ๊ณ์ฐ
final_mse = mean_squared_error(y_test, final_predictions)
final_rmse = np.sqrt(final_mse)
๐ฆ 6. ์์ฉํ๋ฅผ ์ํ ๋ชจ๋ธ ์ ์ฅ
์ ์ฒ๋ฆฌ์ ์์ธก์ด ํ๋ฒ์ ๋์ํ ์ ์๋ ํ๋์ ํ์ดํ๋ผ์ธ์ ๋ง๋ค์ด, pkl ํ์ผํํ๋ก ์ ์ฅํ๋ค.
# ์ ์ฒ๋ฆฌ+์์ธก ๋ ๋ค ์๋ ํ๋์ ํ์ดํ๋ผ์ธ ๋ง๋ค๊ธฐ
full_pipeline_with_predictor = Pipeline([
("preparation", full_pipeline),
("linear", LinearRegression())
])
# ์ฌ์ฉ๋ฐฉ๋ฒ
# full_pipeline_with_predictor.fit(housing, housing_labels)
# full_pipeline_with_predictor.predict(some_data)
my_model = full_pipeline_with_predictor
# ๋ชจ๋ธ ํ์ผ ์ ์ฅ
import joblib
joblib.dump(my_model, "my_model.pkl")
# ๋ชจ๋ธ ํ์ผ ์ฌ์ฉ
my_model_loaded = joblib.load("my_model.pkl")
my_model_loaded.predict(some_data)
+) ์๋ก์ด ํน์ฑ์ ๋ฃ์์ ๋, ์ด๋ค ํน์ฑ์ด ์ค์ํ์ง ํ์ ํ ์ ์๋ค.
# ์๋ก์ด ํน์ฑ์ ๋ฃ์์ ๋ ์ด๋ค ํน์ฑ์ด ์ค์ํ์ง ํ์
ํ๊ธฐ
feature_importances = grid_search.best_estimator_.feature_importances_
feature_importances
extra_attribs = ["rooms_per_hhold", "pop_per_hhold", "bedrooms_per_room"]
#cat_encoder = cat_pipeline.named_steps["cat_encoder"] # old solution
cat_encoder = full_pipeline.named_transformers_["cat"]
cat_one_hot_attribs = list(cat_encoder.categories_[0])
attributes = num_attribs + extra_attribs + cat_one_hot_attribs
sorted(zip(feature_importances, attributes), reverse=True)
'TIL' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
๋จธ์ ๋ฌ๋์ ์ํ ํ๋ฅ ๊ธฐ์ด - TIL230719 (0) | 2023.07.24 |
---|---|
๋จธ์ ๋ฌ๋์ ์ํ ๊ธฐ์ด ์ ํ ๋์ ์์๋ณด๊ธฐ - TIL230718 (0) | 2023.07.20 |
Kafka Producer ๋ฐ Consumer ์ค์ตํด๋ณด๊ธฐ with Python (+ksqlDB) - TIL230713 (0) | 2023.07.14 |
Kafka ์์๋ณด๊ณ ์ค์นํด๋ณด๊ธฐ - TIL230712 (0) | 2023.07.14 |
๋น ๋ฐ์ดํฐ์ ์ค์๊ฐ ์ฒ๋ฆฌ -TIL230710 (0) | 2023.07.11 |