수요일!
오늘은 Multinomial Classification을 배운다.
Linear Regression(연속적인 숫자 값 예측)이 발전한 것이 Logistic Regression → Classification(분류를 판단하는 예측)
- Binary Classification(이항분류)
- Multinomial Classification(다항분류)
Logistic Regression은 이진 분류에 특화됨
SKlearn이 제공하는 분류기인 Gradient Descent(경사하강법)가 발전한 형태인 SGD Classifier(Stochastic Gradient Descent, 확률적 경사하강법)
1. Binary Classification - 위스콘신 유방암 데이터 by Gradient Descent Classifier
import numpy as np
from sklearn.datasets import load_breast_cancer
from sklearn import linear_model
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
import warnings
warnings.filterwarnings('ignore')
# Raw Data Set Loading
cancer = load_breast_cancer()
# Data Set
x_data = cancer.data # 2차원 ndarray 독립변수(feature)
t_data = cancer.target # 1차원 ndarray 종속변수(label)
train_x_data, test_x_data, train_t_data, test_t_data = \
train_test_split(x_data, t_data, test_size=0.3, random_state=2, stratify=t_data) # stratify=t_data는 데이터가 편향되는 것을 방지함
# Model 생성
model = linear_model.LogisticRegression()
# Model 학습
model.fit(train_x_data, train_t_data)
# Accuracy로 Model 평가
test_score = model.score(test_x_data, test_t_data)
print('Logistic Regression Model의 정확도 : {}'.format(test_score)) # 0.9473684210526315
2. Binary Classification - 위스콘신 유방암 데이터 by SGD Classifier Ver. 1(정규화 안 함)
import numpy as np
from sklearn.datasets import load_breast_cancer
from sklearn import linear_model
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
import warnings
warnings.filterwarnings('ignore')
# Raw Data Set Loading
cancer = load_breast_cancer()
# Data Set
x_data = cancer.data
t_data = cancer.target
train_x_data, test_x_data, train_t_data, test_t_data = \
train_test_split(x_data, t_data, test_size=0.3, random_state=2, stratify=t_data)
# Model 생성
sgd = linear_model.SGDClassifier(loss='log', # loss='log'는 Logistic Regression을 이용해 Binary Classification 하겠다.
tol=1e-5, # log loss가 1e-5이면 반복을 멈춤
random_state=2)
# Model 학습
sgd.fit(train_x_data, train_t_data)
# Accuracy로 Model 평가
test_score = sgd.score(test_x_data, test_t_data)
print('SGD Classifier의 정확도 : {}'.format(test_score)) # 0.8947368421052632. 정규화를 안 했기 때문에 낮음
3. Binary Classification - 위스콘신 유방암 데이터 by SGD Classifier Ver. 2(정규화)
import numpy as np
from sklearn.datasets import load_breast_cancer
from sklearn import linear_model
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
import warnings
warnings.filterwarnings('ignore')
# Raw Data Set Loading
cancer = load_breast_cancer()
# Data Set
x_data = cancer.data
t_data = cancer.target
train_x_data, test_x_data, train_t_data, test_t_data = \
train_test_split(x_data, t_data, test_size=0.3, random_state=2, stratify=t_data)
# Data 정규화
scaler = StandardScaler()
scaler.fit(train_x_data)
# Model 생성
sgd = linear_model.SGDClassifier(loss='log', # loss='log'는 Logistic Regression을 이용해 Binary Classification 하겠다.
tol=1e-5, # log loss가 1e-5이면 반복을 멈춤
random_state=2)
# Model 학습
sgd.fit(scaler.transform(train_x_data), train_t_data)
# Accuracy로 Model 평가
test_score = sgd.score(scaler.transform(test_x_data), test_t_data)
print('정규화를 이용한 SGD Classifier의 정확도 : {}'.format(test_score)) # 0.9649122807017544. 정규화를 함
4. Binary Classification - 위스콘신 유방암 데이터 by SGD Classifier Ver. 3(정규화 + L2 규제)
Over-fitting(과대 적합) 방지하기 위해 Regularization 적용
import numpy as np
from sklearn.datasets import load_breast_cancer
from sklearn import linear_model
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
import warnings
warnings.filterwarnings('ignore')
# Raw Data Set Loading
cancer = load_breast_cancer()
# Data Set
x_data = cancer.data
t_data = cancer.target
train_x_data, test_x_data, train_t_data, test_t_data = \
train_test_split(x_data, t_data, test_size=0.3, random_state=2, stratify=t_data)
# Data 정규화
scaler = StandardScaler()
scaler.fit(train_x_data)
# Model 생성
sgd = linear_model.SGDClassifier(loss='log', # loss='log'는 Logistic Regression을 이용해 Binary Classification 하겠다.
tol=1e-5, # log loss가 1e-5이면 반복을 멈춤
random_state=2, # Random Seed
penalty='l2', # L2 - Ridge Regression로 규제 적용
alpha=0.001) # 규제 강도
# Model 학습
sgd.fit(scaler.transform(train_x_data), train_t_data)
# Accuracy로 Model 평가
test_score = sgd.score(scaler.transform(test_x_data), test_t_data)
print('정규화를 이용한 SGD Classifier의 정확도 : {}'.format(test_score)) # 0.9707602339181286. 정규화 + L2
여기까지가 Binary Classification(이항분류)
이제부터 Multinomial Classification(다항분류)
Multinomial에서는 Logistic에서 쓰는 Sigmoid가 아닌 Softmax를 사용하므로 모델(산식)도 Loss func(Cross Entropy)도 변경해야 함
1. Multinomial Classification - BMI 데이터 by Sklearn
import numpy as np
import pandas as pd
from sklearn import linear_model
from sklearn.preprocessing import MinMaxScaler # 결측치가 없기 때문에 정규화에 MinMaxScaler 사용
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from scipy import stats
import tensorflow as tf
import warnings
warnings.filterwarnings('ignore')
df = pd.read_csv('./data/bmi.csv', skiprows=3) # skiprows는 주석이 달려있는 상위 3행을 제외해라
# label 0: thin
# label 1: normal
# label 2: fat
display(df.head()); print(df.shape); display(df.info()) # (20000, 3)
# Data Preprocessing
# print(df.isnull().sum()) # None
zscore_threshold = 2.0 # Z-score로 이상치 처리
(np.abs(stats.zscore(df['height'])) > zscore_threshold).sum() # None
(np.abs(stats.zscore(df['weight'])) > zscore_threshold).sum() # None
#(array([0, 1, 2], dtype=int64), array([6470, 5857, 7673], dtype=int64))
# np.unique(df['label'], return_counts=True) # class의 비율 확인
# Train과 Validation Data Set으로 분리
train_x_data, test_x_data, train_t_data, test_t_data = \
train_test_split(df[['height', 'weight']], df['label'], test_size=0.3, random_state=1, stratify=df['label'])
# Normalization
scaler = MinMaxScaler()
scaler.fit(train_x_data)
norm_train_x_data = scaler.transform(train_x_data)
norm_test_x_data = scaler.transform(test_x_data)
# Model 생성 후 학습 및 평가
model = linear_model.LogisticRegression(C=1000) # C 옵션(alpha 값)으로 L2 규제를 적용할 수 있음. alpha=0.001(1/1000)
model.fit(norm_train_x_data, train_t_data)
predict_val = model.predict(norm_test_x_data)
acc = accuracy_score(predict_val, test_t_data)
print('Sklearn으로 구현한 Accuracy : {}'.format(acc)) # 0.9851666666666666, 0.9845
# Prediction
result = model.predict(scaler.transform(np.array([[187, 81]]))) # 187, 81 -> 1
print(result)
2. Multinomial Classification - BMI 데이터 by Tensorflow
여러 개의 class가 존재하기 때문에 행렬곱 연산을 위해 label을 One-Hot Encoding 처리를 해야 함
→ Tensorflow의 one_hot 기능을 이용해 Node로 만들기
학습 데이터의 사이즈가 매우 크면 메모리에 데이터를 모두 loading 할 수 없기 때문에 batch 처리를 해야 함
sess = tf.Session() # Tensorflow의 기능을 이용해 인코딩을 하므로 node가 생성됨
onehot_train_t_data = sess.run(tf.one_hot(train_t_data, depth=3)) # depth 옵션으로 class의 개수를 알려줘야 함
onehot_test_t_data = sess.run(tf.one_hot(test_t_data, depth=3))
# Placeholder
X = tf.placeholder(shape=[None,2], dtype=tf.float32) # 독립변수(feature)의 개수
T = tf.placeholder(shape=[None,3], dtype=tf.float32) # 원핫 인코딩! class의 개수이면서 Logistic의 개수
# Weight, bias
W = tf.Variable(tf.random.normal([2,3])) # 독립변수 2개, W 3개
b = tf.Variable(tf.random.normal([3]))
# Model, Hypothesis
logit = tf.matmul(X,W) + b
H = tf.nn.softmax(logit) # Multinomial Classification의 Softmax
# Cross Entropy(loss func)
loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(logits=logit, labels=T))
# Train
train = tf.train.GradientDescentOptimizer(learning_rate=1e-1).minimize(loss)
# Session 초기화
sess.run(tf.global_variables_initializer())
# 반복 학습
# for step in range(10000):
# _, loss_val = sess.run([train, loss], feed_dict={X:norm_train_x_data, T:onehot_train_t_data})
# if step % 1000 == 0:
# print('loss value : {}'.format(loss_val))
# Memory Fault 나는 것을 방지하기 위해 데이터를 쪼개서 학습 -> batch 처리
num_of_epoch = 1000 # 학습을 위한 전체 epoch 수
num_of_batch = 100 # 한번에 학습할 데이터 양
for step in range(num_of_epoch):
total_batch = int(norm_train_x_data.shape[0] / num_of_batch) # 학습 데이터의 개수 / batch
for i in range(total_batch):
batch_x = norm_train_x_data[i*num_of_batch:(i+1)*num_of_batch] # [0:100], [100:200] ~. 100개씩 Slicing
batch_y = onehot_train_t_data[i*num_of_batch:(i+1)*num_of_batch]
_, loss_val = sess.run([train, loss], feed_dict={X:batch_x, T:batch_y})
if step % 100 == 0:
print('loss value : {}'.format(loss_val))
# 성능평가(Accuracy)
result = sess.run(H, feed_dict={X:scaler.transform(np.array([[187, 81]]))})
# print(result) # [[4.761967e-05 9.079144e-01 9.203796e-02]]
# print(result[0,1]) # 0.9079144
# print(result.max()) # 중간의 0.9079144(1)가 가장 높은 확률
# print(np.argmax(result, axis=1)) # [1].가장 큰 값의 index를 추출
predict = tf.argmax(H,1)
correct = tf.equal(predict, tf.argmax(T,1))
accuracy = tf.reduce_mean(tf.cast(correct, dtype=tf.float32))
result = sess.run(accuracy, feed_dict={X:norm_test_x_data, T:onehot_test_t_data})
print(result) # 0.9855
앞으로 큰 사이즈의 데이터와 딥러닝을 다뤄야 하기 때문에 로컬의 Jupyter Notebook에서 구글 Colab으로 옮긴다!
수정 → 노트 설정 → 하드웨어 가속기 : GPU로 저장
print(tf.__version__) # Tensorflow의 기본 2.8.0. 버전 지우고 1.15.0 설치
!pip uninstall tensorflow
!pip install tensorflow==1.15
1. 3/15 화 | 2. 3/16 수 | 3. 3/17 목 | 4. 3/18 금 | 5. 3/21 월 |
ML 환경 설정 (아나콘다, 주피터 노트북), Pandas, Numpy, ndarray |
ML Numpy, 행렬곱연산, 전치행렬, iterator, axis, Pandas, Series, DataFrame |
ML Pandas, DataFrame, 함수들 |
ML Pandas, 데이터 분석, 데이터 전처리 |
ML Pandas, 데이터 전처리, 수행평가 |
6. 3/22 화 | 7. 3/23 수 | 8. 3/24 목 | 9. 3/25 금 | 10. 3/28 월 |
ML 데이터 시각화, Matplotlib, 기술통계 |
ML 기술통계 |
ML 기술통계, 머신러닝 |
ML 미분, Regression |
ML 머신러닝 기법들, Regression |
11. 3/29 화 | 12. 3/30 수 | 13. 3/31 목 | 14. 4/1 금 | 15. 4/4 월 |
ML Regression 구현 (Python, Scikit-Learn) |
ML Outlier, Z-score, MinMaxScaler, 다변수 |
ML Tensorflow, Classification |
ML Binary Classification, Logistic Regression |
ML 평가지표(Metrics) |
16. 4/5 화 | 17. 4/6 수 | 18. 4/7 목 | 19. 4/8 금 | 20. 4/11 월 |
ML 평가 시 주의사항 (Over-fitting, Regularization, Over-Sampling) |
ML Multinomial Classification, SGD Classifier, Softmax, batch |
ML | ML |
* 교재로도 수업 내용을 복습하자!