์ด๋ฒ ์ธ์ ์์๋ ๋ง๋ก๋ง ๋ฃ๋ ํ๋ จ ์ธํธ์ ํ ์คํธ ์ธํธ๋ก ๋ฐ์ดํฐ ์ ์ ๋ถํ ํ๋ ์์ ์ ํ๋ ๋ฐฉ๋ฒ์ ๋ํด์, ๊ทธ๋ฆฌ๊ณ ํน์ฑ ์ค์ผ์ผ์ ์กฐ์ ํ๋ ๋ฐฉ๋ฒ์ ๋ํด์ ์์๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
1. ๋ฐ์ดํฐ์ ๋๋๊ธฐ
์ด๋ฒ์๋ ์๋ก์ด ๋ฐ์ดํฐ์ธ Wine ์ ์ฌ์ฉํฉ๋๋ค. ๋ถ๊ฝ ๋ฐ์ดํฐ์์ ๋ฒ์ด๋์ ๊ฑธ ์ถํ๋๋ ค์! wine ๋ฐ์ดํฐ๋ UCI ๋จธ์ ๋ฌ๋ ์ ์ฅ์ ์์ ๋ค์ด๋ฐ์ ์ ์์ต๋๋ค. ํ๋ค์ค๋ฅผ ์ด์ฉํด ๋ฐ๋ก ์ฝ์ด๋๋ฆฌ๋ ์ฝ๋๋ ์๋์ ๊ฐ์ต๋๋ค.
df_wine = pd.read_csv('https://archive.ics.uci.edu/'
'ml/machine-learning-databases/wine/wine.data',
header=None)
# UCI ๋จธ์ ๋ฌ๋ ์ ์ฅ์์์ Wine ๋ฐ์ดํฐ์
์ ๋ค์ด๋ก๋ํ ์ ์์ ๋
# df_wine = pd.read_csv('wine.data', header=None)
df_wine.columns = ['Class label', 'Alcohol', 'Malic acid', 'Ash',
'Alcalinity of ash', 'Magnesium', 'Total phenols',
'Flavanoids', 'Nonflavanoid phenols', 'Proanthocyanins',
'Color intensity', 'Hue', 'OD280/OD315 of diluted wines',
'Proline']
print('ํด๋์ค ๋ ์ด๋ธ', np.unique(df_wine['Class label']))
df_wine.head()
์ํ์ 1, 2, 3 ํด๋์ค ์ค ํ๋์ ์ํด ์์ต๋๋ค. ์์ธ ํ์ข ์ด์ฃ .
๋ฐ์ดํฐ๋ฅผ ๋๋ ๋๋ ์ฌ์ดํท๋ฐ์ model_selection ๋ชจ๋์ train_test_split ํจ์๋ก ๋๋คํ๊ฒ ๋๋ ์ ์์ต๋๋ค.
from sklearn.model_selection import train_test_split
X, y = df_wine.iloc[:, 1:].values, df_wine.iloc[:, 0].values
X_train, X_test, y_train, y_test =\
train_test_split(X, y,
test_size=0.3,
random_state=0,
stratify=y)
์ธ๋ฑ์ค 1๋ถํฐ 13๊น์ง๋ฅผ ๋ณ์ X์ ํ ๋นํ๊ณ , ์ฒซ ๋ฒ์งธ ์ด์ ํด๋์ค ๋ ์ด๋ธ์ ๋ณ์ y์ ํ ๋นํด์ค๋๋ค. ๊ทธ๋ฆฌ๊ณ train_test_split ํจ์๋ฅผ ์ฌ์ฉํด ๋ถํ ํฉ๋๋ค. test_size๊ฐ 0.3์ด๋ฏ๋ก ์ ์ฒด ๋ฐ์ดํฐ์ 30%๊ฐ ํ ์คํธ ๋ฐ์ดํฐ๋ก ํ ๋น๋๊ณ ๊ทธ ๋๋จธ์ง๊ฐ ํ๋ จ ์ธํธ๋ก ๋๋์ด์ง๋๋ค. stratify์ y๋ฅผ ์ ๋ฌํ๋ฉด ํ๋ จ๊ณผ ํ ์คํธ ์ธํธ์ ํด๋์ค ๋น์จ์ด ์๋ณธ๊ณผ ๋์ผํ๊ฒ ์ ์ง๋ฉ๋๋ค.
2. ํน์ฑ ์ค์ผ์ผ ๋ง์ถ๊ธฐ
๊ฒฐ์ ํธ๋ฆฌ์ ๋๋ค ํฌ๋ ์คํธ๋ ํน์ฑ ์ค์ผ์ผ ์กฐ์ ์ ๋ํด์ ๊ฑฑ์ ํ ํ์๊ฐ ์์ง๋ง, ๊ฒฝ์ฌํ๊ฐ ์๊ณ ๋ฆฌ์ฆ์์ ๋ณด์ จ๋ฏ ๋๋ถ๋ถ์ ์๊ณ ๋ฆฌ์ฆ๊ณผ ๋จธ์ ๋ฌ๋์ ํน์ฑ ์ค์ผ์ผ์ด ๊ฐ์ ๋ ์ฑ๋ฅ์ด ๋ ์ข์ต๋๋ค.
ํน์ฑ ์ค์ผ์ผ ์กฐ์ ์ ํด์ผํ๋ ์ด์ ๋ฅผ ๊ฐ๋จํ ์๋ฅผ ๋ค์ด์ ์์๋ณผ๊น์? ํน์ฑ ๋ ๊ฐ๊ฐ ์์ ๋ ํ๋๋ 1์์ 10์ ์ค์ผ์ผ์, ํ๋๋ 1์์ 10๋ง์ ์ค์ผ์ผ์ด ์๋ค๋ฉด ์๋ฌ๋ฆฐ์ ์ ๊ณฑ์ค์ฐจํจ์์์ ์ ์ ์๋ฏ์ด ์๊ณ ๋ฆฌ์ฆ์ ๋ ๋ฒ์งธ ํน์ฑ์ ํฐ ์ค์ฐจ์ ๋ง์ถ์ด์ ๊ฐ์ค์น๋ฅผ ์ต์ ํํ๊ฒ ๋๊ฒ ์ฃ .
ํน์ฑ ์ค์ผ์ผ์ ๋ง์ถ๋ ๋ํ์ ์ธ ๋ฐฉ๋ฒ์ ์ ๊ทํ(normalization)์ ํ์คํ(standardization)์ ๋๋ค. ์ ๊ทํ๋ ๋๋ถ๋ถ ํน์ฑ ์ค์ผ์ผ์ 0๊ณผ 1 ์ฌ์ด์ ๋ง์ถฅ๋๋ค. ์ต์-์ต๋ ์ค์ผ์ผ ๋ณํ(min-max scaling)์ ํน๋ณํ ๊ฒฝ์ฐ์ด์ฃ .
์ฌํ x(i)์์ ์๋ก์ด ๊ฐ์ธ x norm์ ๊ณ์ฐํฉ๋๋ค. ์ฌ์ดํท๋ฐ์ ๊ตฌํ๋ ์ค์ผ์ผ ๋ณํ ๊ธฐ๋ฅ์ ์๋ ์ฝ๋์ ๊ฐ์ต๋๋ค.
from sklearn.preprocessing import MinMaxScaler
mms = MinMaxScaler()
X_train_norm = mms.fit_transform(X_train)
X_test_norm = mms.transform(X_test)
์ ๊ทํ๋ ๋ฒ์๊ฐ ์ ํด์ง ๊ฐ์ด ํ์ํ ๋ ์ฐ์ ๋๋ค. ํ์คํ๋ฅผ ์ฌ์ฉํ๋ฉด ํน์ฑ ํ๊ท ์ 0์ผ๋ก ๋ง์ถ๊ณ ํ์ค ํธ์ฐจ๋ฅผ 1๋ก ๋ง๋ค์ด์ ์ ๊ท๋ถํฌ์ ๊ฐ์ ํน์ง์ ๊ฐ์ง๊ฒ ํฉ๋๋ค. ๊ฐ์ค์น๋ฅผ ๋ ์ฝ๊ฒ ํ์ตํ ์ ์๊ฒ ํ๊ธฐ ์ํด์์ ๋๋ค. ๋, ํ์คํ๋ ๋น์ ์์ ์ธ ์์น ์ ๋ณด๊ฐ ์ ์ง๋๊ธฐ ๋๋ฌธ์ ์ต์-์ต๋ ์ค์ผ์ผ ๋ณํ์ ๋นํด ์๊ณ ๋ฆฌ์ฆ์ด ์ด์ํ ์ ๋ณด์ ๋ ๋ฏผ๊ฐํฉ๋๋ค. ์ต์-์ต๋ ์ค์ผ์ผ ๋ณํ์ ์์ฃผ ์์ ๊ฐ์ด๋ ํฐ ๊ฐ์ด ์์ ๋ ๋ค๋ฅธ ์ํ๋ค์ ์ด์ดํ๊ฒ ๋ชจ์๋ฒ๋ฆฌ๊ธฐ ๋๋ฌธ์ด์ฃ .
์ฌ๊ธฐ์ ๋ฎค๋ ํน์ฑ ์ํ์ ํ๊ท ์ด๊ณ ์๊ทธ๋ง๋ ํ์ค ํธ์ฐจ์ ๋๋ค. ๊ทธ๋ฆผ 4์ ํ๋ ํ์คํ์ ์ต์-์ต๋ ์ ๊ทํ์ ์ฐจ์ด๋ฅผ ๋ณด์ฌ์ค๋๋ค.
์ฝ๋๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
#์ต๋์ต์
ex = np.array([0, 1, 2, 3, 4, 5])
print('ํ์คํ:', (ex - ex.mean()) / ex.std())
print('์ ๊ทํ:', (ex - ex.min()) / (ex.max() - ex.min()))
#ํ์คํ
from sklearn.preprocessing import StandardScaler
stdsc = StandardScaler()
X_train_std = stdsc.fit_transform(X_train)
X_test_std = stdsc.transform(X_test)
3. ๋ชจ๋ธ ๋ณต์ก๋ ์ ํ์ ์ํ L1๊ณผ L2 ๊ท์
์ด๋ฒ์๋ ๊ณผ๋์ ํฉ์ ํผํ๊ธฐ ์ํด, ์ผ๋ฐํ ์ค์ฐจ๋ฅผ ๊ฐ์์ํค๊ธฐ ์ํด ํน์ฑ ์ ํ์ ํตํ ์ฐจ์ ์ถ์๋ก ๊ฐ๋จํ ๋ชจ๋ธ์ ๋ง๋๋ ๋ฐฉ๋ฒ์ ๋ํด์ ์์๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
์์ ์ธ์ ์ ์์๋ L2 ๊ท์ (L2 regularization)์ ๊ฐ๋ณ ๊ฐ์ค์น ๊ฐ์ ์ ํํด ๋ชจ๋ธ ๋ณต์ก๋๋ฅผ ์ค์ด๋ ๋ฐฉ๋ฒ์ด๋ผ๋ ๊ฒ์ ๋ํด์ ๊ธฐ์ต๋์๋์? ๊ฐ์ค์น ๋ฒกํฐ w์ L2 ๊ท์ ๋ ๊ทธ๋ฆผ 5์ ๊ฐ์ต๋๋ค.
๋ชจ๋ธ ๋ณต์ก๋๋ฅผ ์ค์ด๋ ๋ค๋ฅธ ๋ฐฉ๋ฒ์ L1 ๊ท์ (L1 regularization)์ ๋๋ค. L1 ๊ท์ ๋ L2 ๊ท์ ์ ๊ฐ์ค์น ์ ๊ณฑ์ ์ ๋๊ฐ์ผ๋ก ๋ฐ๊พผ ๊ฒ์ ๋๋ค. L2์๋ ๋ค๋ฅด๊ฒ L1์ ํฌ์ํ ํน์ฑ ๋ฐฑํฐ๋ฅผ ๋ง๋ค์ด ๋๋ถ๋ถ์ ํน์ฑ ๊ฐ์ค์น๊ฐ 0์ด ๋ฉ๋๋ค.
๋จผ์ , L2 ๊ท์ ์ ๊ธฐํํ์ ์ธ ํด์๋ถํฐ ์์๋ณผ๊น์? L2๊ท์ ๋ ๋น์ฉ ํจ์์ ํจ๋ํฐ๋ฅผ ๋ถ์ฌํด ๊ฐ์ค์น ๊ฐ์ ๋น์ฉํจ์์ ๋ชจ๋ธ์ ๋นํด ์๊ฒ ๋ง๋๋ ํจ๊ณผ๋ฅผ ๋ ๋๋ค. ๋ ๊ฐ์ ๊ฐ์ค์น w1๊ณผ w2์ ๋ํ ๋ณผ๋กํ ๋น์ฉํจ์ ๋ฑ๊ณ ์ ์ด ๊ทธ๋ฆผ 6๊ณผ ๊ฐ์ต๋๋ค. ์๋ฌ๋ฆฐ์ ์ ๊ณฑ ์ค์ฐจํฉ ๋น์ฉํจ์๊ฐ ๊ตฌ ๋ชจ์์ด๋ผ ๊ทธ๋ฆฌ๊ธฐ ์ฌ์ธ ๊ฒ๋๋ค.
์ฐ๋ฆฌ์ ๋ชฉํ๋ ๋น์ฉํจ์๊ฐ ์ต์๊ฐ ๋๋ ๊ฐ์ค์น ๊ฐ์ ์ฐพ๋ ๊ฒ์ ๋๋ค. ํ์์ ์ค์ฌ ํฌ์ธํธ๊ฐ ๋๊ฒ ์ฃ . ๊ท์ ๋ ๋ ์์ ๊ฐ์ค์น๋ฅผ ์ป๊ธฐ ์ํ ํจ๋ํฐ๋ผ๊ณ ํ ์ ์์ต๋๋ค. ํฐ ๊ฐ์ค์น๋ฅผ ์ ํํ๋ ๊ฒ์ด์ฃ . ๊ท์ ํ๋ผ๋ฏธํฐ์ธ ๋๋ค๋ก ๊ท์ ์ ๊ฐ๋๋ฅผ ํฌ๊ฒ ํ๋ฉด ๊ฐ์ค์น๋ 0์ ๊ฐ๊น์์ง๊ณ ํ๋ จ ๋ฐ์ดํฐ์ ๋ชจ๋ธ์ด ์์กดํ๋ ์ ๋๊ฐ ๋ฎ์์ ธ ์ค๋ฒํผํ ์ ํผํ ์ ์์ต๋๋ค.
L2 ๊ท์ ํญ์ ํ์ ์์ผ๋ก ํํ๋์ด ์์ต๋๋ค. ๊ฐ์ค์น ๊ฐ์ ํ์ ๊ณต, ์ฆ ๊ท์ ๋ฐ๊นฅ์ ์์ ์ ์์ผ๋ฏ๋ก ๋น์ฉํจ์๊ฐ ์ต์ํ ๋๋ ๊ท์ ํญ์ ๊ฒฝ๊ณ์ ๋์ด๊ฒ ๋๋ ๊ฒ์ด์ฃ . ์ด๊ฒ์ ๋ชจ๋ธ์ ํ์ตํ ๋งํ ์ถฉ๋ถํ ๋ฐ์ดํฐ๊ฐ ์์ ๋ ๋ชจ๋ธ์ ๊ฐ๋จํ๊ฒ ๋ง๋ค์ด ๋ถ์ฐ์ ์ค์ผ ์ ์์ต๋๋ค.
๋ ๋ฒ์งธ๋ L1 ๊ท์ ์ ๋๋ค. L1 ํจ๋ํฐ๋ ๊ฐ์ค์น ์ ๋๊ฐ์ ํฉ์ด๊ธฐ ๋๋ฌธ์ ๋ค์ด์๋ชฌ๋์ ์ ํ ๋ฒ์๋ฅผ ๊ทธ๋ฆด ์ ์์ต๋๋ค. L1 ํญ์ ์ด์ฐจ์์ ๋๋ค. ๊ทธ๋ฆผ 8์ ๋ณผ๊น์?
w1์ด 0์ผ ๋ ๋น์ฉํจ์์ ๋ฑ๊ณ ์ ์ด ๋ค์ด์๋ชฌ๋์ ๋ง๋๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค. L2์ ๋ฌ๋ฆฌ L1์ ๋ค์ด์๋ชฌ๋ ํ์ด๋ผ ์ต์ ์ ์ ์ถ์ ๊ฐ๊น์ธ ํ๋ฅ ์ด ๋๊ณ , ์ด๊ฒ ํฌ์์ฑ์ด ๋ํ๋๋ ์ด์ ์ ๋๋ค. ์ฌ์ดํท๋ฐ์์ L1 ๊ท์ ๋ฅผ ์ง์ํ๋ ๋ชจ๋ธ์ penalty ๋งค๊ฐ๋ณ์๋ฅผ l1์ผ๋ก ์ง์ ํด ํฌ์ํ ๋ชจ๋ธ์ ๋ง๋ค ์ ์์ต๋๋ค.
from sklearn.linear_model import LogisticRegression
LogisticRegression(solver='liblinear', penalty='l1')
์ ์ฒ๋ฆฌ๋ Wine ๋ฐ์ดํฐ์ L1 ๊ท์ ๊ฐ ์๋ ๋ก์ง์คํฑ ํ๊ท๋ ๋ค์๊ณผ ๊ฐ์ด ์ ์ฉํ ์ ์์ต๋๋ค.
from sklearn.linear_model import LogisticRegression
lr = LogisticRegression(solver='liblinear', multi_class='auto',
penalty='l1', C=1.0, random_state=42)
# C=1.0์ด ๊ธฐ๋ณธ๊ฐ
lr.fit(X_train_std, y_train)
print('ํ๋ จ ์ ํ๋:', lr.score(X_train_std, y_train))
print('ํ
์คํธ ์ ํ๋:', lr.score(X_test_std, y_test))
ํ๋ จ๊ณผ ํ ์คํธ ์ ํ๋๊ฐ ๋ชจ๋ 1.0์ผ๋ก 100%์์ ํ์ธํ ์ ์์ฃ ? ๋ชจ๋ธ์ด ์๋ฒฝํ๊ฒ ์๋ํ๋ค๋ ๊ฒ์ ์ ์ ์์ต๋๋ค. lr.intercept_ ์์ฑ์ผ๋ก ์ ํธ์ ํ์ธํด๋ณด๋ฉด ๊ฐ ์ธ ๊ฐ๊ฐ ๋ ๋ฐฐ์ด์ด ๋ฐํ๋ฉ๋๋ค.
slover = 'liblinear', multi_class = 'auto'๋ก ์ด๊ธฐํํ LogisticRegression ๊ฐ์ฒด๋ฅผ ๋ค์ค ํด๋์ค ๋ฐ์ดํฐ์ ์ ์ ์ฉํ๋ฉด OvR ๋ฐฉ์์ ์ฌ์ฉํฉ๋๋ค. ์ฒซ ๋ฒ์งธ๋ ํด๋์ค 1๊ณผ 2, 3์ ๊ตฌ๋ถํ๋ ๋ชจ๋ธ์ ์ํ ๊ฒ์ด๊ณ , ๋ ๋ฒ์งธ๋ ํด๋์ค 2๋ฅผ 1, 3๊ณผ ๊ตฌ๋ถํ๋ ๋ชจ๋ธ์ ์ํ ๊ฒ์ด๋ฉฐ ์ธ ๋ฒ์งธ๋ ํด๋์ค 3์ 1, 2์ ๊ตฌ๋ถํ๋ ๋ชจ๋ธ์ ์ ํธ์ ๋๋ค.
lr.coef_ ์์ฑ์ ๊ฐ์ค์น๋ ํด๋์ค๋ง๋ค ๋ฒกํฐ ํ๋์ฉ ์ธ ๊ฐ์ ํ์ด ์๋ ๊ฐ์ค์น ๋ฐฐ์ด์ ๋๋ค.
๊ฐ ํ์ 13๊ฐ ๊ฐ์ค์น๋ฅผ ๊ฐ์ง๊ณ , ๊ฐ ๊ฐ์ค์น์ 13์ฐจ์์ Wine ๋ฐ์ดํฐ์ ์ ํน์ฑ์ ๊ณฑํด ์ต์ข ์ ๋ ฅ์ ๊ณ์ฐํฉ๋๋ค.
์ด์ ๊ท์ ๊ฐ๋๋ฅผ ๋ฌ๋ฆฌํด ํน์ฑ ๊ฐ์ค์น ๋ณํ๋ฅผ ๊ทธ๋ํ๋ก ๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
import matplotlib.pyplot as plt
fig = plt.figure()
ax = plt.subplot(111)
colors = ['blue', 'green', 'red', 'cyan',
'magenta', 'yellow', 'black',
'pink', 'lightgreen', 'lightblue',
'gray', 'indigo', 'orange']
weights, params = [], []
for c in np.arange(-4., 6.):
lr = LogisticRegression(solver='liblinear', multi_class='auto',
penalty='l1', C=10.**c, random_state=0)
lr.fit(X_train_std, y_train)
weights.append(lr.coef_[1])
params.append(10**c)
weights = np.array(weights)
for column, color in zip(range(weights.shape[1]), colors):
plt.plot(params, weights[:, column],
label=df_wine.columns[column + 1],
color=color)
plt.axhline(0, color='black', linestyle='--', linewidth=3)
plt.xlim([10**(-5), 10**5])
plt.ylabel('weight coefficient')
plt.xlabel('C')
plt.xscale('log')
plt.legend(loc='upper left')
ax.legend(loc='upper center',
bbox_to_anchor=(1.38, 1.03),
ncol=1, fancybox=True)
plt.show()
์ด๋ฒ ์ธ์ ์์๋ ํ๋ จ ์ธํธ์ ํ ์คํธ ์ธํธ๋ก ๋ฐ์ดํฐ๋ฅผ ๋๋๋ ๋ฐฉ๋ฒ, ํน์ฑ ์ค์ผ์ผ์ ๋ง์ถ๋ ๋ฐฉ๋ฒ๊ณผ L1, L2 ๊ท์ ์ ๋ํด ์์๋ณด์์ต๋๋ค. L1, L2 ๊ท์ ๋ ์ ๋ ์ ๋ง ์ด๋ ค์ ๋๋ฐ์, ์ถํ์ ์ ๊ฐ ๋ ์ดํด๋ฅผ ์ํ๊ฒ ๋๋ฉด ์๋ถ๋ถ์ ์ถ๊ฐ์ ์ผ๋ก ์ค๋ช ์ ๋ง๋ถ์ด๋๋ก ํ๊ฒ ์ต๋๋ค(2020.02.13). ์๊ณ ํ์ จ์ต๋๋ค!