'공부/딥러닝'에 해당되는 글 7건

반응형

요구사항

- train set 으로 학습, validation val set 이용, test set 으로 테스트 accuracy 도출

- 자신만의 deep neural network을 설계하여 문제를 해결 할 것

(전이학습 모델 이용하면 안됨)

 

 

모델 개선 과정

----------------------------------------------------------------------------------------------------

먼저 데이터를 X_train/y_train, X_test/y_test, X_val, y_val로 나누어 학습을 진행하였습니다.

from keras.models import Sequential
from keras.layers import Dense
from keras.layers import Dropout
from keras.layers import Flatten
from keras.layers.convolutional import Convolution2D
from keras.layers.convolutional import MaxPooling2D
from keras.utils import np_utils
import numpy as np
import matplotlib.pyplot as plt
import os
import cv2

from tensorflow.python.keras.preprocessing.image import ImageDataGenerator
from tensorflow.python.keras.preprocessing.image import load_img, img_to_array

import numpy as np
from pathlib import Path
import glob
import pandas as pd
from skimage.io import imread # reading image as data

data_dir = Path('chest_xray')

train_dir = data_dir / 'train'
val_dir = data_dir / 'val'
test_dir = data_dir / 'test'

normal_cases_dir = train_dir / 'NORMAL'
pneumonia_cases_dir = train_dir / 'PNEUMONIA'

normal_cases_t = normal_cases_dir.glob('*.jpeg')
pneumonia_cases_t = pneumonia_cases_dir.glob('*.jpeg')

# Training data as a list
X_train = []
y_train = []

# Normal cases

for img in normal_cases_t:
    img = cv2.imread(str(img))
    img = cv2.resize(img, (224,224))
    # Convert grayscale image
    if img.shape[2] ==1:
        img = np.dstack([img, img, img])
    # CV2 uses BGR format, so we need to convert it to RGB
    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    # Normalizing the pixel values by dividing by its maximum
    img = img.astype(np.float32)/255.
    X_train.append(img)
    y_train.append(0)

# Pneumonia cases        
for img in pneumonia_cases_t:
    img = cv2.imread(str(img))
    img = cv2.resize(img, (224,224))
    if img.shape[2] ==1:
        img = np.dstack([img, img, img])
    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    img = img.astype(np.float32)/255.
    X_train.append(img)
    y_train.append(1)

X_train = np.array(X_train)
y_train = np.array(y_train)
normal_cases_dir = val_dir / 'NORMAL'
pneumonia_cases_dir = val_dir / 'PNEUMONIA'

normal_cases_v = normal_cases_dir.glob('*.jpeg')
pneumonia_cases_v = pneumonia_cases_dir.glob('*.jpeg')

# Training data as a list
X_val = []
y_val = []

# Normal cases
for img in normal_cases_v:
    img = cv2.imread(str(img))
    img = cv2.resize(img, (224,224))
    # Convert grayscale image
    if img.shape[2] ==1:
        img = np.dstack([img, img, img])
    # CV2 uses BGR format, so we need to convert it to RGB
    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    # Normalizing the pixel values by dividing by its maximum

    img = img.astype(np.float32)/255.
    X_val.append(img)
    y_val.append(0)

# Pneumonia cases        
for img in pneumonia_cases_v:
    img = cv2.imread(str(img))
    img = cv2.resize(img, (224,224))
    if img.shape[2] ==1:
        img = np.dstack([img, img, img])
    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    img = img.astype(np.float32)/255.
    X_val.append(img)
    y_val.append(1)

X_val = np.array(X_val)
y_val = np.array(y_val)

normal_cases_dir = test_dir / 'NORMAL'
pneumonia_cases_dir = test_dir / 'PNEUMONIA'

normal_cases_test = normal_cases_dir.glob('*.jpeg')
pneumonia_cases_test = pneumonia_cases_dir.glob('*.jpeg')
# Training data as a list
X_test = []
y_test = []

# Normal cases
for img in normal_cases_test:
    img = cv2.imread(str(img))
    img = cv2.resize(img, (224,224))
    # Convert grayscale image
    if img.shape[2] ==1:
        img = np.dstack([img, img, img])
    # CV2 uses BGR format, so we need to convert it to RGB
    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    # Normalizing the pixel values by dividing by its maximum
    img = img.astype(np.float32)/255.
    X_test.append(img)
    y_test.append(0)

# Pneumonia cases        
for img in pneumonia_cases_test:
    img = cv2.imread(str(img))
    img = cv2.resize(img, (224,224))
    if img.shape[2] ==1:
        img = np.dstack([img, img, img])
    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    img = img.astype(np.float32)/255.
    X_test.append(img)
    y_test.append(1)

X_test = np.array(X_test)
y_test = np.array(y_test)

from keras.models import Sequential
from keras.layers import Dense
from keras.layers import Dropout
from keras.layers import Flatten
from keras.layers.convolutional import Convolution2D
from keras.layers.convolutional import MaxPooling2D

seed = 100
np.random.seed(seed)


model=Sequential()

a=3

model.add(Convolution2D(32, kernel_size=(a, a), padding='same', strides=(1, 1), input_shape=(image_size, image_size, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2,2)))

model.add(Convolution2D(64, kernel_size=(a, a), padding='same',  activation='relu'))
model.add(MaxPooling2D(pool_size=(2,2)))

model.add(Convolution2D(128, kernel_size=(a, a), padding='same', activation='relu'))
model.add(MaxPooling2D(pool_size=(2,2)))

model.add(Convolution2D(256, kernel_size=(a, a), padding='same', activation='relu'))
model.add(MaxPooling2D(pool_size=(2,2)))

model.add(Flatten())

model.add(Dense(256,activation='relu'))
model.add(Dropout(0.5))

model.add(Dense(1,activation='sigmoid'))

model.compile(loss='binary_crossentropy',optimizer='adam',metrics=['accuracy'])

# Final evaluation of the model
scores = model.evaluate(X_test, y_test, verbose=0)
print("loss: %.2f" % scores[0])
print("acc: %.2f" % scores[1])

'''
loss: 2.00
acc: 0.75
'''


관련 자료를 찾던 중 ImageDataGenerator을 알게되었습니다.


CNN
은 영상의 2차원 변환인 회전(Rotation), 크기(Scale), 밀림(Shearing), 반사(Reflection), 이동(Translation)와 같은 2차원 변환인 Affine Transform에 취약합니다.

, Affine Tranform으로 변환된 영상은 다른 영상으로 인식하므로, Data Generator를 사용하여 이미지에 변화를 주면서 컴퓨터의 학습자료로 이용하여 더욱 효과적이고 과적합을 방지하는 방식인, ImageDataGenerator으로 학습하도록 하였습니다.

 

ImageDataGenerator 사용

from tensorflow.python.keras.preprocessing.image import ImageDataGenerator
from keras.applications.mobilenet import preprocess_input

image_size = 224
batch_size = 32
seed = 100
datagen = ImageDataGenerator (
            rescale = 1./255, 
            shear_range=0.2,
            zoom_range=0.2,
            horizontal_flip=True,
            )

# load the data using data generators
train_generator  =    datagen.flow_from_directory(
                             train_dir,
                             seed=seed,
                             target_size = (image_size,image_size),
                             batch_size =batch_size ,               
                             class_mode = 'binary',
                            )

test_generator = datagen.flow_from_directory(
                             val_dir,
                             seed=seed, 
                             target_size = (image_size,image_size),
                             batch_size = batch_size ,               
                             class_mode = 'binary',
                            )

validation_generator = datagen.flow_from_directory(
                             test_dir,
                             seed=seed, 
                             target_size = (image_size,image_size),
                             batch_size = batch_size ,               
                             class_mode = 'binary',
                            )

from keras.models import Sequential
from keras.layers import Dense
from keras.layers import Dropout
from keras.layers import Flatten
from keras.layers.convolutional import Convolution2D
from keras.layers.convolutional import MaxPooling2D

seed = 100
np.random.seed(seed)

model=Sequential()

a=3

model.add(Convolution2D(32, kernel_size=(a, a), padding='same', strides=(1, 1), input_shape=(image_size, image_size, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2,2)))

model.add(Convolution2D(64, kernel_size=(a, a), padding='same',  activation='relu'))
model.add(MaxPooling2D(pool_size=(2,2)))

model.add(Convolution2D(128, kernel_size=(a, a), padding='same', activation='relu'))
model.add(MaxPooling2D(pool_size=(2,2)))

model.add(Convolution2D(256, kernel_size=(a, a), padding='same', activation='relu'))
model.add(MaxPooling2D(pool_size=(2,2)))

model.add(Flatten())

model.add(Dense(256,activation='relu'))
model.add(Dropout(0.5))

model.add(Dense(1,activation='sigmoid'))


model.compile(loss='binary_crossentropy',optimizer='adam',metrics=['accuracy'])


# Final evaluation of the model
scores = model.evaluate(test_generator, verbose=0)
print("loss: %.2f" % scores[0])
print("acc: %.2f" % scores[1])

'''
loss: 1.12
acc: 0.69
'''

 

 

Epoch10으로 하였을 때, ImageDataGenerator를 사용하지 않았을 때, acc = 0.75, 사용하였을때 acc =0.69로 사용하지 않았을 경우가 더 높게 나왔습니다.

좀 더 확실히 비교하기 위해 epoch20으로 늘려 테스트해보았습니다.

 

ImageDataGenerator 사용 X

Acc :0.71

 

ImageDataGenerator 사용 O

Acc :0.75

 

여러 차례 수행하였을 때 비슷하게 결과가 나왔습니다.

ImageDataGenerator를 쓰지 않은 경우가 속도가 더 빠르므로 ImageDataGenerator를 쓰지 않고 가장 좋은 결과가 나왔을 때, 그 경우로 ImageDataGenerator를 사용하여 비교해보기로 하였습니다.

 

 

Layer

먼저 flatten 전까지의 layer의 개수(feature (32) 동일,batch_size = 200)를 점차 늘려 보았습니다.


 [Layer4개 일 때]

 

[Layer5개 일 때 ]

 

[Layer6개 일 때]

 

[Layer7개일 때]

점점 lossacc가 안좋아지므로 layer 수는 5개가 가장 좋은 것으로 확인되었습니다.

 

그리고 feature의 수를 조절하려 하였습니다. Feature 갯수가 이렇게 많아지게 되면 컴퓨팅 속도가 저하되고 오버피팅의 위험이 생길 수 있으므로 적절한 feature 수가 무엇일지 생각하였습니다.

http://www.hellot.net/new_hellot/magazine/magazine_read.html?code=202&sub=&idx=42517의 글을 참조하여 ‌Krizhevsky - ‘ImageNet classification with deep convolution neural network’논문의 내용을 참고하여 feature수를 layer가 깊어질수록 증가시켰습니다.

 

Feature

[논문의 모델과 동일하게 구성]

 

 

 

[32->32->64->64->128]

 

 

 

[32->64->128->256->256]

 

 

 

[64->64->128->128->256]

 

점진적으로 증가되는 것이 좋은 결과를 보여주었습니다.

 

 

Batch_size

다음으로는 batch size를 늘려보았습니다.

[32]

 

 

[64]

 

 

[128]

 

 

 

[256]

 

 

 

[512]

 

 

[1024]

 

Batch size가 커질수록 좋아지는 것을 알 수 있었습니다.

 

 

하지만 일정 크기 이상으로 커질 경우

[2048]

 

좋지 않은 것을 알 수 있었습니다.

또한 https://blog.naver.com/qbxlvnf11/221449595336사이트의 글을 참조하여 batch size를 상대적으로 높이지만 너무 커지면 일반화 성능이 감소하므로, 적절히 값을 다른 데이터들을 바탕으로 종합적으로 모델을 만든 후 값을 바꾸어 가며 테스트를 하기로 하였습니다.

 

 

그 다음으로 kernel size를 조절하였습니다.

Kernel size는 작은 것을 여러 개 쓰는 방법이 좋으므로 5부터 1까지 테스트하였습니다

 

Kernel size

[5]

 

 

 

 

[4]

 

 

[3]

 

 

 

[2]

 

 

[1]

 

Kernel size1일 때 가장 좋은 결과를 보여주었습니다.

 

 

위 결과들을 바탕으로 layer를 구성하여 테스트하였습니다.

위 요소들을 섞어가며 테스트 중 batch size300이 넘어갈 경우 colab에서 ResourceExhaustedError 에러가 크게 하지 못하였습니다.

또한 세션이 다운되는 문제를 겪었습니다.

 

다른 요소로 정확도를 향상시키기 위해https://teddylee777.github.io/tensorflow/keras-%EC%BD%9C%EB%B0%B1%ED%95%A8%EC%88%98-vol-01를 참고하여 ReduceLROnPlateau를 사용하여 학습률을 동적으로 조정하였습니다.

 

여러 요소들을 조절해가며 테스트하였을 때 밑의 모델이 가장 좋은 예측력을 보여주었습니다.

 

결과

 

그리고 이 모델을 ImageDataGenerator를 사용하여 테스트하였습니다.

시간은 더 오래 걸리지만 확실히 더 좋은 성능을 보여주었습니다.

 

그 후 다시 한번 batch size feature, image_size, epoch를 조절해보았습니다.

하지만 0.87의 정확도를 넘어서지 않았습니다.

----------------------------------------------------------------------------------------------------

 

<최종>

from keras.models import Sequential
from keras.layers import Dense
from keras.layers import Dropout
from keras.layers import Flatten
from keras.layers.convolutional import Convolution2D
from keras.layers.convolutional import MaxPooling2D
from keras.utils import np_utils
import numpy as np
import matplotlib.pyplot as plt
import os
import cv2

from tensorflow.python.keras.preprocessing.image import ImageDataGenerator
from tensorflow.python.keras.preprocessing.image import load_img, img_to_array

import numpy as np
from pathlib import Path
import glob
import pandas as pd
from skimage.io import imread # reading image as data

data_dir = Path('chest_xray')

train_dir = data_dir / 'train'
val_dir = data_dir / 'val'
test_dir = data_dir / 'test'

normal_cases_dir = train_dir / 'NORMAL'
pneumonia_cases_dir = train_dir / 'PNEUMONIA'

'''
======================================================================================================================
'''
from tensorflow.python.keras.preprocessing.image import ImageDataGenerator
from keras.applications.mobilenet import preprocess_input

image_size = 224
batch_size = 256
seed = 100
datagen = ImageDataGenerator (
            rescale = 1./255, 
            shear_range=0.2,
            zoom_range=0.2,
            horizontal_flip=True,
            )

# load the data using data generators
train_generator  =    datagen.flow_from_directory(
                             train_dir,
                             seed=seed,
                             target_size = (image_size,image_size),
                             batch_size =batch_size ,               
                             class_mode = 'binary',
                            )

validation_generator = datagen.flow_from_directory(
                             val_dir,
                             seed=seed, 
                             target_size = (image_size,image_size),
                             batch_size = batch_size ,               
                             class_mode = 'binary',
                            )

test_generator = datagen.flow_from_directory(
                             test_dir,
                             seed=seed, 
                             target_size = (image_size,image_size),
                             batch_size = batch_size ,               
                             class_mode = 'binary',
                            )

from keras.models import Sequential
from keras.layers import Dense
from keras.layers import Dropout
from keras.layers import Flatten
from keras.layers.convolutional import Convolution2D
from keras.layers.convolutional import MaxPooling2D
model=Sequential()

a=3

model.add(Convolution2D(32, kernel_size=(a, a), padding='same', strides=(1, 1), input_shape=(image_size, image_size, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2,2)))

model.add(Convolution2D(64, kernel_size=(a, a), padding='same',  activation='relu'))
model.add(MaxPooling2D(pool_size=(2,2)))


model.add(Convolution2D(128, kernel_size=(a, a), padding='same', activation='relu'))
model.add(MaxPooling2D(pool_size=(2,2)))


model.add(Convolution2D(256, kernel_size=(a, a), padding='same', activation='relu'))
model.add(MaxPooling2D(pool_size=(2,2)))


model.add(Flatten())

model.add(Dense(256,activation='relu'))
model.add(Dropout(0.5))

model.add(Dense(1,activation='sigmoid'))

from keras.callbacks import ReduceLROnPlateau
learning_rate_reduction = ReduceLROnPlateau(monitor='val_loss', factor=0.3, patience=2, verbose=2, mode='auto')

model.compile(loss='binary_crossentropy',optimizer='adam',metrics=['accuracy'])

history = model.fit_generator(train_generator, epochs = 10, validation_data = validation_generator, callbacks = [learning_rate_reduction])

# summarize history for accuracy
plt.plot(history.history['accuracy'])

plt.plot(history.history['val_accuracy'])
plt.title('model accuracy')
plt.ylabel('accuracy')
plt.xlabel('epoch')
plt.legend(['train', 'validation'], loc='upper left')
plt.show()

# Final evaluation of the model
scores = model.evaluate(test_generator, verbose=0)
print("loss: %.2f" % scores[0])
print("acc: %.2f" % scores[1])

 

<그래프>

 

<model>

<epoch>

728x90
반응형

'공부 > 딥러닝' 카테고리의 다른 글

CIFAR-10 의 레이블중 하나를 예측  (0) 2021.05.09
classification 경진대회  (0) 2021.05.03
딥러닝 4  (0) 2020.10.29
딥러닝 3  (0) 2020.10.09
딥러닝 2  (0) 2020.09.29
블로그 이미지

아상관없어

,
반응형

이미지 파일을 업로드하면 CIFAR-10 의 레이블중 하나를 예측하여 보여주는 소프트웨어를 개발

예측 모델은 전이학습을 이용하여 만들고 CIFAR-10을 이용하여 학습

 

"""
Created on Sun Dec  6 02:22:39 2020

@author: Changmin
"""
from urllib.request import urlopen
from tkinter import *
import requests
from PIL import Image, ImageTk
from io import BytesIO

from keras.engine import Model

from keras.preprocessing.image import img_to_array

from tensorflow.keras.applications.efficientnet import preprocess_input

import io

def decode_pred(pred):
    arr = ['airplane','automobile','bird','cat','deer','dog','frog','horse','ship','truck']
    index = pred.argmax() #0,1
    #label = [arr[index], pred[0,index]]
    return arr[index]

def click():
    image_url = str.get()
    data = urlopen(image_url).read()
    image = Image.open(io.BytesIO(data))
    img = image.resize((400,300))
    
    img = ImageTk.PhotoImage(img)
    img_label.configure(image=img)
    img_label.photo = img
    img_label.grid(column=0,row=3, sticky = W+N)
    
    
    #이미지 예측#
    ##############################
    # load an image

    image = image.convert('RGB')
    image = image.resize((32,32), Image.NEAREST)
    
    # convert the image pixels to a numpy array
    image = img_to_array(image)
    
# reshape data for the model
    image = image.reshape((1, image.shape[0], image.shape[1], image.shape[2]))
    
    # prepare the image
    image = preprocess_input(image)
    
    
    # load model
    from keras.models import load_model
    model = load_model('epoch_80.h5')
    
    # predict the probability across all output classes
    pred = model.predict(image)
    
    # convert the probabilities to class labels
    answer = decode_pred(pred)
    
    
    L2 = Label(window, text="This image is {}".format(answer))
    L2.grid(column=1, row=3, sticky=W+S)
    
    window = Tk();
window.title("Image Classification")
window.geometry("1000x700+100+100")
window.resizable(True, True)


str = StringVar()
answer = StringVar()
L1 = Label(window, text="Image classification")
L1.grid(column=0,row=0, sticky=W)

textbox = Entry(window, width=50, textvariable=str)
textbox.grid(column=0,row=1)


img_label = Label(window,image="")

upload_Button = Button(window, width=10, text="Upload Image", fg='white', bg='blue', command = click)
upload_Button.grid(column=1,row=1, sticky = W)


window.mainloop();

 

<모델>

from keras import optimizers
from keras.datasets import cifar10
from keras.engine import Model
from keras.layers import Dropout, Flatten, Dense
from keras.utils import np_utils
import numpy as np

from keras.preprocessing.image import load_img
from keras.preprocessing.image import img_to_array
from tensorflow.keras.applications.efficientnet import preprocess_input, decode_predictions

from tensorflow.keras.applications import EfficientNetB0

def decode_pred(pred):
    arr = ['airplane','automobile','bird','cat','deer','dog','frog','horse','ship','truck']
    index = pred.argmax() #0,1
    label = [arr[index], pred[0,index]]
    return label

#이미지 예측#
##############################

img_width, img_height = 32, 32

#top false => top layer 삭제
base_model = EfficientNetB0(weights='imagenet', include_top=False, input_shape=(32, 32, 3), drop_connect_rate=0.4)

nb_epoch = 80 # 50 is good
nb_classes = 10

# load dataset
(X_train, y_train), (X_test, y_test) = cifar10.load_data()
y_train = np_utils.to_categorical(y_train, nb_classes)
y_test = np_utils.to_categorical(y_test, nb_classes)

# Extract the last layer from third block of model
last = base_model.get_layer('top_activation').output

# Add classification layers on top of it
x = Flatten()(last)
x = Dense(256, activation='relu')(x)
x = Dropout(0.5)(x)
output = Dense(10, activation='softmax')(x)
    
model = Model(inputs = base_model.input, outputs= output)
    
    
model.compile(loss='binary_crossentropy', optimizer=optimizers.SGD(lr=1e-3, momentum=0.9), metrics=['accuracy'])
model.summary()
model.fit(X_train, y_train, validation_data=(X_test, y_test), epochs =nb_epoch, batch_size=64, verbose=1)

# Final evaluation of the model
scores = model.evaluate(X_test, y_test, verbose=0)
print("loss: %.2f" % scores[0])
print("acc: %.2f" % scores[1])

#  모델 저장하기
from keras.models import load_model
model.save('epoch_80.h5')


from google.colab import files
files.download('epoch_80.h5') 


 

 

실행화면

 

모델을 만들 때 efficientnet 모델을 사용하였지만, 소요되는 시간이 너무 많았다.

 

그래서 방법을 찾던중 colab에서 gpu로 코드를 돌릴 수 있다는 것을 알게되었고, 5시간 정도의 작업이 30분정도로 줄어들어 epoch을 더 늘려 높은 정확도를 얻을 수 있었다.

파이썬 GUI를 처음 사용하면서 url로 불러온 이미지를 어떻게 처리할지 어려웠는데, Byte단위로 읽어와 처리해주고, 표시되는 이미지를 resize하여 동일한 크기로 보이게 하여 gui로 나타낼 때 좀더 간결하게 표현하였다.

 

또한 decode_prediction1000개의 이미지에 맞추어져 있다는 사실을 까먹고 자꾸 이상한 값이 나와 이 문제를 해결하는데 시간이 많이 소요되었다.

728x90
반응형

'공부 > 딥러닝' 카테고리의 다른 글

흉부 X-ray 사진으로 폐렴 진단 모델  (0) 2021.05.09
classification 경진대회  (0) 2021.05.03
딥러닝 4  (0) 2020.10.29
딥러닝 3  (0) 2020.10.09
딥러닝 2  (0) 2020.09.29
블로그 이미지

아상관없어

,
반응형

- trainset.csv 파일을 이용하여 classification 모델 생성

- 모델을 이용하여 testset.csv 파일의 자료에 대한 class 예측

 

trainset.csv

(A열이 class label이다.)

 

testset.csv

 

- 예측결과 포맷

=========================================================================

model development process[Feature Selection -> Algorithm Selection -> Hyper parameter tuning] 순이므로, 먼저 어떠한 Feature을 고를 것인지 결정하였습니다.

Feature Selection 방법으로 강의에서 배운 filter method, backward elimination, forward selection 세가지 방법으로 테스트를 하였습니다. Feature selection을 하기 위해 model을 선택하여야 했는데, 이는 강의에서 배운 model comparison을 통하여 선정하였습니다.

기존에 배운 분류 알고리즘인 DecisionTreeClassifier, KNeighborsClassifier, RandomForestClassifier, SVC 외에 검색을 통하여 몇 가지 알고리즘을 추가하였습니다. 자주 사용되는 Xgboost, xgboost의 느린 단점을 보완한 LightGBM을 추가하여 비교를 하였습니다. (pip install 명령어를 사용하여 설치함)

5번 반복하여 비교한 결과 RandomForestxgboost, LightGBM이 모델 변동폭이 작고 정확도도 높은 것을 알 수 있어 이 3가지 모델을 사용하여 비교해보기로 하였습니다.

from sklearn.model_selection import RandomizedSearchCV
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import train_test_split
from xgboost import plot_importance

# Model comparison 
import matplotlib.pyplot as plt
from sklearn import model_selection

# from sklearn.linear_model import LogisticRegression
from sklearn.tree import DecisionTreeClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.svm import SVC
from xgboost import XGBClassifier
from lightgbm import LGBMClassifier
from sklearn.preprocessing import LabelEncoder
from sklearn.model_selection import KFold
from sklearn.metrics import accuracy_score
import pandas as pd
import numpy as np
import pprint as pp

#1. 데이터 셋 준비
data = pd.read_csv('C:\dataset/trainset.csv')

#2. 설명변수 반응 변수 나눔
data_x = data.iloc[:, 1:32]
data_y = data.iloc[:, 0]

# train, test 나눔
train_X, test_X, train_y, test_y = train_test_split(data_x, data_y, test_size=0.3,random_state=1234) 



# prepare configuration for cross validation test harness
seed = 7

# prepare models
models = []
models.append(('KNN', KNeighborsClassifier()))
models.append(('DT', DecisionTreeClassifier()))
models.append(('RF', RandomForestClassifier()))
models.append(('SVM', SVC()))
models.append(('xgboost', XGBClassifier()))
models.append(('LGBM', LGBMClassifier()))
results = []
names = []
scoring = 'accuracy'

for name, model in models:
    kfold = model_selection.KFold(n_splits=10, random_state=seed, shuffle=True)
    cv_results = model_selection.cross_val_score(model, data_x, data_y, cv=kfold, scoring=scoring)
    results.append(cv_results)
    names.append(name)
    msg = "%s: %f (%f)" % (name, cv_results.mean(), cv_results.std())
    print(msg)
    
print(results)

# average accuracy of classifiers
for i in range(0,len(results)):
    print(names[i] + "\t" + str(round(np.mean(results[i]),4)))
    
# boxplot algorithm comparison
fig = plt.figure()
fig.suptitle('Algorithm Comparison')
ax = fig.add_subplot(111)
plt.boxplot(results)
ax.set_xticklabels(names)
plt.show()

그리고 filter method, backward elimination, forward selection을 통하여 feature을 선정하였습니다.

(먼저 데이터 셋의 column name이 없어 0부터 숫자를 순서대로 할당하여 보기 편하게 하였습니다. Backward n_features_to_select=4, Cv=5)

 

[모델 선택하기 위해 비교]

 

LighGBM의 경우

[filter method]

“0.9159”

[backward elimination]

“0.7869”

 

[forward selection]

“0.871”

 

 

 

 

RandomForest의 경우

[filter method]

“0.909”

[backward elimination]

“0.849”

 

[Forward selection]

“0.871”

 

 

 

 

 

Xgboost의 경우

[filter method]

“0.907”

 

[backward elimination]

“0.850”

 

[Forward selection]

“0.872”

 

각기 다른 모델을 사용해도 feature의 중요도는 바뀌질 않으니 빠른 lightGBM 모델로 backward, forward selection에서 각 인자 n_features_to_select, k_features의 수를 filter method 에서 얻은 데이터를 바탕으로 수정하여 한번 더 테스트 하였습니다.

Filter method의 결과를 보면 선택하는 feature의 수가 많아질수록 정확도가 높아지므로 개수를 크게 변화가 없어지는 21개부터 30개까지 테스트를 해보았습니다.

하지만 forward selction을 할 경우 시간이 오래 걸리고 컴퓨터도 간헐적으로 멈추어 backward elimination으로 테스트하였습니다.

 

 

# Feature selection Example
import pandas as pd
import numpy as np
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import cross_val_score

from sklearn.tree import DecisionTreeClassifier
from sklearn.neighbors import KNeighborsClassifier

from sklearn.ensemble import RandomForestClassifier
from sklearn.svm import SVC
from sklearn.preprocessing import LabelEncoder
#from xgboost import XGBClassifier
from lightgbm import LGBMClassifier

#1. 데이터 셋 준비
name = []
for i in range(0,32):
    name.append(i)  
data = pd.read_csv('C:\dataset/trainset.csv', names = name)
print(data.head())
#2. 설명변수 반응 변수 나눔
data_x = data.iloc[:, 1:32]
data_y = data.iloc[:, 0]
# whole features
model = LGBMClassifier()
scores = cross_val_score(model, data_x, data_y, cv=5)
print("Acc: "+str(scores.mean()))
print('######################################################################')
print('# feature selection by filter method')
print('######################################################################')
######################################################################
# feature selection by filter method
######################################################################
# feature evaluation method : chi-square
from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import chi2
test = SelectKBest(score_func=chi2, k=data_x.shape[1])
fit = test.fit(data_x, data_y)

# summarize evaluation scores
print(np.round(fit.scores_, 3)) #소수점 3자리까지 반올림
f_order = np.argsort(-fit.scores_) # sort index by decreasing order
sorted_columns = data.columns[f_order]
f_order
data_x.shape[1]
# test classification accuracy by selected features
model = XGBClassifier()

for i in range(0, data_x.shape[1]):
    fs = sorted_columns[0:i]
    data_x_selected = data_x[fs]
    scores = cross_val_score(model, data_x_selected, data_y, cv=5)
    print(fs.tolist())
    print(np.round(scores.mean(), 4))

'''
for i in range(20, 31):
    
    print('index = ', i)
'''
    ######################################################################
    # Backward elimination (Recursive Feature Elimination)
    ######################################################################
    from sklearn.feature_selection import RFE
    
model = LGBMClassifier()
    rfe = RFE(model, n_features_to_select=i)
    fit = rfe.fit(data_x, data_y)
    print("Num Features: %d" % fit.n_features_)
    fs = data_x.columns[fit.support_].tolist() # selected features
    print("Selected Features: %s" % fs)
    scores = cross_val_score(model, data_x[fs], data_y, cv=5)
    print("Acc: "+str(scores.mean()))



    print('######################################################################')
    print('# Forward selection')
    print('######################################################################')
    ######################################################################
    # Forward selection
    ######################################################################
    # please install 'mlxtend' moudle
    from mlxtend.feature_selection import SequentialFeatureSelector as SFS
    model = LGBMClassifier()
    sfs1 = SFS(model, k_features=i, n_jobs=-1, scoring='accuracy', cv=5)
    sfs1 = sfs1.fit(data_x, data_y, custom_feature_names=data_x.columns)
    sfs1.subsets_ # selection process
    sfs1.k_feature_idx_ # selected feature index
    print(sfs1.k_feature_names_)# selected feature name
    
    

Backward elimination을 하였을 때

 

Feature25개 사용하면 정확도가 0.9165으로 가장 좋았지만, 나머지와 비교하였을 때 filter method도 그러하듯이 feature 개수에 따른 큰 차이를 보여주지 못하여 테스트 시 모든 feature들을 사용하기로 결정하였습니다.

 

이제 hyperparameter 튜닝을 하기 전 각 모델별로 테스트를 해보았다.

 

Feature을 선정하기 위한 과정에서 model도 함께 선정하였으므로 다음으로 hyperparameter tuning을 진행하였습니다. Hyper parameter를 찾기 위해 RandomizedSearchCV 방법을 사용하였습니다.

 

(다른 최적화 방법 BaysianOptimizaion을 찾았으나 정확한 사용법을 익히지 못하여 RandomizedSearchCV 방법을 사용하였습니다.

또한 autosklearn을 통하여 최적의 모델을 찾고 hyper parameter 최적값을 찾는 과정을 자동으로 해주려 하였으나, 다음의 글을 찾아Anaconda does not ship auto-sklearn, and there are no conda packages for auto-sklearn” 이 방법은 해보지 못하였습니다.

-Xgboost

max_depth(int, default: 3): 기본 학습자를 위한 최대 트리 깊이

learning_rate(float, default: 0.1) : Boosting 학습률

n_estimators(int, default: 100) : fit하기 위한 Boosted tree

silent(boolean, default: True : Boosting 실행하는 동안 메시지를 print할지 여부

objective(string or callable, default:’reg:linear’) : 학습할 Objective Function 사용

booster(string, default: ‘gbtree’): Booster 사용할 모드 gbtree, gblinear, dart

nthread(int, default: ‘None’): xgboost 실행하는데 사용할 병렬 스레드

- xgboost.XGBClassifier(nthread=20)

n_jobs(int, default: 1): xgboost 실행하는데 사용할 병렬 스레드

gamma(float, default: 0): 트리의 leaf 노드에 추가 파티션(partition) 만들때 최소 손실 감소(Minimum loss reduction) 필요하다.

min_child_weight(int, default: 1): Child 노드에 필요한 instance weight(hessian) 최소 합계

max_delta_step(int): Tree 가중치(Weight) 추정을 허용하는 최대 Delta 단계

subsample(float): 학습(Training) Instance Subsample 비율

colsample_bytree(float): Tree 구성할 column Subsample 비율

colsample_bylevel(float): Tree Level에서 분할(split) 대한 column Subsample

 

처음햇을 때

 

max_depth를 늘리니 향상되는 것을 알 수 있었다.

따라서 max_depth를 더 늘려 테스트해보려 하였지만, 실수로 n_estiators np.linspace(start = 200, stop = 10000, num = 21)와 같이 늘려서 테스트 하였다.

시간은 2시간 가량 걸렸지만, n_estimators의 값은 크게 영향이 없다는 것을 알았다.

Max_depth값이 늘어났을 때 성능이 향상되는 것을 알 수 있었다.

 

np.linspace(4000, 10000, num = 11)로 바꾸어 하였을 때,

비슷한 향상 폭을 보여주었다.

 

 

-RandomForest

예제코드와 같이 실행을 하면

1.21%의 향상을 얻을 수 있었습니다.

 

위와 같이 각 모델에 대해 HyperParameter를 진행하려하였으나,

tuningparameter들의 수가 많고 tuning을 하는 과정도 상당한 시간이 걸려,

시간 비용을 줄이고자 분산이 적고 예측력이 세가지 모델 중 가장 좋은 LightGBM을 선택하여 hyper parameter tuning을 하고 테스트를 진행하였습니다.

=========================================================================

 

초반에는 여러 데이터들의 범위를 바꾸어 가면서 테스트를 하였습니다.

2000 candidates를 하였지만 시간대비 좋지 않은 결과를 얻었다.

Xboost에서 max_depth가 커지면서 좋아진 것을 보고 LightGBM에서도 값을 크게 잡아서 테스트를 하였다.

Candidates100이지만 성능이 더 좋아진 것으로 보아 candidate를 크게 잡을 필요가 없다고 생각하였습니다.

 

그리고 num_leaves를 바꾸어 테스트하였으나 결과에 변화가 없는 것으로 보아 num_leaves는 큰 영향을 끼치지 않는 것으로 확인했다.

min_data_in_leaf가 커지면 향상 폭이 줄어드는 것을 확인하였다.

 

따라서 max_depth가 크면 향상 폭이 가장 좋아지는 것으로 판단하였다.

parameter들을 범위를 넓혀 가면서 테스트를 하였다.

범위를 넓게 한 경우

 

그리고 default parameter를 사용할 때와 0.82%의 향상이 있었던 파라미터를 사용하여 테스트해보았습니다.

Default의 경우 0.93이 나왔고, 향상된 파라미터를 사용할 경우 0.90으로 줄어들었습니다. 과적합이 의심되어 max_depth값을 낮추어 다시 테스트하니 0.93이 나온 것을 알 수 있었습니다. 따라서 과적합과 같은 경우를 고려하기 위하여 과적합을 줄일 수 있는 요소를 찾아보았습니다.

https://greeksharifa.github.io/machine_learning/2019/12/09/Light-GBM/http://machinelearningkorea.com/2019/09/29/lightgbm-%ED%8C%8C%EB%9D%BC%EB%AF%B8%ED%84%B0/를 참고하여 사용할 파라미터를 선정하였습니다.

 

그리고 여러 parameter들을 종합적으로 테스트를 하면 각 요소들이 얼만큼 차이를 내는지 파악하기 힘들어 parameter 하나씩 테스트를 하였습니다.

 

 

다음과 같이 범위를 좁혀나가며 best Parameter에 근접한 범위로 좁혀가면서 최적 값을 찾아보았습니다. 그리고 과적합을 조절할 파라미터들은 max_depth와 함께 테스트하였습니다.

하지만 다른 파라미터들과 함께 테스트하였을 때 좋지 않은 결과를 보여주기도 하였습니다.

 

사이트를 통하여 테스트시 0.93

 

 

적절한 max_depth를 찾으려 하였으나, 초기에 max_depth값 테스트를 해보기위해 설정했던 max_depth = 90, learning_rate = 0.1, n_estimators = 300이 가장 좋은 결과를 보여주었습니다. 아마 과적합이 일어나면서 확률이 좋아진 것으로 예상합니다. 과적합을 줄이면서 좋은 성능을 내는 파라미터를 찾기 어려웠습니다. 따라서 n_iter의 값을 늘리고 max_depth, n_estimators의 값을 줄여서 테스트 하였습니다.

여러 번 testset으로 예측한 결과 max_depthlearning_rate, n_estimators의 값을 변경한 경우가 0.93으로 더 좋은 예측을 보여주어 다른 값보다 이 3가지 값을 변경시켜 더 테스트 해보기로 하였습니다. 범위를 넓히고 과적합을 줄이기 위해 범위를 줄이면서, n_iter1000으로 늘려 여러 값들을 테스트해보았습니다.

그래도 변화가 없어 0.43%가 나왔던 범위를 선택하고 나머지 parameter들을 추가하여 다시 테스트해 보았습니다. 

0.92로 향상은 없었습니다.

Hyper parameter값들을 여러가지로 조정해보고 testset을 적용하여 정확도를 보았을때, acc : 0.929039301310044 가 가장 좋은 결과를 보여주었습니다.

 

###HYPERPAMETER TUNING####
from sklearn.model_selection import RandomizedSearchCV
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import train_test_split
# Model comparison 
import matplotlib.pyplot as plt
from sklearn import model_selection
# from sklearn.linear_model import LogisticRegression
from sklearn.tree import DecisionTreeClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.svm import SVC
from sklearn.preprocessing import LabelEncoder
from xgboost import XGBClassifier
import lightgbm as lgb
from lightgbm import LGBMClassifier
from bayes_opt import BayesianOptimization
from hyperopt import fmin, tpe, hp

import pandas as pd
import numpy as np
import pprint as pp

'''
HI, PH, GR, PH, EL, MI, PH, MI, CO, EL, GR....
1. feature selecion

2. algorithm selection

3. hyper parameter tuning
randomizedserchcv 가 조합을 자동으로 골라주고, 시간이 줄어드므로 사용함.
'''

#1. 데이터 셋 준비
data = pd.read_csv('C:\dataset/trainset.csv')

#2. 설명변수 반응 변수 나눔
data_x = data.iloc[:, 1:32]
data_y = data.iloc[:, 0]

data_x
# train, test 나눔
train_X, test_X, train_y, test_y = train_test_split(data_x, data_y, test_size=0.3, random_state=1234) 


base_model = LGBMClassifier(random_state=1234)
base_model.fit(train_X, train_y)
base_accuracy = base_model.score(test_X, test_y)
print(base_accuracy)

n_estimators = [int(x) for x in np.linspace(start = 200, stop = 600, num = 41)]
# Maximum number of levels in tree
max_depth = [int(x) for x in np.linspace(1, 400, num = 41)]
#하나의 트리가 가지는 최대 리프 개수
#num_leaves = [int(x) for x in np.linspace(2, 1000, num = 31)]

#리프 노드가 되기 위한 최소한의 샘플 데이터 수
#min_child_samples  = [int(x) for x in np.linspace(1, 100, num = 11)]

learning_rate = [float(x) for x in np.linspace(0.000001, 0.5, num = 41)]



#데이터 샘플링 비율 0이되면 안됨
#bagging_fraction = [float(x) for x in np.linspace(0.1, 1, num = 11)]

#개별 트리 학습시 선택되는 피처 비율 - 과적합 방지
#feature_fraction = [float(x) for x in np.linspace(0.000001, 1, num = 11)]

#과적합을 제어하기 위해 데이터를 샘플링하는 비율
#subsample  = [float(x) for x in np.linspace(0.000001, 1, num = 11)
#metric = ['multiclass']

# Create the random grid
random_grid = {'n_estimators' : n_estimators,
               'max_depth' : max_depth,
               #'feature_fraction': feature_fraction,
               #'subsample' : subsample,
               'learning_rate' : learning_rate
               #'bagging_fraction' : bagging_fraction,
               #'num_leaves' : num_leaves,
               #'min_child_samples' : min_child_samples,
              # 'metric' : metric
               }

pp.pprint(random_grid)


'learning_rate' : learning_rate
               #'bagging_fraction' : bagging_fraction,
               #'num_leaves' : num_leaves,
               #'min_child_samples' : min_child_samples,
              # 'metric' : metric
               }

pp.pprint(random_grid)

# Use the random grid to search for best hyperparameters
rf = LGBMClassifier(random_state=1234)
rf_random = RandomizedSearchCV(estimator = rf, param_distributions = random_grid, n_iter = 1000, cv = 5, verbose=2, random_state=42, n_jobs = -1)

# Fit the random search model
rf_random.fit(train_X, train_y)

# best parameters
# best_params에 최적 조합이 저장됨
pp.pprint(rf_random.best_params_)


# best model
#best_estimator => 최적 조합을 적용해서 만들어진 모델
best_random_model = rf_random.best_estimator_
best_random_accuracy = best_random_model.score(test_X, test_y)

print('base acc: {0:0.2f}. best acc : {1:0.2f}'.format( \
base_accuracy, best_random_accuracy))
print('Improvement of {:0.2f}%.'.format( 100 * \
(best_random_accuracy - base_accuracy) / base_accuracy))

 

 

######testset save to csv#######
from lightgbm import LGBMClassifier
import pandas as pd
import numpy as np

#1. 데이터 셋 준비
data = pd.read_csv('C:\dataset/trainset.csv', header=None)
test_x = pd.read_csv('C:\dataset/testset.csv', header=None)

data.shape
test_x.shape
#2. 설명변수 반응 변수 나눔
data_x = data.iloc[:, 1:32]
data_y = data.iloc[:, 0]

data_x
data_y

model = LGBMClassifier(learning_rate = 0.1, max_depth = 90, n_estimators = 300)
model.fit(data_x, data_y)

pred_y = model.predict(test_x)

result = pd.DataFrame(pred_y)
result.to_csv('lightgbm.csv', header=None, index=False)

 

 

후기)

먼저 그래프로 모델을 비교하여 해당 데이터에 어떤 모델이 가장 잘 맞는지 고르는 것이 전반적인 예측율에 많은 영향을 끼친다고 느꼈다. 그리고 적절한 feature을 찾기 위해 시간이 빠른 모델을 사용하여 테스트를 하면 시간을 줄일 수 있고 hyper parameter를 찾기 위한 여러가지 방법들을 알게 되었다.

 

이번 경진대회에서는 RandomizedSearchCV를 사용하였다. 이 방법으로 적절한 hyper parameter를 찾기 위해 parameter 별로 값을 바꾸어 테스트를 해보고, 여러 parameter들을 동시에 바꾸어 가며 테스트를 하였다.

또한 n_iter을 높일수록 과적합을 줄여 향상이 더 줄어들 수 있다는 것도 알게 되었다. 하지만 적절한 값을 찾는 것이 매우 힘들었다. Parameter를 바꿀 때 이것이 향상되었는지 과적합인지, 과소적합인지를 구분하기가 힘들었다.

처음에 1.38%의 향상을 보았지만 그 값은 과적합으로 인해 예측은 좋지 못하였고, 오히려 max_depth를 낮추니 결과가 좋아지는 경우를 보았다. 또한 test_size 비율을 바꿔가며 나온 결과값을 테스트해보았지만 좋은 결과를 얻기는 어려웠다.

따라서 이런 튜닝을 하는 과정은 소모적이며 때론 2시간 이상이 걸릴 만큼, 시간이 많이 들고 적절한 값을 찾는 것은 감에 의존하고 우연에 의존한다는 생각을 하였다. 이런 과정을 편하게 해주는 방법들이 없을까 찾아보았고, hyper parameter가 변경될 때마다 정확도의 변화를 그래프로 보여주던가, 과적합을 판단할 수 있게 과적합 수치도 함께 보여준다면 더 편리할 것이라 생각하였다.

 

AutoML은 데이터의 특성에 따라 좋은 알고리즘과 어울리는 파라미터들을 자동화하여 찾아준다.

그 중 Auto-sklearn라는 방법이 있다. 데이터가 들어오면, 데이터에 맞을만한 알고리즘, parameter를 알려주는 meta-learning process를 진행하고 이 결과로 알고리즘과 parameter set들을 추천해 준다. 그 후 앙상블 기법을 활용해 추천된 알고리즘, parameter set들의 최적화를 진행합니다. 하지만 Anaconda does not ship auto-sklearn, and there are no conda packages for auto-sklearn” 와 같은 답변을 얻어 실제로 해보진 못하였다.

그리고 Bayesian Optimization을 통하여 hyper parameter의 최적값을 탐색할 수 있다. Bayesian Optimization은 매 회 새로운 hyper parameter값에 대한 조사를 수행할 시, 사전지식을 충분히 반영하면서 전체적인 탐색 과정을 체계적으로 수행할 수 있는 방법론이다. 따라서 이 방법을 통하여 hyper parameter를 찾으려 하였다. 하지만 완벽히 이해하지 못하였고, 관련 자료를 많이 찾지 못하여 사용법과 에러에 대한 원인을 찾지 못하였다.

728x90
반응형

'공부 > 딥러닝' 카테고리의 다른 글

흉부 X-ray 사진으로 폐렴 진단 모델  (0) 2021.05.09
CIFAR-10 의 레이블중 하나를 예측  (0) 2021.05.09
딥러닝 4  (0) 2020.10.29
딥러닝 3  (0) 2020.10.09
딥러닝 2  (0) 2020.09.29
블로그 이미지

아상관없어

,

딥러닝 4

공부/딥러닝 2020. 10. 29. 01:34
반응형

#Artificial Neural Network

History

  • 1943년 Warren McCulloch, Walter Pitts가 제안
  • 1950년대 Perceptron 나옴(응용 가능할만해짐 하지만 선형분리만 가능
  • 1990년대 Multi-layered Perceptron(선형 분리문제 해결했지만 층을 많이 쌓으면 잘 안되는 문제점)
  • 요즘 Deep Neural Network
  • 거의 산업 전 분야에 적용됨.

개념

입력층, 은닉층, 출력층으로 구분됨

 

은닉층의 개수에 따라 분류 가능

 

층을 많이 쌓을수록 복잡한 문제들을 학습가능하지만 시간이 오래걸림

 

 

에러 : 예측값(0~1사이 값)과 정답의 차이

에러가 발생한 부분만큼을 feedback함

노드의 선들에 weight가 있음

 

모델은 구조 + weight값으로 정의가능

 

 

Perceptron

 

가장 단순한 형태의 신경망

다수의 신호를 입력으로 받아들여 하나의 신호(원하는)를 출력하는 알고리즘

 

 

Machine learning by perceptron

 

다음의 데이터로 가중치, 편항, 활성함수를 구해야함.

 

 

- weight value

 

전기회로의 저항과 유사하지만 인공신경망에서는 weight value가 크면 입력값이 출력에 많이 전달되고, 작으면 입력값이 출력에 적게 전달된다.

만약 x1은 큰값이고, x2는 작은 값일 경우, x1w1 + x2w2할 경우 x2가 잘 반영이 되지 않는다.

 

- 편향

 

b값에 따라 y값이 0또는1에 치우친 값이 나오므로 편향이라고 함.

만약 환자 = 0, 정상인 = 1로 진단하는 인공 신경망이 있을 때, 환자를 정상인으로 오인하는 것을 막기위해 |b|값을 크게 함 => 정상인이라는 증거가 충분히 클때만 정상인으로 판단

 

* weight = 각각의 입력신호가 출력에 영향을 주는 정도 조절

* bias(편향) = 뉴런이 얼마나 쉽게 활성화 되는지를 조절

 

예를 들어 and 연산을 구하는 인공신경망을 어떻게 만드는가?

머신러닝으로 weight, bias, 임계점 구함

 

 

Design of neural network

input node의 수는 feature의 수이다.

output node의 수는 class의 수이다.

 

 

4개의 클래스를 구분하기 위해선

|0|0|1|1|                                    |1|0|0|0| =>1

|0|1|0|1|                                    |0|1|0|0| => 2

 |  |  | |                                     |0|0|0|1| => 3

 |  |  | |                                    |0|0|0|1|  => 4

 v v v v                                   

1, 2, 3, 4

 

처음의 경우가 아닌 뒤의 경우로 4가지 클래스를 구분한다.

 

인공신경망을 설계할때

1. 히든 레이어의 수

2. 히든 레이어 별 노드수

3. 활성함수(모든 레이어마다)

4. bias 값

을 구해야 할 것이다.

 

곱셈연산을 하므로 값이 1 이상이 나오지않게 각 노드들의 값은 0~1사이이다.

 

선형분리 문제만 해결가능한 것을 극복하기 위해 다층 perception을 사용한다.

728x90
반응형

'공부 > 딥러닝' 카테고리의 다른 글

CIFAR-10 의 레이블중 하나를 예측  (0) 2021.05.09
classification 경진대회  (0) 2021.05.03
딥러닝 3  (0) 2020.10.09
딥러닝 2  (0) 2020.09.29
딥러닝 1  (0) 2020.09.25
블로그 이미지

아상관없어

,

딥러닝 3

공부/딥러닝 2020. 10. 9. 17:12
반응형

Learing for classification => class를 나누는 경계선을 찾는 문제였음

경계선을 직선으로 할 경우 오류가 많지만 곡선으로 할 경우 오류가 줄어들음

Scikit-learn classifiers

  • Logistic regression
  • KNN'
  • Support Vector Machine (SVM)
  • Naive Bayes
  • Decision Tree
  • Random Forest
  • AdaBoost
  • xgboost(Not in scikit-learn)

여러 classifier들이 있지만, 어떤 방법이 현재 가지고 있는 데이터에 대해 가장 효과적인지 사전에 알 수 없다. 따라서 모든 방법을 해보고 그 중에 좋은 것을 선택해야한다.

1. Decision Tree


  • 큰 문제를 작은 문제들의 조각으로 나누어 해결한다.
  • 예측을 위한 모델이 만들어졌을때, Tree의 형태로 나온다.
  • Tree형태이기때문에 결론이 나온 이유를 이해하기 쉽다. => 예측 결과에 대해서 근거가 명확하다
  • 예를 들면 의료분야에서 질병진단시 근거가 명확해야한다.

1.1 Decision Tree 예시


  • 영화 대본 및 기본 정보를 이용하여 영화가 흥행할지 예측하는 모델
  • 유명 배우수와 추정 제작비로 예측
  • 결과는 매우흥행, 어느정도 흥행, 폭망으로 3가지로 구분

  1. 특정 class와 다른 class를 가장 잘 구분할 수 있는 선을 찾는다. 하지만, 잘못 예측한 경우도 있다.

  1. 다른 class를 다시 구분하는 선을 찾는다. 잘못 예측한 것들이 있지만 최선이다.

  1. 결과

1.1.1 문제점


  • 트리의 node를 선택 할 때 데이터 셋에서 어떤 속성을 선택할 것인가?
    => 이전 영화문제에서는 유명배우가 많으면서 예산이 적어야 성공한 영화였다. 그러면 스타급 배우수가 먼저인가? 예산이 먼저인가?

사진과 같이 class가 겹치는 부분이 적은 것을 선택한다.

  • 트리를 split할 때 언제 중단할 것인가?
    => 트리의 가지를 계속 뻗어나가면 모든 instance를 100%t식별 할 수 있다. 하지만 overfitting발생

적당할 때 트리생성을 중단 해야한다. -> 가지치기(pruning)
경계선을 많이 나누면 이론상으로 100% 예측 가능한 tree를 만들 수 있다. 하지만 test 정확도는 낮다.

1.1.2 장점


  • 모든 문제에 적합
  • 결측치, 명목속성(범주), 수치속성을 처리하기에 용이
  • 여러 속성중 중요한 속성들만 사용하여 예측
  • 매우 많은 수 또는 상대적은 훈련 데이터로도 모델 구축 가능
  • 수학적 배경이 없이도 해석이 가능한 모델
  • 단순한 이론적 근거에 비해 높은 효율성

1.1.3 단점


  • 결정 트리는 다수의 레이블을 가진 속성쪽으로 구분하는 경향이 잇음
  • 모델이 쉽게 과적합(overfitting)하거나 과소적합(underfitting) 됨
  • 축에 평행한 구분선을 사용하기 때문에 일부 관계를 모델화 하는데 문제가 있다.
  • 훈련 데이터에 대해 약간의 변경이 결정 논리에 큰 변화를 준다.
  • 큰 트리는 이해하기 어렵고 직관적이지 않다.

1.1.4 코드


예시) liver.scv (간 장애 자료, 레이블 + 혈액검사 결과(6개 변수))

category
mcv
alkphos
sgpt
sgot
gammagt
drinks

category = 클래스 정보. 0 : 정상 1 : 간장애

  1. 데이터 셋 준비
  2. 설명변수/반응변수 구분
  3. train/test 셋 나눔
  4. 모델 만듬
  5. 모델 training
  6. 튜닝
from sklearn.tree import DecisionTreeClassifier, export_graphviz //export_graphviz는 tree시각화에 필요
from sklearn.model_selection import train_test_split
from sklearn.metrics import confusion_matrix
import pandas as pd
import pydot # need to install

#1. 데이터 셋 준비
# prepare the iris dataset
df = pd.read_csv('D:/data/liver.csv')
print(df.head())
print(df.columns) # column names

#2. 설명변수/반응변수 구분
df_X = df.loc[:, df.columns != 'category']
df_y = df['category']

#train/test 셋 나눔
# Split the data into training/testing sets
train_X, test_X, train_y, test_y = \
train_test_split(df_X, df_y, test_size=0.3,\
random_state=1234) 
#4. 모델 만듬
# Define learning model (basic)
model = DecisionTreeClassifier(random_state=1234)

#5. 모델 학습
# Train the model using the training sets
model.fit(train_X, train_y)

# performance evaluation
print('Train accuracy :',model.score(train_X, train_y))
print('Test accuracy :',model.score(test_X, test_y))

#6. 튜닝
# Define learning model (tuning)
model = DecisionTreeClassifier(max_depth=4, random_state=1234)

# Train the model using the training sets
model.fit(train_X, train_y)

# performance evaluation
print('Train accuracy :',model.score(train_X, train_y))
print('Test accuracy :',model.score(test_X, test_y))

### 튜닝 후 test 정확도가 69%로 더 좋아진 것을 알 수 있다. 그러므로 매개변수를 잘 조절하면 모델의 성능이 좋아진다.

 visualize tree
export_graphviz(model, out_file='tree_model.dot', feature_names =
train_X.columns, class_names = 'category’, rounded = True,
proportion = False, precision = 2, filled = True)
(graph,) = pydot.graph_from_dot_file('tree_model.dot’,
encoding='UTF-8')
graph.write_png('decision_tree.png') # save tree image

#from IPython.display import Image
#Image(filename = 'decision_tree.png')

1.1.5 Hyper parameters


모델을 만들 때, 모델의 성능에 여향을 끼치는 매개변수들이다.
따라서 Hyper parameter를 어떻게 조절하냐가 중요하다. 그러나 매개변수가 20개 가까이 되므로 다 조절하기는 힘들다.
그러므로 몇개의 자료로 추린다.

  • criterion : String, optional (default = "gini")
    Decision Tree의 가지를 분리 할 때, 어떤 기준으로 정보 획득량을 계산하고 가지를 분리 할 것인지 정함
    gini = entropy보다 빠르지만 한쪽으로 편향된 결과를 낼 수 있음
    entropy = gini에 비해 조금 더 균형잡힌 모델을 만들 수 있다.
  • max_depth : int or None, optional(default = None)
    Decision Tree의 최대 깊이 제한을 줄 수 있음
    사전 가지치기를 하고 voerfitting을 방지 할 수 있음
  • min_sample_split : int, float optaional(default = 2)
    노드에서 가지를 분리할 때 필요한 최소 sample 개수에 대한 제한을 줄 수 있음. 주어진 값에 type에 따라 다음과 같이 기능함
    int -> 주어진 값 그대로 사용
    float -> 0,1사이의 값을 줄 수 잇음,. cell(전체 데이터수 * min_sample_split)의 값을 사용함
  • min_sample_leaf : int, float optaional(default = 2)
    한 노드에서 가지고 있어야 할 최소 sample 개수에 대한 제한을 줄 수 있음.주어진 값에 type에 따라 다음과 같이 기능함
    int -> 주어진 값 그대로 사용
    float -> 0,1사이의 값을 줄 수 잇음,. cell전체 데이터수 * min_sample_leaf)의 값을 사용함
  • max_features : int, float, string or None, optional(default = None)
    Decision Tree model을 만들 때 사용할 수 있는 변수의 개수를 제한을 줄 수 있음
    int -> 주어진 값 그대로 사용
    flaot -> int(max_features * 총변수 개수) 사용
    None -> 총 변수 개수 사용
  • class_weight : dict, list of dict or "balanced", default=None
    예측 할때 두개의 class의 중요도가 다른 경우가 있다.
    예로 환자 판단시, 정상을 정상으로 진단하는 것보다 환자를 환자로 진단하는 것이 더 중요하다
    그러므로 정상:환자 = 6:4 와 같이 비율을 정한다.
    class_label: weight

1.2 Random Forest


  • N개의 Decision Tree가 투표를 통해 결정하는 방식이다.
  • Bagginf approach중 하나임. -> 여러 모델을 합쳐서 결론냄
  • 주어진 데이터에서 랜덤하게 subset을 N번 sampling해서(좀 더 정확하게 observations와 features들을 랜덤하게 sampling) N개의 예측 모형을 생성
  • 개별 예측 모형이 voting하는 방식으로 예측결과를 결정하여 Low Bias는 유지하고 High Variance는 줄임
  • Random Forest는 이런 Bagging 계열의 가장 대표적이고 예측력 좋은 알고리즘

1.2.1 코드


from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import confusion_matrix
import pandas as pd

# prepare the iris dataset
df = pd.read_csv('D:/data/liver.csv')
print(df.head())
print(df.columns) # column names
df_X = df.loc[:, df.columns != 'category']
df_y = df['category']

# Split the data into training/testing sets
train_X, test_X, train_y, test_y = \
train_test_split(df_X, df_y, test_size=0.3,\
random_state=1234) 

 

# Define learning model (# of tree: 10) #################
model = RandomForestClassifier(n_estimators=10, random_state=1234) # n_estimators = 트리 수

# Train the model using the training sets
model.fit(train_X, train_y)

# performance evaluation
print('Train accuracy :', model.score(train_X, train_y))
print('Test accuracy :', model.score(test_X, test_y))
pred_y = model.predict(test_X)
confusion_matrix(test_y, pred_y)

 

# Define learning model (# of tree: 10) #################
model = RandomForestClassifier(n_estimators=10, random_state=1234)

# Train the model using the training sets
model.fit(train_X, train_y)

# performance evaluation
print('Train accuracy :', model.score(train_X, train_y))
print('Test accuracy :', model.score(test_X, test_y))
pred_y = model.predict(test_X)
confusion_matrix(test_y, pred_y)

 

# Define learning model (# of tree: 50) #################
model = RandomForestClassifier(n_estimators=50, random_state=1234)

# Train the model using the training sets
model.fit(train_X, train_y)

# performance evaluation
print('Train accuracy :', model.score(train_X, train_y))
print('Test accuracy :', model.score(test_X, test_y))
pred_y = model.predict(test_X)
confusion_matrix(test_y, pred_y)

tree 수를 50으로 늘리니까 정확도가 올라갔다.

 

 

Hyper parameters

  • n_estimators : 생성하는 트리의 개수, 많을수록 성능이 좋아짐 이론적으론 500, 1000이면 충분
  • max_feautures : 좋은 split을 하기위한 features의 개수
  • Criterion : measure the quality of a split

1.3 Support Vector Machine


이때까지는 tree 형태의 모델로 접근을 했다.
Support Vector Machine은 접근법이 다르다.

idea 1)

  • finding maximum-margin hyperplane
    모든 점 정보를 가지고 경계선을 찾는게 아니라 class 경계면에 있는 몇개의 점들로 경계선을 찾는다.
  • 데이터의 차원을 높이는 방법
    차원을 높여서 찾는다.
  • C - Support Vector Classification
    학습시간이 sample 수(data set의 instance 수)의 제곱에 비례하여 많아짐

1.3.1 코드

from sklearn import svm
from sklearn.model_selection import train_test_split
from sklearn.metrics import confusion_matrix

import pandas as pd
import pydot

# prepare the iris dataset
df = pd.read_csv('D:/data/liver.csv')
df_X = df.loc[:, df.columns != 'category']
df_y = df['category']

# Split the data into training/testing sets
train_X, test_X, train_y, test_y = \
train_test_split(df_X, df_y, test_size=0.3,\
random_state=1234)
# Define learning model (basic)
#####################################
model = svm.SVC()

# Train the model using the training sets
model.fit(train_X, train_y)

# performance evaluation
print('Train accuracy :', model.score(train_X, train_y))
print('Test accuracy :', model.score(test_X, test_y))
pred_y = model.predict(test_X)
confusion_matrix(test_y, pred_y)

 

# Define learning model (poly kernel) ############
model = svm.SVC(kernel='poly')

# Train the model using the training sets
model.fit(train_X, train_y)

# performance evaluation
print('Train accuracy :', model.score(train_X, train_y))
print('Test accuracy :', model.score(test_X, test_y))
pred_y = model.predict(test_X)
confusion_matrix(test_y, pred_y)

정확도가 낮아졌다.

 

1.3.3 Hyper parameter

  • c: float, deault =1.0
    Regularization parameter
    과적합을 조절(일어나지 않게)
  • kernel : linear, poly, rbf, sigmoid, precomputerd default = 'rbf'
    차원 변경
  • degree : int, default = 3
    커널에 따라 달라짐
  • gamma : scale, auto or float default = 'scale'
    'rbf', 'poly', 'sigmoid' 지원

1.3.4 SVM 장단점

장점

  • 범주나 수치데이터 보두에 사용가능
  • 노이즈 데이터에 영향을 크게 받지 않고 overfitting이 잘 일어나지 않음
  • 경계면의 몇개의 점만 사용하므로
  • 높은 정확도

단점

  • 최적의 모델을 찾기 위해 커널과 기타 hyper parameter의 여러 조합ㅇ르 테스트해보아야한다.
  • 입력 데이터셋이 feature 수와 데이터 sample 수가 많으면 훈련시간이 많이 소요될 수 있다.
  • 모델의 해석이 불가능하진 않지만 어렵다.

1.4 xgboost


예측력이 가장 좋지만 복잡하다.

  • Ensemble => 예측 모델을 만들때 여러개 모데ㅐㄹ을 만들어 하나로 합친다. 여러개 모델로 단일한 결과를 나오게 한다. 예측 성능을 높일 수 있다.
  1. Bagging => 투표로 결과 도출
  2. Boosting =>잘못 예측된 것들에 대해 예측력을 높여줌

728x90
반응형

'공부 > 딥러닝' 카테고리의 다른 글

CIFAR-10 의 레이블중 하나를 예측  (0) 2021.05.09
classification 경진대회  (0) 2021.05.03
딥러닝 4  (0) 2020.10.29
딥러닝 2  (0) 2020.09.29
딥러닝 1  (0) 2020.09.25
블로그 이미지

아상관없어

,

딥러닝 2

공부/딥러닝 2020. 9. 29. 21:14
반응형

Clustering


  • Grouping target data into some category(class)
  • 성격이나 가진 정보가 비슷한 데이터들을 묶음
  • 비지도 학습임(정답이 없고 알아서 묶음)
  • 어떻게 컴퓨터가 그룹을 나누느냐? => 거리가 가까운것 끼리 묵음 따라서 거리 계산이 중요함.

Classification


  • 데이터들이 그룹이 나누어져있고 알고 있음
  • 새로운 데이터가 들어왔을때, 어디에 속할지 판단함
  • 예측, 의료에서 진단 분야에서 사용됨.
  • 주로 많이 사용함.
  • 범주데이터를 주므로 지도학습임.

예시 : clustering

  • 차량의 특성을 가지고 grouping
  • 산점도를 그림

  • 점이 모이는 것을 확인할 수 있음
  • 그룹이 지어지면 해석이 가능해짐, 그룹의 특징을 해석해서 활용함
  • 혹은 비정상 거래 판단시, 주류범주에 속하지 않으면 비정상 거래로 탐지

예시 : classification

  • 이미 그룹이 만들어져 있음
  • ex) 병원 새로운 사람이 왔을때 환자인지 정상인지 판단
  • 어떤 class에 속하는지 찾아봄

Binary vs multiple classfication


  • Binary classification
  • class 의 수가 2개인 경우
  • 좀 더 쉬움 = 모델의 정확도가 높음
  • multifple classfication
  • class의 수가 3개 이상인 경우

K-means clustering


  • 예시 : 금이간 타일과 정상 타일 군집화

  • 크랙이 있는 것과 없는 것은 소리(주파수)가 다름
  • clustering을 하였을때, 금이 간 것과 안 간것끼리 class가 나뉘어야 사용할 수 있음
  • 주의) log값을 취하여 사용함. 왜냐하면 scale을 맞추어 왜곡값을 줄이기 위하여임(그러지 않을 경우 값들이 x, y축에 붙음)

  • 두개의 그룹으로 확연하게 분리됨

  • k = 클러스터의 수 => 따라서 2개(금간것, 안간것)

  • 임의로 점 두개를 찍음( k 개수 만큼)
    1. 이 점이 각 클러스터의 중심점이 됨
    2. 중심점과 점들의 거리를 구함
    3. 각 점들에 대해 더 가까이 있는 중심점을 그 점들과 합쳐서 중심점을 구함(x 좌표 평균, y 좌표 평균이 새로운 중심점)
    4. 반복하여 계산함

  1. 더 이상 안움직이는 때(움직임이 작을 때)가 오면 그룹의 중심을 찾았다는 뜻이다. 그러면 중심점들과 점 사이 거리를 계산하여 그룹을 찾는다.
  2. 두 그룹이 금간 것, 안간 것으로 구분이 되면, 이것으로 새로운 것이 들어왔을때 판단을 한다(중심점으로)

  • 거리계산법

import matplotlib.pyplot as plt
import numpy as np
from sklearn.cluster import KMeans

X = np.array([[1,2], [4,3], [2,5],
              [8,5], [10,6], [9,4]])

kmeans = KMeans(n_clusters=2, random_state=0).fit(X)
  • n_clusters : 클러스터의 개수
  • random_state : seed for reproducability => 클러스터 중심점 위치를 랜덤하게 찍기위해

# cluster label
kmeans.labels_ #클러스터 번호 알려줌

# bind data & cluster label
np.hstack((X, kmeans.labels_.reshape(-1, 1))) #lable을 포함하여 X를 보여줌, 세로로 바꾸어 합침

# center of clusters
kmeans.cluster_centers_ #중심점의 좌표값을 보여줌 

# predict new data
kmeans.predict([[0, 0], [12, 3]]) #예측

KNN classifier


  • 분류(classification)
  • 어느 카테고리에 속할것인가?
  • idea of KNN
  • 모르는 데이터와 알려진 데이터 중 모르는 데이터에 가까운 것들을 추림
  • K-NN : K는 몇개를 추릴 것인지
  • 그러면 K개 중 많은 것을 따름(다수를 따라감)

  • 가까운 이웃을 판단하기 위해선 거리를 다 계산함(모르는 데이터와 알려진 데이터들 사이의 거리)
  • K는 홀수로 하여야 모르는 데이터가 어디에 속할 지 정하기 쉬움

  • 계산
  • K의 값은 데이터의 수가 N이라 할 때, K < sqrt(N)을 권장
  • K가 클때와 작을때 각각 장단점이 있음

  • K개수에 따라 정확도가 달라지므로 여러개를 해보고 그중 정확도가 높은 것을 선택해야한다.
  • 이러한 모델의 정확도에 영향을 미치는 변수를 초매개변수라 한다. 정확도가 높은 초매개변수를 찾는 것이 중요함
  • 장점
  1. 통계적 가정 불필요(머신러닝 초기 모델들은 통계에 기반하여, 데이터는 정규분포를 따른다는 가정을 했다. 따라서 가정을 벗어난 데이터는 예측이 불가능했다)
  2. 단순하다
  3. 성능이 좋다
  4. 모델을 훈련하는 시간이 필요없다 (모델을 만드는 과정이 없음, 데이터를 바로 찾아서 결과를 냄 )
  • 단점
  1. 데이터가 커질수록 많은 메모리가 필요하다
  2. 데이터가 커질수록 처리시간(분류시간)이 증가한다.
  • 모르는 값이 있을 때, class를 구하려면 거리계산을 다 해주어야한다. 따라서 메인메모리에 모든 값이 있어야한다. 그리고 모두 거리계산을 해주어야한다.
from sklearn import datasets
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score

# Load the iris dataset
iris_X, iris_y = datasets.load_iris(return_X_y=True)
print(iris_X.shape) # (150, 4)

# Split the data into training/testing sets
train_X, test_X, train_y, test_y = \
train_test_split(iris_X, iris_y, test_size=0.3,\
random_state=1234) 
# Define learning model
model = KNeighborsClassifier(n_neighbors=3) #K값은 3임, 초매개변수 K = 3 (default값은 5임)

# Train the model using the training sets
model.fit(train_X, train_y)

# Make predictions using the testing set
pred_y = model.predict(test_X)
print(pred_y)

# model evaluation: accuracy #############
acc = accuracy_score(test_y, pred_y)
print('Accuracy : {0:3f}'.format(acc))
  • Dataset scaling
  • 거리기반 학습방법을 적용할 때는 scaling이 필요
  • 예로 키, 시력을 비교시 (170, 0.8) 두 값간의 차이가 커서 시력의 거리 의미가 없어짐
  • 따라서 두 크기의 스케일을 바꾸어 동등한 영향력을 가지게해야함.
from sklearn.preprocessing import StandardScaler

scaler = StandardScaler() # 정의
scaler.fit(X) # X : input data # 실행
X_scaled = scaler.transform(X) # 결과 얻음

Performance metric : 모델 성능 평가 척도


For Binary classification model only

  • Sensitivity
  • Specificity
  • precision
  • F1 score
  • ROC, AUC

For All classification model

  • Accuracy

=> 평가 척도가 다양한 이유는 응용을 어디에 하느냐에 따라 모델 평가 척도가 달라지기때문

 

 

  • Binary classification metric

의료일 경우 FP인 경우, 음성을 양성으로 잘못 판단한 것이므로 정상을 비정상으로 진단한 경우다.
FN인 경우 양성을 음성으로 잘못 판단한 것이다. 실제로 감염이 된 것인데 안되었다고 판단하므로 FN의 경우가 더 심각하다

  • 민감도

    - Sensitivity = TP/(TP+FN) => (실제 양성인데) 양성 판단 / 실제 양성

  • 특이도

     - Specifity = TN/(TN+FP) => (실제 음성인데) 음성 판단 / 실제 음성

  • 정밀도

     - Precision = TP/(TP+FP) => (실제 양성인데) 양성 판단 / 양성 판단

 

 

  • F1 ScoreBinary가 아닌 경우
  • class A, B, C가 있을경우
  • For class A : A는 Postive, B,C는 Negative
  • For class B : B는 Postive, A,C는 Negative
  • For class C : C는 Postive, A,B는 Negatvie
    => table을 만드는 경우 복잡하고 의미를 찾기 힘들다.
from sklearn.metrics import accuracy_score
test_y = [2, 0, 2, 2, 0, 1]
pred_y = [0, 0, 2, 2, 0, 2]
acc = accuracy_score(test_y, pred_y)
print(acc)

aac = 0.6666666666666

  • Confusion matrix
  • from sklearn.metrics import confusion_matrix test_y = [2, 0, 2, 2, 0, 1] pred_y = [0, 0, 2, 2, 0, 2] confusion_matrix(test_y, pred_y)

  • 정답이 0이고 예측도 0인 경우가 2개 있고, 1,1인 경우가 0개 2,2개인 경우가 2개이다 나머지는 예측이 틀린 경우이다
# binary classification
test_y = [1, 0, 0, 1, 0, 1]
pred_y = [0, 0, 0, 1, 0, 1]
tn, fp, fn, tp = confusion_matrix(test_y, pred_y).ravel()
(tn, fp, fn, tp)

tn, fp, fn, tp
3, 0, 1, 2
=> tn, fp, fn, tp 순이다.

K-fold Cross Validation

---------------------------------------------------------------------------------------------------

  • 데이터를 Training과 Test로 나누었을때 나온 accuracy를 믿어야하는가?
  • Test 데이터 셋을 다르게 만든다면 accuracy는 달라질 것임
  • Test 데이터 셋이 어떻게 구성되었느냐에 따라 accuracy가 원래 성능보다 높거나 낮게 나올 수도 있음
  • K-fold Cross Validation을 사용함

  • k가 4인 경우 4등분하여 각 모델별로 Test와 Train을 다르게 한다.
  • 그리고 각 모델의 정확도의 평균을 구한다

 

복잡한 방법 : 하지만 for문 사이에 테스트 코드를 추가할 수 있다.

from sklearn import datasets
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import KFold
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
import numpy as np

# Load the iris dataset

iris\_X, iris\_y = datasets.load\_iris(return\_X\_y=True)

# Define fold (5 fold)

kf = KFold(n\_splits=5, random\_state=123, shuffle=True) # shuffle => 섞음(섞어서 나눔)

# Define learning model

model = KNeighborsClassifier(n\_neighbors=3)  
acc = np.zeros(5) # 5 fold 저장할 배열  
i = 0 # fold no

for train\_index, test\_index in kf.split(iris\_X):  
print("fold:", i)  
train\_X, test\_X = iris\_X\[train\_index\], iris\_X\[test\_index\]  
train\_y, test\_y = iris\_y\[train\_index\], iris\_y\[test\_index\]  
model.fit(train\_X, train\_y)  
pred\_y = model.predict(test\_X)

# model evaluation: accuracy

acc\[i\] = accuracy\_score(test\_y, pred\_y)  
print('Accuracy : {0:3f}'.format(acc\[i\]))  
i += 1  
print("5 fold :", acc)  
print("mean accuracy :", np.mean(acc))

 

심플한 방법

from sklearn import datasets
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
import numpy as np



# Load the iris dataset

iris\_X, iris\_y = datasets.load\_iris(return\_X\_y=True)

# Define learning model

model = KNeighborsClassifier(n\_neighbors=3)

# Define fold (model, train, target, cross validation)

scores = cross\_val\_score(model, iris\_X, iris\_y, cv=5) # cv=5는 fold가 5개임  
print("fold acc", scores)  
print("mean acc", np.mean(scores))

  • K-fold cross validation이 원하는 모델을 도출하진 않음 (k=5일 경우 모델은 5개가됨)
  1. 주어진 데이터 셋으로 모델 개발시 미래의 정확도를 추정 ( k=1, 3, 5 일경우 최적의 경우를 찾음)
  2. 최종 모델 개발을 위한 hyper parameter 튜닝에 사용
  3. 전처리시 feature selection에 사용 => 모델을 만드는데 도움이되는 변수를 골라냄
728x90
반응형

'공부 > 딥러닝' 카테고리의 다른 글

CIFAR-10 의 레이블중 하나를 예측  (0) 2021.05.09
classification 경진대회  (0) 2021.05.03
딥러닝 4  (0) 2020.10.29
딥러닝 3  (0) 2020.10.09
딥러닝 1  (0) 2020.09.25
블로그 이미지

아상관없어

,

딥러닝 1

공부/딥러닝 2020. 9. 25. 21:24
반응형

머신 러닝 분류

  • 지도학습
  • 회귀(regression) - 수치형 자료(대소 비교가능)
  • 분류(classification) - 범주형 자료
  • 비지도 학습
  • 강화학습

1. 단순 선형회귀 (Simple linear regression)

  • 종속 변수 y와 독립 변수 x 사이의 선형 관계를 파악하고 이를 예측에 활용하는 방법
    예시) 기온(x) 아이스크림 판매량(y) => 필요한 아이스크림 재료의 양을 예측 가능해짐
  • 독립 변수 x와 선형 변수 y 사이의 관계식을 모델이라고 함.(학습 모델)
  • y = Wx + b
    상수인 W와 b를 찾는것이 학습 목표
  • 현실 세계에서는 두 변수가 _선형관계_에 있는 경우가 많음
  • 두 변수가 선형 관계에 있는지 알아보는 법 = 산점도, 상관계수
    산점도 : x,y 좌표값으로 나타냄
  • 회귀식에서 W와 b를 찾는 방법

(a)와 (b)중 어떤걸 선택? => 객관적 평가 척도가 필요함

좋은 식은 오차들의 합계가 작은 것임

오차들의 차이 계산? => 오차가 +값, -값이 나오므로 제곱한 값들의 합을 사용함 => 최소 제곱법

Code

# module load
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

from sklearn.linear_modle import LinearRegression
from sklearn.metrics import mean_wquared_error, r2_score
from sklearn.model_selection import train_test_split
# prepare dataset

cars = pd.read_csv('D:cars.csv')

speed = cars['speed']
distance = cars['distance']

# data frame to npl.numpy => numpy 배열로 바꾸어주어야함
speed = np.array(speed).reshape(50,1)
distance = np.array(distance_.reshape(50,1) # 1차원 벡터가 되어야 하므로 (50,1)로 바꾸어줌 (2차원 벡터로)

# Split the data into training/testing sets
train_X, test_X, train_y, test_y = train_test_split(speed, distance, test_size=0.2, random_state=123)
# 인자 speed = x, distance = y, test_size-0.2 = 전체 개수 중 20%를 테스트로 사용하고 나머지를 trainning으로, random_State = 무엇이 test가 되고 train이 될지 랜덤하게 결정​
# 학습 방법을 정해줌
model = LinearRegression()

# 학습 시킴
model.fit(train_X, train_Y)

# 예측함(테스트 셋으로 테스트함)
pred_y = model.predict(test_X)
print(pred_y)
# 예측
print(model.predict([[13]])

- [[]] 괄호 2개를 사용하는 이유는 predict는 배열이 들어가야하는데, 2차원 배열을 만들기 위해서 괄호 2개를 사용함

# W와 b값
print('coef : {0: .2f}, Intercept : {1: .3f}'.format(model.coef_[0][0], model.intercept
_[0]))

(파이썬에서는 format함수를 이용해서 문자열과 변수값을 쉽게 작성할 수 있다. 문자열 안에 {}기호를 작성하고 .format을 붙여 변수를 넣음. print("a={}".format(a)) )

  • Model 평가
  • The mean squared error
print('Mean squared error: {0: .2f}'.format(mean_squared_error(test_y, pred_y)))
  • The coefficient of determination : 1 is perfect prediction
print('%.2f' % r2_score(test_y, pred_y))
  • 모델 시각화(
plt.scatter(test_X, test_y, color = 'black')
plt.plot(test_X, pred_y, color='blue', linewidth=3)

plt.xlabel('speed')
plt.ylabel('distance')

plt.show()

Multiple linear regression (중선형 회귀)

  • 독립변수(설명변수)가 2개 이상인 경우
  • 예시
  • 키(X1) 몽무게(X2)를 가지고 혈당(Y)를 예측
  • 앞의 예시인 자동차의 속도를 가지로 제동거리를 예측할 경우, 단순히 제동거리는 주행속도에 의해 결정이 되진 않음!
  • 따라서 다양한 요인을 넣는다면 오차는 줄어들 것임
  • 예시 = 특정 직군의 연봉을 교육년수, 여성비율, 평판으로 예측
  • import pandas as ps import numpy as np from sklearn.linear_model import LinearRegression from skleran.metrics import mean_squared_error, r2_score from sklearn.model_selection import train_test_split
# load the prestge dataset
df = ps.read_csv('D:prestige.csv')
print(df)
df_x = df[['education', 'women', 'prestige']]
df_y = df[[i'income']]

데이터 셋을 준비하면 test/training set으로 나눔

# split the data into training/testing sets
train_X, test_X, train_y, test_y = train_test_split(df_X, df_y, test_size=0.2)

# Dfine learing model
model = LinearRegression()

# Train the model using the training sets
model.fit(train_X, train_y)

# Make predictions using the testing set
pred_y = model.predict(test_X)
print(pred_y)

learning model은 같지만 내용은 달라짐 = 변수 3개

# The coefficient & intercept
print('cofficients: {0:.2f}, {1:,2f}, {2:.2f} Intercept {3:.3f}'.format(model.coef_[0], model.coef_[1], model.coef[2], model.intercept))

# The mean squared error
print('Mean squared error: {0:.2f}',format(mean_squared_error(test_y, pred_y)))

# The coefficient of determination: 1 is perfect prediction
print('Coefficient of determinaion: %.2f' % r2_score(Test_y, pred_y))

그러면 연봉은 어떻게 구할까? => model.predict 사용

ex) education : 11.44 /women : 8.13 /prestige : 54.1

# Test single data
my_test_x = np.array([11.44, 8.13, 54.1]),reshape(1,-1) #행의 개수는 1, 열은 알아서 맞추어라(주어진 개수대로)
my_pred_y = model.predict(my_test_x) #예측값 얻음
print(my_pred_y)

Logistic regression

  • 일반적인 회귀 문제는 종속변수가 수치데이터임
  • 범주형 데이터를 예측할때, 회귀방법으로 구할때
  • 예시 : iris 데이터셋이에서 4개의 측정 데이터로부터 품종(분류)을 예측
  • Logistic 회귀도 y값이 숫자임
from sklearn import datasets #dataset에 iris가 포함되어 잇음
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score # 모델 정확도가 오차를 사용하지 못함
# Load the diabetes dataset
iris_X, iris_y = datasets.load_iris(return_X_y=True) # 독립변수와 종속변수를 구분해서 가져옴
print(iris_X.shape)

# Split the data into training/testing sets
train_X, test_X, train_y, test_y = train_test_split(iris_X, iris_y, test_size=0.3, random_state=1234)
# Define learning model
model = LogisticRegression()

# Train the model using the training sets
model.fit(train_X, train_y)

# Make predictions using the testing set
pred_y = model.predict(test_X)
print(pred_y)

# model evaluation: accuracy #############
acc = accuracy_score(test_y, pred_y)
print('Accuracy : {0:3f}'.format(acc))

Accuracy = 예측과 정답이 일치하는 instance 수 / 전체 test instance 수

! 종속변수가 숫자여야하기 때문에 문자형으로 되어 있는 범주 데이터를 숫자로 변환해야됨 => LabelEncoder

from sklearn.preprocessing import LabelEncoder
import numpy as np
number = LabelEncoder() # 객체생성

label_str = np.array(['M','F','M','F','M'])
label_num = number.fit_transform(label_str).astype('int') # int로 바꾸어라 기준은 알파벳 순서대로 F =0, M = 1
print(label_str)
print(label_num)
728x90
반응형

'공부 > 딥러닝' 카테고리의 다른 글

CIFAR-10 의 레이블중 하나를 예측  (0) 2021.05.09
classification 경진대회  (0) 2021.05.03
딥러닝 4  (0) 2020.10.29
딥러닝 3  (0) 2020.10.09
딥러닝 2  (0) 2020.09.29
블로그 이미지

아상관없어

,