MNIST(Multinomial classification)/model평가

2021. 9. 10. 01:05ai/Machine Learning

728x90

Multinomial classification(다중분류) → 
"MNIST" → Machine Learning 계의 Hello world 

              2차원 pixel안에 값이 있으면 1 없으면 0 해서 사람들의 숫자글씨체를 표현 

              높은 수일수록 더 어두움

 

vision : 사진 동영상같이 보이는거

class : label의 갯수, 종류

2차원 pixel안에 값이 있으면 1 없으면 0 해서 사람들의 숫자글씨체를 표현 / 높은 수일수록 더 어두움
사람마다 글씨체가 다르다

왜 만들었을까 ? 

손 편지 쓰던 시절 미국에서 사람들이 우편번호 분리하기 힘들어 MNIST를 만들어 machine learning으로 학습해서 쉽게하기 위해


- mnist는 2차원 + 사람수 = 3차원 / 인데 ravel()로 mnist를1차원으로 변경

- class 가 10개이므로 binary classfication도 10개있어야 한다 == multinomial classfication

- 28 * 28 pixel = 784 pixel

- data는 kaggle data set을 가져다가 사용 

 


# MNIST 예제 (기본적인 multinomial classification)

import numpy as np
import pandas as pd     
import tensorflow as tf
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import MinMaxScaler
import matplotlib.pyplot as plt
# 평가에 관련된 module을 하나 추가할꺼예요! (precision, recall, accuracy, f1 score)


# data preprocessing : 전처리 부터 해야해요!

# raw data loading
df = pd.read_csv('./data/mnist/train.csv ')

# display(df)

# feature engineering 같은 작업이 필요! 하지만 우리예제에서는 할 필요가 없어요!

# 결측치 이상치 같은 데이터 전처리가 나와야 해요!
# 결측치 없어요!, 이상치 없어요!

# 픽셀데이터를 실제로 그려서 눈으로 확인해 보아요!
img_data = df.drop('label', axis=1, inplace=False).values

fig = plt.figure()
fig_arr = []   # list (이 안에 subplot이 저장되게 되요!)

for n in range(10):
    fig_arr.append(fig.add_subplot(2,5,n+1))
    fig_arr[n].imshow(img_data[n].reshape(28,28), cmap='Greys', interpolation='nearest')


  #  interpolation='nearest' : data의 보간의 의미로 이미지를 data의 차이를 어떻게

                                     조정해서 자연스럽게 이미지를 보여줄지에 대한 기법

  #  cmap=                     : 이미지 색상   


plt.tight_layout()                  # 위치조절
plt.show()


# training data와 validation data 분리

train_x_data, valid_x_data, train_t_data, valid_t_data = \
train_test_split(df.drop('label', axis=1, inplace=False),
                 df['label'],
                 test_size=0.3,
                 random_state=0,
                 stratify=df['label'])

# x_data에 대한 Normalization
scaler = MinMaxScaler()
scaler.fit(train_x_data)
train_x_data_norm = scaler.transform(train_x_data)
valid_x_data_norm = scaler.transform(valid_x_data)

# label에 대해 one-hot encoding을 적용
# 예) label 3 => 0 0 0 1 0 0 0 0 0 0
#     label 9 => 0 0 0 0 0 0 0 0 0 1
sess = tf.Session()
train_t_data_onehot = sess.run(tf.one_hot(train_t_data, depth=10))
valid_t_data_onehot = sess.run(tf.one_hot(valid_t_data, depth=10))


# 데이터 전처리가 끝났으니 이제 Tensorflow Graph를 그려보아요!

# placeholder
X = tf.placeholder(shape=[None,784], dtype=tf.float32)
T = tf.placeholder(shape=[None,10], dtype=tf.float32)

# Weight & bias
W = tf.Variable(tf.random.normal([784,10]))
b = tf.Variable(tf.random.normal([10]))

# Hypothesis(Model)
logit = tf.matmul(X,W) + b
H = tf.nn.softmax(logit)

# loss function(cross entropy)
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())   # 초기화 코드

# 반복학습
# 지금까지 했던 방식은 사용하기 곤란해요 이제!!
num_of_epoch = 3000   # 1 epoch(에폭) : training data 전체를 이용해서 1번 학습을 진행.
batch_size = 100

# 1 epoch = 29400개의 데이터
# 이걸 100개씩 짤라서 학습을 진행 => 29400 / 100 = 294 반복
for step in range(num_of_epoch):
    
    num_of_iter = train_x_data_norm.shape[0] / batch_size   # 294.0
    
    for i in range(int(num_of_iter)):
        batch_x = train_x_data_norm[i*batch_size:(i+1)*batch_size]
        batch_y = train_t_data_onehot[i*batch_size:(i+1)*batch_size]
        tmp, loss_val = sess.run([train, loss], feed_dict={X:batch_x, 
                                                           T:batch_y})
    if step % 300 == 0:
        print('loss : {}'.format(loss_val))       

 


# 모델이 완성되었어요!
# 모델이 완성되면 당연히 evaluation(평가)을 진행
# Evaluation Metric으로 accuracy를 사용

# H => [0.2 0.1 0.3 ... 0.2]   => 10개   => 2번 index가 가장 크기때문에 숫자 2라고 예측
predict = tf.argmax(H,1)
correct = tf.equal(predict, tf.argmax(T,1))
accuracy = tf.reduce_mean(tf.cast(correct, dtype=tf.float32))

# 2가지 경우로 평가를 진행
# 1. training data로 accuracy를 계산 => 당연히 높게 나와요!
train_result = sess.run(accuracy, feed_dict={X:train_x_data_norm, 
                                             T:train_t_data_onehot})
print('train_result : {}'.format(train_result))
# 2. validation data로 accuracy를 계산 => 상대적으로 낮게 나와요!
valid_result = sess.run(accuracy, feed_dict={X:valid_x_data_norm, 
                                             T:valid_t_data_onehot})
print('valid_result : {}'.format(valid_result))

# 계산결과가 
# 1. train acc >>> validation acc   => overfitting
# 2. train acc 비슷비슷 validation acc 그러면서 둘 다 높아 => 잘 만들어졌어요!
# 3. train acc 비슷비슷 validation acc 그러나 둘 다 낮아 => underfitting


# sklearn이 제공하는 평가 관련 module을 사용해 보아요!
# sklearn.metrics.classification_report()

# sklearn.metrics.classification_report(y_true, y_pred, target_names=[])
# y_true : 우리가 가지고 있는 정답. 1차원. onehot 형태가 아닌 label형태로 입력 
#          ex) [0 3 5 8]
# y_pred : 우리 모델이 예측한 값. 1차원. onehot 형태가 아닌 label형태로 입력 
# target_names : label을 표현하기 위해서 사용!

from sklearn.metrics import classification_report

print(
classification_report(valid_t_data,
                      sess.run(predict, feed_dict={X:valid_x_data_norm}),
                      target_names=['num0','num1','num2','num3','num4','num5','num6','num7','num8','num9',])
)

 


sklearn ver

from sklearn.preprocessing import MinMaxScaler

from sklearn.model_selection import train_test_split

 

x_data = df.drop('label', axis=1, inplace=False)

t_data = df['label']      # one-hot encoding을 진행해야 해요! (tensorflow 1.15버전인경우)

 

# 정규화

scaler = MinMaxScaler()

scaler.fit(x_data)

x_data_norm = scaler.transform(x_data)

 

# train, validation 분리

train_x_data_norm, valid_x_data_norm, train_t_data, valid_t_data = \

train_test_split(x_data_norm,

                 t_data,

                 test_size=0.3,

                 random_state=0,

                 stratify=t_data)

 

# sklearn 구현

from sklearn.linear_model import LogisticRegression

from sklearn.metrics import classification_report

 

model = LogisticRegression(solver='saga')   

                               # default값으로 regulzation작업인 onehot incoding인 l2가 적용

                               # solver (algorithm)의 default = 'lbfgs'   => 상대적으로 작은 데이터에 적합

                               # 데이터량이 많은 경우에는 'lbfgs'를 사용하기에 적합하지 않아요!

                               # 'sag' => 상대적으로 큰 데이터에 적합 

                               # 이 'sga'를 개량한 버전이 있는데 'saga' = stochasic avarage gradient algorithm

model.fit(train_x_data_norm, train_t_data)   

# 요자리 위 까지가 validation data가 들간다 모델 평가

 

result = classification_report(valid_t_data, model.predict(valid_x_data_norm))

# 최종적으로 들어가므로 요자리에 test data가 들간다

print(result)

 

 


tf 2.0 ver

# tensorflow 2.x keras 구현

import tensorflow as tf

from tensorflow.keras.models import Sequential

from tensorflow.keras.layers import Flatten, Dense

from tensorflow.keras.optimizers import Adam

 

keras_model = Sequential()

keras_model.add(Flatten(input_shape=(train_x_data_norm.shape[1],)))

                               #input_shape= 독립변수갯수

keras_model.add(Dense(10, activation='softmax'))

                              # 종속변수 종류의 갯수

 

keras_model.compile(optimizer=Adam(learning_rate=1e-1),

                    loss='sparse_categorical_crossentropy',

                    metrics=['accuracy'])

                          #  sparse_categorical_crossentropy : 다중분류 (앞에 sparse는 onehot encoding을 안한다)

                          #  모델이 만들어지면서 evaluation한다

history = keras_model.fit(train_x_data_norm,

                          train_t_data,

                          epochs=100,

                          verbose=0,

                          batch_size=100,

                          validation_split=0.2)

# epochs=몇번반복 /  verbose= 출력레벨 /batch_size=몇번씩 끊어서하나 (memorie부족때문) /

# validation_split= traindata를 validation으로 더 쪼개겠다)

처음은 training data로 evaluation함 / val_ 은 validation으로 evaluatiion한것

#위 결과로 보았을때 내꺼인 train data만 높고 val은 낮은걸로 보아 과적합


print(history.history.keys())

# 이런것들을 조사해서.. 모델을 완성!!

# 처음 history는 변수명 . 다음 history는 속성(dic형태)

 

 

 

# 모델이 완성됬으면 마지막 평가

keras_model.evaluate(valid_x_data_norm,valid_t_data)

 

# 모델이 완성 된 후 precision, recall, f1 score, accuracy를 같이 출력

from sklearn.metrics import classification_report

 

print(classification_report(valid_t_data,      # 1, 2, 3, 4

                            tf.argmax(keras_model.predict(valid_x_data_norm), axis=1).numpy()))

 

'그래프를 그려 둘의 차이를 확인할수 있따'

 

print(history.history.keys())

import matplotlib.pyplot as plt

 

# plt.plot(history.history['loss'], color='b')

# plt.plot(history.history['val_loss'], color='r')

plt.plot(history.history['accuracy'], color='b')

plt.plot(history.history['val_accuracy'], color='r')

 

plt.show()

loss 그래프이며 떨어져야 정상이지만 red는 올라가므로 망했따
accuaracy 그래프이며 학습 할수록 올라가야 정상이지만 red가 blue따라 안올라가므로 over fitting

비정형 data이기때문에 deep learning으로 w를 증가시켜 복잡도를 올려야 

정확도가 올라간다

'ai > Machine Learning' 카테고리의 다른 글

KNN ( K - Nearest Neighbor )  (0) 2021.09.11
tensor flow 2.0 ver  (0) 2021.09.10
Multinomial classification(다중분류)  (0) 2021.09.09
Regulerization(규제)  (0) 2021.09.08
SGDClassifier, StandardScaler  (0) 2021.09.08