티스토리 뷰

Logistic Regression은 반드시 성능평가 (Accuracy)를 진행해야 한다.

Logistic Regression과 Sigmoid 함수

 

성능 평가 지표 (Metric)

성능 평가 지표

 

Learning Rate와 Overshooting

  • Learning Rate가 너무 큰 경우 Overshooting이 발생하여 최적점을 지나친다.
  • Learning Rate가 너무 작은 경우에는 최적점에 도달하지 못한 채 학습이 끝난다.

 

Overfitting

  • Training data에 대해 학습이 너무 잘 아루어져서, 오히려 실제 입력 데이터에는 적용이 잘 안되는 경우

 

Overfitting을 해결하는 방법들

  1. 많은 양의 Training Data를 활용한다. -> 프로그래밍적으로는 해결x
  2. Feature Engineering을 통해 Feature (=독립변수)의 개수를 줄인다. 
  3. Weight 값을 인위적으로 조절하는 Regulation 기법을 이용한다.
  4. 딥러닝에서는 Dropout을 이용한다.

 

Evaluation (평가)

  • 데이터를 어떻게 나누어서 평가할 것인가?

 

Cross Validation

 

Multinomial Classification와 Softmax 함수

 

 

 

 

Multinomial Classficiation

  • BMI 지수에 대한 데이터로 학습 후 예측까지 진행해본다.

  • BMI 지수는 키와 몸무게를 가지고 저체중, 정상, 과체중, 비만을 판단하는 지수

  • BMI = 자신의 몸무게 (kg) / 키의 제곱 (m)

    • 18.5 이하 =>저체중

    • 18.5 ~ 23 => 정상

    • 23 ~ 25 => 과체중

    • 25 ~ 비만

  • BMI 지수를 조사한 데이터를 학습하여 예측한다. 3가지로 분류됨

 

sklearn으로 Multinomial Classificiation 구현

In [27]:
# Multinomial Classficiation

import numpy as np
import pandas as pd
# stats 서브패키지는 확률분포 분석 기능 제공
from scipy import stats 
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import MinMaxScaler
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import cross_val_score
from sklearn.metrics import accuracy_score

df = pd.read_csv('./data/bmi.csv', skiprows=3)
display(df)

# 결측치 확인 - 없음
df.isnull().sum()

# 이상치 확인
zscore = 1.8

# height의 이상치 확인 => 셋 다 없음
# df.loc[np.abs(stats.zscore(df['height'])) >= zscore, :]
# df.loc[np.abs(stats.zscore(df['weight'])) >= zscore, :]
# df.loc[np.abs(stats.zscore(df['label'])) >= zscore, :]

# Data Split
# training, test 7:3 분리
# 나중에 Train부분은 k-fold cross validation을 진행한다.

x_data_train, x_data_test, t_data_train, t_data_test = \
train_test_split(df[['height', 'weight']], df['label'], test_size=0.3, random_state=0)

# Normalization
scaler = MinMaxScaler()  # scaler 객체를 생성한다.
scaler.fit(x_data_train) # scaler 객체에 최대, 최소와 같은 정보가 들어간다.

x_data_train_norm = scaler.transform(x_data_train)
x_data_test_norm = scaler.transform(x_data_test)

del x_data_train  # 혼동을 방지하기 위해 변수 삭제
del x_data_test  

# sklearn 구현은 매우 간단!
# Model을 생성하고, 학습시키고, 예측한다.

model = LogisticRegression()
model.fit(x_data_train_norm, t_data_train)

# model의 정확도 측정
# cross validation
kfold = 10
kfold_score = cross_val_score(model, x_data_train_norm, t_data_train, cv=kfold)
print('### cross validation ###')
print('### cross validation score ###')
print('score : {}'.format(kfold_score))
print('평균 : {}'.format(kfold_score.mean()))

# 최종모델평가
predict_val = model.predict(x_data_test_norm) # 테스트 데이터로 예측값을 구한다.
acc = accuracy_score(predict_val, t_data_test)
print('Model의 최종 Accuracy : {}'.format(acc))

# Predict
height = 188
weight = 78
my_state = [[height, weight]]
my_state_val = model.predict(scaler.transform(my_state))
print(my_state_val) # [1] -> 정상
 
  label height weight
0 1 188 71
1 2 161 68
2 0 178 52
3 2 136 63
4 1 145 52
... ... ... ...
19995 0 163 48
19996 2 139 70
19997 1 150 48
19998 1 189 69
19999 1 142 41

20000 rows × 3 columns

 
### cross validation ###
### cross validation score ###
score : [0.98       0.98642857 0.985      0.97642857 0.98642857 0.98428571
 0.98714286 0.97714286 0.97714286 0.98642857]
평균 : 0.9826428571428572
Model의 최종 Accuracy : 0.9845
[1]
 

tesorflow로 Multinomial Classificiation 구현

In [18]:
import numpy as np
import pandas as pd
df = pd.read_csv('./data/bmi.csv', skiprows=3)
display(df)
 
  label height weight
0 1 188 71
1 2 161 68
2 0 178 52
3 2 136 63
4 1 145 52
... ... ... ...
19995 0 163 48
19996 2 139 70
19997 1 150 48
19998 1 189 69
19999 1 142 41

20000 rows × 3 columns

In [23]:
%reset

# BMI Multinomial Example
import numpy as np
import pandas as pd
import tensorflow as tf
from sklearn.preprocessing import MinMaxScaler # Normalization
from sklearn.model_selection import train_test_split # train, test 데이터 분리
from sklearn.model_selection import KFold # cross validation


# Raw Data Loading
df = pd.read_csv('./data/bmi.csv', skiprows=3)

# 결측치와 이상치 확인 및 처리
# 이상 없음

# Data Split
x_data_train, x_data_test, t_data_train, t_data_test = \
train_test_split(df[['height','weight']], df['label'], test_size=0.3, random_state=0)

# 7:3 비율로 train과 test 데이터를 분리했다.
# x_data_test, t_data_test 두개는 맨 끝에서 모델의 최종 Accuracy를 측정할 때 한번 사용한다.

# Normalizaion 진행 (Min-Max Scaling)
scaler = MinMaxScaler()
scaler.fit(x_data_train) # 나중에 scaling을 하기 위한 정보를 scaler에게 세팅
x_data_train_norm = scaler.transform(x_data_train)
x_data_test_norm = scaler.transform(x_data_test)

del x_data_train # 에러를 방지하기 위해 사용하지 않는 변수 삭제
del x_data_test


t_data_train
# 정답에 해당하는 t_data_train을 살펴보니 Multinomial이다.
# One hot encoding으로 데이터를 변환시켜야 한다.

# 0 -> 1 0 0 
# 1 -> 0 1 0 
# 2 -> 0 0 1 
# 종류 3가지 => Logistic 3개 => depth 3
# Numpy를 이용한 로직 처리와, Tensorflow API를 이용하는 방법이 있는데 후자 선택.

# Tensorflow node를 실행하기 위해 session이 필요하다.
sess = tf.Session()

# 우리가 사용할 label(t_data)을 one hot encoding 형태로 변환
t_data_train_onehot = sess.run(tf.one_hot(t_data_train, depth=3))
t_data_test_onehot = sess.run(tf.one_hot(t_data_test, depth=3))

del t_data_train  # 에러를 방지하기 위해 사용하지 않는 변수 삭제
del t_data_test

# 지금까지 위에서 x_data_train_norm, t_data_train_onehot을 만들었다.
# training data set을 준비했다.

# 데이터가 준비 되었으니 Tensorflow Graph를 그려보자

# Placeholder
# shape=[None, n] => 행은 상관 없음
X = tf.placeholder(shape=[None, 2], dtype=tf.float32)
T = tf.placeholder(shape=[None, 3], dtype=tf.float32)

# Weight & bias
# X, T의 shape을 이용한 행렬 연산으로 수행되기 위해 
# W: 각각의 열이 logistic 1개에 해당 => 3개가 뭉쳐있음
W = tf.Variable(tf.random.normal([2, 3]), name='weight') # 2가 키, 몸무게인가?
b = tf.Variable(tf.random.normal([3]), name='bias')

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

# loss function
loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(logits=logit, 
                                                                 labels=T))
# train
train = tf.train.GradientDescentOptimizer(learning_rate=0.1).minimize(loss)

# 반복학습하는 함수
# parameter
num_of_epoch = 1000
batch_size = 100 # 한번에 학습할 x_data와 t_data의 행의 수


def run_train(sess, train_x, train_t):
    print('### 학습이 시작된다. ###')
    # session과 초기화
    sess.run(tf.global_variables_initializer())
    total_batch = int(train_x.shape[0] / batch_size)  # (14000, 2)[0] => 14000
    
    for step in range(num_of_epoch):
        
        for i in range(total_batch):
            batch_x = train_x[i*batch_size:(i+1)*batch_size]
            batch_t = train_t[i*batch_size:(i+1)*batch_size]
            _, loss_val = sess.run([train, loss], 
                                   feed_dict={X: batch_x,
                                              T: batch_t})
        if step % 100 == 0:
            print('Loss : {}'.format(loss_val))
        
    print('### 학습이 종료된다.###')
            
        
# Accuracy (정확도 측정)   #    0    1     2   일 확률
predict = tf.argmax(H, 1)  # [[0.5  0.4  0.1]] 입력한 값에 대한 예측 중 가장 큰 값을 알아냄
                           # 2차원이기에 axis 지정, axis=1 열방향 가로 방향
    
correct = tf.equal(predict, tf.argmax(T, 1))
accuracy = tf.reduce_mean(tf.cast(correct, dtype=tf.float32))
    

# 1. 학습을 진행하고 Training data로 validation 수행 - 의미 없지만 오버피팅 확인
# 학습진행
# run_train(sess, x_data_train_norm, t_data_train_onehot)
# # Accuracy 측정 (Training data로 validation 수행)
# result = sess.run(accuracy, feed_dict={X:x_data_train_norm,
#                               T:t_data_train_onehot})

# print('Training data로 validation한 정확도 : {}'.format(result))


# 2. 이렇게 하는 것 보다는 Cross Validation을 하는게 좋다.
# Cross Validation
cv = 5  # [훈련, 검증] => 5 set가 만들어 진다.
results = []  # 5 set에 대한 accuracy를 구해서 liast 안에 넣는다.
kf = KFold(n_splits=cv, shuffle=True)

for training_idx, validation_idx in kf.split(x_data_test_norm):
    # training_idx : 결국은 index 값을 알아온다.
    train_x = x_data_train_norm[training_idx]    # Fancy indexing
    train_t = t_data_train_onehot[training_idx]  # Fancy indexing
    
    valid_x = x_data_train_norm[validation_idx]
    valid_t = t_data_train_onehot[validation_idx]
    
    run_train(sess, train_x, train_t)
    results.append(sess.run(accuracy,
                           feed_dict={X:valid_x,
                                      T:valid_t}))
    
print('CrossValidation 결과 : {}'.format(results))
print('CrossValidation 최종 결과 : {}'.format(np.mean(results)))


# 3. 최종 accuracy 확인
# 학습진행
run_train(sess, x_data_train_norm, t_data_train_onehot)
# Accuracy 측정
result = sess.run(accuracy, feed_dict={X:x_data_test_norm,
                              T:t_data_test_onehot})

print('최종 정확도 : {}'.format(result))
 
Once deleted, variables cannot be recovered. Proceed (y/[n])? y
### 학습이 시작된다. ###
Loss : 1.2564572095870972
Loss : 0.2887102961540222
Loss : 0.22310075163841248
Loss : 0.19122354686260223
Loss : 0.17133188247680664
Loss : 0.1573738008737564
Loss : 0.14687514305114746
Loss : 0.13860520720481873
Loss : 0.13187086582183838
Loss : 0.12624940276145935
### 학습이 종료된다.###
### 학습이 시작된다. ###
Loss : 0.8981712460517883
Loss : 0.26843613386154175
Loss : 0.20586833357810974
Loss : 0.1754659116268158
Loss : 0.15666088461875916
Loss : 0.14358223974704742
Loss : 0.13382002711296082
Loss : 0.12617820501327515
Loss : 0.11998720467090607
Loss : 0.11484046280384064
### 학습이 종료된다.###
### 학습이 시작된다. ###
Loss : 1.0913689136505127
Loss : 0.29898032546043396
Loss : 0.23251324892044067
Loss : 0.20037376880645752
Loss : 0.1804378628730774
Loss : 0.16651469469070435
Loss : 0.1560787558555603
Loss : 0.14787890017032623
Loss : 0.14121384918689728
Loss : 0.1356564462184906
### 학습이 종료된다.###
### 학습이 시작된다. ###
Loss : 0.8923856616020203
Loss : 0.28808844089508057
Loss : 0.21965719759464264
Loss : 0.1859416514635086
Loss : 0.1649031788110733
Loss : 0.15019038319587708
Loss : 0.13917024433612823
Loss : 0.1305249035358429
Loss : 0.12351295351982117
Loss : 0.11768021434545517
### 학습이 종료된다.###
### 학습이 시작된다. ###
Loss : 1.18339204788208
Loss : 0.2931476831436157
Loss : 0.2233366221189499
Loss : 0.18957221508026123
Loss : 0.16861818730831146
Loss : 0.15398569405078888
Loss : 0.14302600920200348
Loss : 0.13442343473434448
Loss : 0.12744039297103882
Loss : 0.12162692099809647
### 학습이 종료된다.###
CrossValidation 결과 : [0.9866667, 0.97833335, 0.9825, 0.98333335, 0.97333336]
CrossValidation 최종 결과 : 0.9808333516120911
### 학습이 시작된다. ###
Loss : 0.8983460068702698
Loss : 0.20564807951450348
Loss : 0.16245803236961365
Loss : 0.1428089588880539
Loss : 0.1310224086046219
Loss : 0.12295746058225632
Loss : 0.11699065566062927
Loss : 0.1123417392373085
Loss : 0.10858340561389923
Loss : 0.10545945912599564
### 학습이 종료된다.###
최종 정확도 : 0.9829999804496765
In [25]:
# Prediction
height = 187
weight = 78

my_state = [[height, weight]]
my_state_scaled = scaler.transform(my_state)
print(my_state_scaled)

result = sess.run(H, feed_dict={X:my_state_scaled})
print(np.argmax(result))
 
[[0.8375     0.95555556]]
1
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/09   »
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
글 보관함