ecsimsw

BMI 분류 학습 / Keras 연습 본문

BMI 분류 학습 / Keras 연습

JinHwan Kim 2020. 2. 6. 03:54

Keras 활용 / BMI 계산 / 학습 후 저장, 오답 확인

 

1. bmi 계산식을 이용해서 20000개의 키/몸무게/상태 데이터를 csv 파일로 생성한다.

2. Keras 학습하여 bmi 계산식을 모르는 상황에서 학습만으로 얼마나 정확히 분류할 수 있는가 평가한다.

3. 학습된 결과를 확인하고, 예측에 실패한 데이터를 확인한다.

4. model은 JSON, weight는 h5으로 각각 저장하고 불러와 해당 모델을 사용해본다.

5. svm과 학습 결과를 비교한다.

 

설명 참고 : https://ecsimsw.tistory.com/entry/Keras

 

코드 내용 

 

1. Create BMI data

import random

dataSrc = "./data_bmi/"

## CreateBMI data Set

def carBMI(w,h):
    result = w/(h/100)**2
    if result <= 18:
        return "thin"
    elif result >= 25:
        return "fat"
    else:
        return "normal"

def createBMIdataset(size):
    with open(dataSrc+'write.csv',mode ='w') as f:
        f.write("{0},{1},{2}\n".format('weight','height','label'))

        for _ in range(size):
            w = random.randint(40,100)
            h = random.randint(150,200)
            l = carBMI(w,h)
            f.write("{0},{1},{2}\n".format(w,h,l))

createBMIdataset(20000)

 

2. Compile / Learn

from keras.models import Sequential
from keras.layers.core import Dense, Dropout, Activation
from keras.callbacks import EarlyStopping
from keras.models import model_from_json 
import pandas as pd, numpy as np

### get csv data and refine

dataSrc = "./data_bmi/"

csv = pd.read_csv(dataSrc+'write.csv')

csv['weight'] /= 100  ###
csv['height'] /= 200  ###

X = csv[['weight', 'height']].values

bclass = {'thin': [1, 0, 0], 'normal': [0, 1, 0], 'fat': [0, 0, 1]}

y = np.empty((20000, 3))
for i, v in enumerate(csv['label']):
    y[i] = bclass[v]

X_train, y_train = X[1:15001], y[1:15001]
X_test, y_test = X[15001:20001], y[15001:20001]


### model compile

model = Sequential()
model.add(Dense(512, input_shape=(2,)))
model.add(Activation('relu'))
model.add(Dropout(0.1))

model.add(Dense(512))
model.add(Activation('relu'))
model.add(Dropout(0.1))

model.add(Dense(3))
model.add(Activation('softmax'))

model.compile(
    loss='categorical_crossentropy',
    optimizer='rmsprop',
    metrics=['accuracy']
)


### model fit & evaluate

hist = model.fit(
    X_train, y_train,
    batch_size=100,
    epochs=20,
    validation_split=0.1,
    callbacks=[EarlyStopping(monitor='val_loss', patience=2)],
    verbose=1
)

score = model.evaluate(X_test, y_test)
print('loss=', score[0])
print('accuracy=', score[1])

 

3. Predict / Check wrong answers

### predict with new data

X_temp = np.array([[50.5/100,156/200]])
pre_temp = model.predict_classes(X_temp)
print(str(X_temp)+" => "+ str(pre_temp))

### check wrong answers

pre = model.predict_classes(X_test)
wrongIndexList = []
for i, v in enumerate(pre):
    ans = np.where(y_test[i]==1)[0][0] # = y_test[i].agrmax()
    if(v!=ans):
        print(i)
        wrongIndexList.append(i)

m = np.array([[100,200]])
for wrongIndex in wrongIndexList:
    print("X : ", (X_test[wrongIndex]*m[0]))
    print("pre : ", pre[wrongIndex])
    print("ans : ", np.where(y_test[wrongIndex]==1)[0][0])
    print("re-cal : ", (X_test[wrongIndex]*m)[0][0]/((X_test[wrongIndex]*m)[0][1]/100)**2 )

 

4-1. Save model and weight as json, h5

### save model as json, weight as h5 

modelJson = model.to_json()

with open(dataSrc+"model_bmi.json", "w") as jsFile: 
    jsFile.write(modelJson)

model.save_weights(dataSrc+"model_bmi.h5")

 

4-2  Load and Predict with loaded model

from keras.models import Sequential
from keras.layers.core import Dense, Dropout, Activation
from keras.callbacks import EarlyStopping
from keras.models import model_from_json 
import pandas as pd, numpy as np

### load model and weight

dataSrc = "./data_bmi/"

with open(dataSrc+"model.json", "r") as jsFile:
    loaded_json = jsFile.read()

loaded_model = model_from_json(loaded_json)
loaded_model.load_weights(dataSrc+"model.h5")


### predict with loaded model

X_temp = np.array([[100/100,180/200]])
pre = loaded_model.predict_classes(X_temp)

print(str(X_temp)+" => "+ str(pre))

 

5. Compare with Svm

### Convert data shape

y_train_svm = []
for i in range(len(y_train)):
    y_train_svm.append(np.where(y_train[i]==1)[0][0])
y_train_svm = np.array(y_train_svm)

y_test_svm = []
for i in range(len(y_test)):
    y_test_svm.append(np.where(y_test[i]==1)[0][0])
y_test_svm = np.array(y_test_svm)

### Compare with svm

import sys
from sklearn import svm, metrics, model_selection

clf = svm.SVC()
clf.fit(X_train,y_train_svm)

pre_svm = clf.predict(X_test)
svm_score = metrics.accuracy_score(y_test_svm,pre)

print("svm score :",svm_score)

 

Report

 

 1. 정규화 

 

- 몸무게, 키를 직접 대입하여 학습하는 것 보다 이를 0~1 사이의 값으로 정규화해서 학습하는 것이 훨씬 더 좋은 모델을 만든다. 이전에는 80% 전후의 학습 결과를 보였는데, 정규화 이후에는 95% 전후의 결과를 갖는다.

csv = pd.read_csv(dataSrc+'/write.csv')
X = csv[['weight', 'height']].values

csv['weight'] /= 100  ###
csv['height'] /= 200  ###

bclass = {'thin': [1, 0, 0], 'normal': [0, 1, 0], 'fat': [0, 0, 1]}
y = np.empty((20000, 3))
for i, v in enumerate(csv['label']):
    y[i] = bclass[v]

 

 2. 오답 확인 

 

- 세개의 레이블의 기준인 18과 25 사이의 값에서 오답이 발생하는 것은 당연하다.  이상한 점은 모든 오답(700개의 추출된 오답 데이터) 들이 실제보다 더 작은 값으로 예측해서 틀렸다는 것이다.

 

- 18, 25 전후로 오답이 발생하는 것은 당연한 일이지만, 18이상은 없이, 17.xxx 또는 25 이상은 없이, 24.xxx에서 오답이 발생한다.

X :  [[ 88. 188.]]
pre :  2
ans :  1
re-cal :  24.898143956541425
X :  [[ 79. 181.]]
pre :  2
ans :  1
re-cal :  24.114038033027075
X :  [[ 71. 199.]]
pre :  1
ans :  0
re-cal :  17.928840180803515
X :  [[ 76. 176.]]
pre :  2
ans :  1
re-cal :  24.535123966942148
X :  [[ 68. 198.]]
pre :  1
ans :  0
re-cal :  17.345168860320378
X :  [[ 79. 179.]]
pre :  2
ans :  1
re-cal :  24.65590961580475
X :  [[ 92. 197.]]
pre :  2
ans :  1
re-cal :  23.70584142853462
X :  [[ 86. 191.]]
pre :  2
ans :  1
re-cal :  23.573915188728378
X :  [[ 89. 196.]]
pre :  2
ans :  1
re-cal :  23.167430237401085
X :  [[ 92. 197.]]
pre :  2
ans :  1
re-cal :  23.70584142853462
X :  [[ 57. 178.]]
pre :  1
ans :  0
re-cal :  17.990152758490087
X :  [[ 54. 174.]]
pre :  1
ans :  0

 

3. SVM과 비교 

 

 - svm의 정확도는 93.7, keras는 92~96의 정확도를 가진다. 아직 케라스를 사용하는 법만 알지 개념을 제대로 공부하지 않아, svm과 keras가 어떤 상황에서 각각 유리한지 모르겠다.

 

keras_bmi.txt
0.00MB

Comments