퐈니썬's LIfe - 잘 실패하자 RSS 태그 관리 글쓰기 방명록
Ai (6)
2021-07-16 14:30:04
728x90
반응형

00. 서문

오토 인코더에 대해서 공부해야 할 일이 생겨서, 하는 도중 정리하기 위해 포스팅을 하게 되었습니다.

공부하여 작성하는 거라, 부족할 수 있으니 많은 피드백 주시면 감사하겠습니다.

01. 오토 인코더 (autoencoder)

오토 인코더는 비지도 학습 방법의 하나입니다. 그러기 때문에 모델을 학습하기 위한 명확한 라벨(정답)이 제공되지 않습니다. 즉, 오토 인코더를 학습하기 위해서는 입력 데이터를 필요로 합니다.

 

 제가 공부하면서 느낀 것은 오토 인코더의 학습과정은 마치 "압축과 압축해제"와 같다고 느꼈습니다.

이미지를 학습한다고 가정했을 때, 입력 이미지를 받고, 학습 레이어를 거쳐 입력 이미지를 잘 설명할 수 있는 축소된 차원이 데이터("latent space" 또는 "bottle neck"이라고 하는)로 변환되고, 이 데이터를 다시 reconstruct하여 입력이미지를 복원하거나 target 이미지를 구성해내는 과정을 거친다고 이해했습니다.

 

 

 

조금 더 깊게 생각했을 때, 입력층에서 이미지가 들어오고, 각 노드들은 이에 대한 특징(feature)을 Encoder를 통해 차원 축소를 거치고, 입력 및 target 이미지를 잘 설명할 수 있는 데이터로 압축한 후에 이를 Decoder를 통해 복원하여 표현하는 과정이라고 이해했습니다. 

마치 오토 인코더는 PCA와 비슷하다고 생각도 들었습니다. 하지만, PCA는 선형적 차원축소하는 반면 오토인코더는 비선형적 차원축소를 한다고 합니다 (활성함수 이야기 인거 같습니다).

 

02. Encoder와 Decoder

오토인코더 과정은 3단계로 나누어 볼 수 있을 거 같습니다. 

  • 데이터 입력
  • Encoder 
  • Decoder

Encoder: Encoder는 결국 입력 데이터를"입력 데이터의 특징을 잘 설명할 수 있는 데이터로 차원 축소한다" 이 공간을 "latent-space", 또는 "bottle neck"이라고 합니다. 

 

Decoder: Decoder는 입력 및 target 데이터로 복원(복호화)을 합니다. decoder가 encoder로부터 받은 데이터로 정확하게 입력 및 target 데이터로 복원한다면 decoder의 성능이 좋다고 표현합니다.

728x90
반응형
2021-07-06 22:12:01
728x90
반응형

01. Confusion Matrix?

Confusion Matrix라고 해서 굉장히 어렵게 느꼈는데, 생각보다 간단하였습니다.

한국말로 "분류결과표"라고 합니다.

즉, 참값(타겟의 원래 클래스)와 예측값(모형이 예측한 클래스)가 일치하는지를 갯수로 수치화 한 결과 표입니다.

정답 클래스는 행(row)로, 예측 클래스는 열(column)로 표현합니다. 

 

02. 실습을 통해 Confusion Matrix 보기 (코드포함)

이전에, 포스트한 CIFAR-10 학습을 기반으로 해당 모델의 Confusion Matrix를 추출 해보았습니다. 

 

https://panython.tistory.com/12

 

[AI Study] ImageDataGenerator 사용하여 CIFAR-10 분류하기

01. CIFAR-10 이미지 분류해 보기 01. ImageDataGenerator 사용해 보기 keras에서는 이미지데이터 학습을 쉽게하도록 하기위해 다양한 패키지를 제공한다. 그 중 하나가 ImageDataGenerator 클래스이다. ImageData..

panython.tistory.com

 

이전에 학습하였던 모델을 사용하였습니다. 

 

이전 학습 모델을 불러와 테스트 데이터 예측하기

model = load_model('./saved_models/cifar10_cnn_model_epoch40.h5')
images = test_set
label, fns, images2 = load_rand_img(images,32)
predictions = model.predict(images2/255)

예측한 데이터와 정답 텍스트로 확인 하기

#정답보기
for i in range(32):
    pred_label = labels[np.argmax(predictions[i])]
    fn = fns[i]
    la = labels[label[i]]
    print(i, '번째', '파일', fn, '참값', la, '예측값', pred_label)
>>>0 번째 파일 ./CIFAR-10-images-master/test/truck/0959.jpg 참값 truck 예측값 truck
>>>1 번째 파일 ./CIFAR-10-images-master/test/truck/0830.jpg 참값 truck 예측값 truck
>>>2 번째 파일 ./CIFAR-10-images-master/test/bird/0134.jpg 참값 bird 예측값 bird
>>>3 번째 파일 ./CIFAR-10-images-master/test/horse/0935.jpg 참값 horse 예측값 horse
>>>4 번째 파일 ./CIFAR-10-images-master/test/horse/0147.jpg 참값 horse 예측값 horse
>>>5 번째 파일 ./CIFAR-10-images-master/test/dog/0239.jpg 참값 dog 예측값 dog
>>>6 번째 파일 ./CIFAR-10-images-master/test/frog/0285.jpg 참값 frog 예측값 frog
>>>7 번째 파일 ./CIFAR-10-images-master/test/truck/0876.jpg 참값 truck 예측값 truck
>>>8 번째 파일 ./CIFAR-10-images-master/test/deer/0236.jpg 참값 deer 예측값 frog

 

위의 방법이 있다는 수준으로 전달 드린 것입니다. 결국 참값과 예측값을 비교하는 것이죠!! 

 

이번에는 그림으로 시각화 해보시죠!

 

예측한 데이터와 정답 이미지로 확인 하기

#이미지 데이터를 랜덤하게 n개 추출하여 라벨, 파일이름, 이미지 배열 추출 함수 
def load_rand_img(imagesset, randint):
    images = imagesset.filepaths
    labels = imagesset.labels
    rand_imgs = []
    label = []
    for i in range(randint):
        rand_num = random.randrange(0,len(images))
        rand_imgs.append(images[rand_num])
        label.append(labels[rand_num])
    load_imgs = load_img(rand_imgs)
    return label, rand_imgs, load_imgs
    
# 예측 결과를 figure로 확인하는 함수 
def plot_predict(figsize, num, classes, label, images, predictions):
    fig = plt.figure(figsize=(figsize[0], figsize[1]))
    for i in range(num):
        plt.subplot(figsize[0], figsize[1], i + 1)
        plt.grid(False)
        plt.xticks([])
        plt.yticks([])
        fn = plt.imread(images[i])
        plt.imshow(fn)
        la = classes[label[i]]
        pred_label = classes[np.argmax(predictions[i])]
        if pred_label == la:
            color = 'green'
        else:
            color = 'red'
        plt.xlabel("{}({}, i={})".format(pred_label, la, i), color=color)
    plt.show()
    
# 메인 실행 
labels = ["airplane", "automobile", "bird", "cat", "deer", "dog", "frog", "horse", "ship", "truck"]
label, fns, images2 = load_rand_img(images, 10000)
predictions = model.predict(images2/255)
plot_predict((4,8),32, labels, label, fns, predictions)

xlabel의 형식은 "예측값(참값)" 으로 설정하였습니다.

이번 시행에서 32개 중에 7개 오답을 보였으니, 약 22%의 오답률, 즉 78% 정답률을 보여주었지만, 해당 코드는 실행할 때마다 다시 랜덤추출하기 때문에 한눈에 모델을 평가하기는 어렵습니다!! 

 

그래서!! 모델의 성능을 한눈에 보기위해 "Confusion Matrix"를 적용해보았습니다!!

 

예측한 데이터와 정답을 "Confusion Matrix"로 확인 하기

Confusion Matrix에 대해 잠깐 본다면 참값(타겟의 원래 클래스)와 예측값(모형이 예측한 클래스)가 일치하는지를 갯수로 수치화 한 결과 표라고 보시면 되겠네요!

정답 클래스는 행(row)로, 예측 클래스는 열(column)로 표현하기때문에, Confusion Matrix는 모델이 잘 작동되는지 확인할 수 있는 좋은 방법입니다. 

예를 들면 아래의 표와 같다. (출처 : datascienceschool.net)

 

# confusion matrix 사용을 위한 라이브러리
from sklearn.metrics import confusion_matrix

# confusion matrix 그리는 함수 
def plot_confusion_matrix(con_mat, labels, title='Confusion Matrix', cmap=plt.cm.get_cmap('Blues'), normalize=False):
    plt.imshow(con_mat, interpolation='nearest', cmap=cmap)
    plt.title(title)
    plt.colorbar()
    marks = np.arange(len(labels))
    nlabels = []
    for k in range(len(con_mat)):
        n = sum(con_mat[k])
        nlabel = '{0}(n={1})'.format(labels[k],n)
        nlabels.append(nlabel)
    plt.xticks(marks, labels)
    plt.yticks(marks, nlabels)

    thresh = con_mat.max() / 2.
    if normalize:
        for i, j in itertools.product(range(con_mat.shape[0]), range(con_mat.shape[1])):
            plt.text(j, i, '{0}%'.format(con_mat[i, j] * 100 / n), horizontalalignment="center", color="white" if con_mat[i, j] > thresh else "black")
    else:
        for i, j in itertools.product(range(con_mat.shape[0]), range(con_mat.shape[1])):
            plt.text(j, i, con_mat[i, j], horizontalalignment="center", color="white" if con_mat[i, j] > thresh else "black")
    plt.tight_layout()
    plt.ylabel('True label')
    plt.xlabel('Predicted label')
    plt.show()

# 예측값과 참값 
pred_labels = np.argmax(predictions, axis=1)
true_labels = test_set.labels

#메인 실행 
confusion_matrix = confusion_matrix(true_labels, pred_labels)
plot_confusion_matrix(confusion_matrix, labels=labels, normalize=True)

 

 

 

짜잔! 이렇게 대각을 보시면 진한 파란색일 수록 많이 맞췄다는 겁니다. 

Xlabel은 예측값, Ylabel은 참값이기 때문에 각 라벨에서 몇개를 예측한지 볼 수 있으며 어떤 라벨은 어떤라벨에서 헷갈릴 수 있는지도 파악이됩니다!!

예를 들면, 예측값 dog이라고 예측을 했지만 사실상 cat이라고 예측한 비율도 꽤 높습니다. 이것을 미루어 볼때, 해당모델은 다른 라벨에 비해 dog과 cat을 분류하는데는 조금 좋지 못한 성능을 보이구나! 와 같이 확인 할 수 있습니다. 

 

728x90
반응형
2021-06-22 13:37:16
728x90
반응형

01. CIFAR-10 이미지 분류해 보기

01. ImageDataGenerator 사용해 보기

keras에서는 이미지데이터 학습을 쉽게하도록 하기위해 다양한 패키지를 제공한다. 그 중 하나가 ImageDataGenerator 클래스이다.

ImageDataGenerator 클래스를 통해 객체를 생성할 때 파라미터를 전달해주는 것을 통해 데이터의 전처리를 쉽게할 수 있고, 또 이 객체의 flow_from_directory 메소드를 활용하면 폴더 형태로된 데이터 구조를 바로 가져와서 사용할 수 있다.

이 과정은 매우 직관적이고 ImageDataGenerator를 사용하지 않는 방법에 비해 상당히 짧아진다.

ImageDataGenerator를 통해 parameter arugmentation을 하고, flow_from_directory
메소드를 사용해, 폴더를 특정 사이즈로 이미지를 불러올 수 있다. 

02. CIFAR-10 학습해 보기

학습과정은 기본적인 FLOW를 배경으로 하였다.

  • 이미지로드
  • train 과 validation 데이터 분리
  • 이미지 전처리 (정규화 포함, DATAGENERATOR, 원핫인코딩)
  • 학습모델형성
  • 학습진행
  • 학습평가 (시각화)

01. 이미지 로드

지난 시간에 subplot의 대한 사용법을 복습하고, rows: labels, columns 각 이미지로 하여,

10 x 10의 이미지를 추출해보았다. 데이터 탐색의 목적으로, 데이터 확인이 목적이다.

ex) 비행기는 비행기네,, 트럭은 트럭이네,, 등등 < 실무에 이러한 작업이 필수적>

CIFAR-10 이미지 플롯

02. train과 validation 데이터 분리

 이 과정은 추가적으로 진행하게 된 작업이다. 기본적으로 데이터가 주어지면 train set, validation set, test set으로 구분해야 한다.

 목적은 "Overfitting"!! 즉, 내가 만든 모델이 내가 제공한 train set데이터에 너무 과적합되도록 학습되어버려서 이를 조금이라도 벗어난 케이스에 대해서 예측률이 낮아지는 현상이 발생한다. 그렇기 때문에 이러한 현상을 막기 위해서 데이터를 목적에 맞도록 구분한다.

  • train set : 모델이 훈련하는 데이터셋
  • validation set : train set 학습 중간에 모델 평가에 사용되는 데이터셋 (모델 성능에 영향 줌)
  • test set : 오로지 모델의 성능 평가를 위해 사용되는 데이터셋 (모델 성능에 영향 안 줌)

 

이번 주차에서는 train set을 train을 위한 데이터셋과 validation을 위한 데이터셋으로 나누어 볼 것이다. 아주 간단하다. 왜냐하면, ImageDataGenerator과 flow_from_directory에서 쉽게 할 수 있다.

[train set, validation set] = [0.8, 0.2]로 나누어 볼 것이다.

train_datagen = ImageDataGenerator(rescale=1./255,
                                   rotation_range=15,
                                   shear_range=0.2,
                                   zoom_range=0.2,
                                   horizontal_flip=True,
                                   width_shift_range=0.1,
                                   height_shift_range=0.1,
                                   validation_split=0.2)

train_set = train_datagen.flow_from_directory('./CIFAR-10-images-master/train/',
                                              target_size=(32,32),
                                              batch_size=32,
                                              class_mode='categorical',
                                              subset='training')

val_set = train_datagen.flow_from_directory('./CIFAR-10-images-master/train/',
                                              target_size=(32,32),
                                              batch_size=32,
                                              class_mode='categorical',
                                          subset='validation')

#데이터 스플릿 확인 
size_data = [train_set.n, val_set.n]

plt.bar(range(len(size_data)), size_data)
ax = plt.subplot()
ax.set_xticks([0,1])
ax.set_xticklabels(['train set', 'validation set'])
plt.show()

 

핵심은, ImageDataGenerator로 argumentation에서 "validation_split"을 지정한 후에 (내가 원하는, 이는 이미지 전처리와 같음) 각 flow_from_directory시에 "subset"을 지정해주면 된다. 5만 장으로 구성되었던, train directory의 데이터를 학습에 4만 장, 1만 장으로 나누었다. Good!

 

데이터 분할 

03. 이미지 전처리

이미지 전처리에서는 ImageDataGenerator로 argumentation를 통해 데이터 학습을 위한 1) 데이터 가공 (정규화) 2) 데이터 뻥튀기를 통해 많은 데이터를 모델이 학습할 수 있도록 하는 역할이 있다. 생각할수록 굉장히 유용한 클래스이다.. overfitting 방지

이를 통해 두 가지를 한 번에 하는 마법 같은 경험을 하였다

 

#개수작을 좋아하는 나는 사용할 수 있는 모든 argumentation을 최대한 활용하였다. 
train_datagen = ImageDataGenerator(rescale=1./255,
                                   rotation_range=15,
                                   shear_range=0.2,
                                   zoom_range=0.2,
                                   horizontal_flip=True,
                                   width_shift_range=0.1,
                                   height_shift_range=0.1,
                                   validation_split=0.2)

rescale:정규화 위해
rotation_range = 0~15도 까지 회전하기
shear_range = 시계반대방향으로 밀림,0.2이라면, 0.2 라이안내외로 
							시계반대방향으로 변형
zoom_range = “1-수치”부터 “1+수치”사이 범위로 확대/축소,0.2이라면, 
							0.8배에서 1.2배 크기 변화를 시킴
horizontal_flip = 수평방향으로 뒤집기
width_shift_range, height_shift_range = 0.1 배율의 픽셀 만큼 이동

 

진짜 돌아가는 건지, 그러니깐 ImageDataGenerator가 구동되는지 궁금했다.

 

CIFAR10의 비행기 그림

 

airplane의 하나를 해당 조건으로 25장의 이미지로 만들어 저장하여 불러보았다.

뭐,,, 확실히 이미지의 변화가 생긴 거 같긴 하다.  ok!

 

 

ImageDataGenerator를 통해 argumentation  수행 결과

 

import numpy as np
import os
import matplotlib.pyplot as plt

from keras.preprocessing.image import ImageDataGenerator, 
array_to_img, img_to_array, load_img


train_datagen = ImageDataGenerator(rescale=1./255,
                                   rotation_range=15,
                                   shear_range=0.2,
                                   zoom_range=0.2,
                                   horizontal_flip=True,
                                   width_shift_range=0.1,
                                   height_shift_range=0.1,
                                   validation_split=0.2)


img = load_img('./CIFAR-10-images-master/train/airplane/0001.jpg')
plt.figure()
a = plt.imread(img)
plt.imshow(a)
plt.show()
x = img_to_array(img)
x = x.reshape((1,) + x.shape)

i = 0
for batch in train_datagen.flow(x, batch_size=20, 
save_to_dir='./CIFAR-10-images-master/tmp_files', save_prefix='tmp', 
save_format='jpg'):
    i += 1
    if i > 24:
        break
image_dir = './CIFAR-10-images-master/tmp_files'
plt.figure(figsize=(5,5))
images = os.listdir('./CIFAR-10-images-master/tmp_files')
for i in range(5):
    for j in range(5):
        plt.subplot(5,5,i*5 +j + 1)
        fn = image_dir+ '/' + images[i]
        image = plt.imread(fn)
        plt.grid(False)
        plt.tight_layout()
        plt.imshow(image)
plt.show()

 

04. 이미지 모델 생성 & 학습 진행 & 학습평가 (시각화)

여러 가지 모델에 대하여 생성하고, 학습하고 평가까지 한 번에 해보았다. 코드 스플릿이 필요하긴 할 듯,, 다음에..

기본적은 CNN이며 둘 차이는 layer 수와 optimizer를 두었다.

이전과 다른 것은 ImageDataGenerator로 데이터를 전처리 및 부풀렸기 때문에, model에 대하여 fit() 메서드를 사용하는 것이아니라, fit_generator() 메소드를 사용한다는 것! 중요!

 

#모델 1
Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d (Conv2D)              (None, 30, 30, 32)        896       
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 15, 15, 32)        0         
_________________________________________________________________
conv2d_1 (Conv2D)            (None, 13, 13, 32)        9248      
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 6, 6, 32)          0         
_________________________________________________________________
flatten (Flatten)            (None, 1152)              0         
_________________________________________________________________
dense (Dense)                (None, 64)                73792     
_________________________________________________________________
dense_1 (Dense)              (None, 10)                650       
=================================================================
Total params: 84,586
Trainable params: 84,586
Non-trainable params: 0
_________________________________________________________________

#compile
optimzier = "adam"
loss function = "categorical_crossentropy"
metrics(평가) = "acc"
#fit
epoch = "30"
batch_size = "32"

 

모델#1에 대한 학습 결과

음,, validation accuracy가 70% 언저리.. 변경! 옵티마이저. Layers와 epoch를 변경!

 

#모델 2
Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d (Conv2D)              (None, 30, 30, 32)        896       
_________________________________________________________________
conv2d_1 (Conv2D)            (None, 28, 28, 32)        9248      
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 14, 14, 32)        0         
_________________________________________________________________
dropout (Dropout)            (None, 14, 14, 32)        0         
_________________________________________________________________
conv2d_2 (Conv2D)            (None, 12, 12, 64)        18496     
_________________________________________________________________
conv2d_3 (Conv2D)            (None, 10, 10, 64)        36928     
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 5, 5, 64)          0         
_________________________________________________________________
dropout_1 (Dropout)          (None, 5, 5, 64)          0         
_________________________________________________________________
flatten (Flatten)            (None, 1600)              0         
_________________________________________________________________
dense (Dense)                (None, 128)               204928    
_________________________________________________________________
dense_1 (Dense)              (None, 10)                1290      
=================================================================
Total params: 271,786
Trainable params: 271,786
Non-trainable params: 0
_________________________________________________________________

#compile
optimzier = keras.optimizers.RMSprop(lr=0.0001, decay=0.0000001)
loss function = "categorical_crossentropy"
metrics(평가) = "acc"
#fit
epoch = "40"
batch_size = "32"

모델#2에 대한 학습결과

Accuracy가 높아지지 않았지만, validation의 accuracy가 train의 accuracy보다 높다...(?)

왜지?? 이는, train set에서 과적합이 발생하지 않고, validation set에서 잘 맞추었다는 이야기로, 정확도는 낮지만 bias와 variance가 낮은 모델이라고 볼 수 있다.

 

여기서 과적합에 대한 내용을 잠시 담자면, 조금 찾아보니깐, → "validation set의 accuracy가 train set보다 낮다면, Regularization을 계산 반복해야 한다."

이 말을 이해하고자 다음 그림을 인용해보았다.

 

정규화에 대한 자료 (인용)

 

작성자는 이렇게 말한다. "overfitting 그래프(3번째)를 보면, 데이터 분포에 비해서 loss함수가 복잡해지고, smooth 하지 않다. 즉, 새로운 데이터를 넣으면 제대로 예측하지 못할 가능성이 높다."

 

2번째의 그래프의 경우 데이터 분포와 조화가 잘되어 smooth 하다, 이러한 곡선이 적절한 모델일 가능성이 높다고 한다. 이는 변동성을 낮추어야 한다고 하는데,, 잘 이해는 되지 않는다 다만 앞서 말한 것처럼 변동성을 낮추기 위해서 "Regularization" 이 필요하다고 한다.

 

그럼 해보자!

옵티 아미저는 model1과 함께 가고, epoch 늘리고 layers는 model2를 따라가는데,

Regularization을 layer마다 추가해보자! 어떻게? 케라스에서 친절히 제공한다.

  • kernel_regularizer=regularizers.l2(weight_decay) Good!
  • from keras import regularizers부터 하고 보자.
  • from keras.layers import BatchNormalization
  • layers에 padding 옵션 추가 - 레이어의 인풋과 아웃풋에 크기에 대한 것으로 "same"은 아웃풋이 원래 인풋과 동일한 길이를 갖도록 인풋을 패딩
#model3
Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
conv2d (Conv2D)              (None, 32, 32, 32)        896       
_________________________________________________________________
batch_normalization (BatchNo (None, 32, 32, 32)        128       
_________________________________________________________________
conv2d_1 (Conv2D)            (None, 32, 32, 32)        9248      
_________________________________________________________________
batch_normalization_1 (Batch (None, 32, 32, 32)        128       
_________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 16, 16, 32)        0         
_________________________________________________________________
conv2d_2 (Conv2D)            (None, 16, 16, 64)        18496     
_________________________________________________________________
batch_normalization_2 (Batch (None, 16, 16, 64)        256       
_________________________________________________________________
conv2d_3 (Conv2D)            (None, 16, 16, 64)        36928     
_________________________________________________________________
batch_normalization_3 (Batch (None, 16, 16, 64)        256       
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 8, 8, 64)          0         
_________________________________________________________________
conv2d_4 (Conv2D)            (None, 8, 8, 128)         73856     
_________________________________________________________________
batch_normalization_4 (Batch (None, 8, 8, 128)         512       
_________________________________________________________________
conv2d_5 (Conv2D)            (None, 8, 8, 128)         147584    
_________________________________________________________________
batch_normalization_5 (Batch (None, 8, 8, 128)         512       
_________________________________________________________________
max_pooling2d_2 (MaxPooling2 (None, 4, 4, 128)         0         
_________________________________________________________________
flatten (Flatten)            (None, 2048)              0         
_________________________________________________________________
dense (Dense)                (None, 128)               262272    
_________________________________________________________________
dense_1 (Dense)              (None, 10)                1290      
=================================================================
Total params: 552,362
Trainable params: 551,466
Non-trainable params: 896
_________________________________________________________________


#compile
optimzier = "adam"
loss function = "categorical_crossentropy"
metrics(평가) = "acc"
#fit
epoch = "40"
batch_size = "32"

 

모델#3 에 대한 학습 결과

  • 모델에 대한 evaluate() 메서드를 통해 val_set의 평가 점수를 추출하고, CNN error 스코어로 정의하여 추출해보았다. "CNN Error : 20%"!!
  • 즉, Validation accuracy가 대략 80%에 도달하였다.
  • 이전에 목적한 거와 같이 Train set accuracy가 더 높다. 즉, overfitting이 발생했다는 것이고,,
  • 비록 정확도는 높았지만, bias나 variance를 가 더 생겨서 validation 학습 때는 train set의 정확도에 비해 떨어진다고 볼 수 있다. 일정 부분 과적합이 발생했다고 보인다..
  • 생각한 대로 모델이 나오진 않았지만 5% 정도 validation 정확도를 높인 것에 대해 정규화 과정의 역할을 확인할 수 있었다.
  • 다만, val loss 함수의 그래프가 많은 피크를 보인 것 또한,, 뭔가 정규화가 잘된 거 같지도 않고,,
  • 다음에는, bias와 variance를 고려하여 모델을 잘 찾아서 적용해보자..
728x90
반응형
2021-03-04 19:32:22
728x90
반응형

#1. Andrew Ng. Lecture.C1W2L04

강의 출처 : www.youtube.com/channel/UCcIXc5mJsHVYTZR1maL5l9w

 

DeepLearningAI

Welcome to the official DeepLearning.AI YouTube channel! Here you can find the videos from our Coursera programs on machine learning as well as recorded events. DeepLearning.AI was founded in 2017 by machine learning and education pioneer Andrew Ng to fill

www.youtube.com

본업 이외에 따로 무엇가를 준비한다는 것은 쉬운일은 아닌거 같다. 하지만, 꾸준히 하자!

01. Lecture 10. Gradient Descent

  • 강의 목적 - "경사 하강법 (Gradient Descent)" 알고리즘을 사용한, 매개변서 w, b를 훈련세트에 학습시키는 방법.
  • 이전 강의의 연장선으로, 로지스틱회귀 함수의 경사하강법에 대한 설명.

그림 1

로지스틱 회귀법의 "시그모이드 함수" 를 예로 들어 설명합니다.

 

(그림 1의 첫번째 식) "시그모이드 함수"의 표현 식입니다.

 

(그림 1의 두번째 식)  "비용함수"를 J라 할 때, 비용함수 J는 w, b에 대한 함수가 됩니다.

 

이 함수 J는  "손실함수의 평균"으로 정의합니다. 즉, 손실함수와 비용함수는 목적은 같지만 약간의 의미는 다릅니다.

 

결국, m개의 데이터셋이 있다면 각 데이터셋의 손실함수를 계산한 값의 평균이 "비용함수" 로 정의됩니다.

 

이는 훈련셋이 얼마나 참값과 예측값이 맞는지에 대한 측정이 가능하죠.

 

(그림 1의 그래프) 두 가로축은 w,b에 대한 정의가 된 축입니다. 세로축은 비용함수 J에 의한 (w,b)의 출력 값이 되겠죠.

 

J함수가 저 그림에 따른 모양이라면, 어느한점 (w,b)에서 가장 적은 최소값을 찾으려 할 것입니다.

 

그것이 알고리즘이고, 비용함수 J가 아래로 볼록한(convex)한 모양이라는 것이 로지스틱 회귀가 적용에 적절한 비용

 

수가 된다는 것을 의미하고, 이대의 w, b가 적절한 파라미터라고 할 수 있겠습니다.

 

그림 2

결국에는 비용함수 J의 목적은 최소 값을 찾는 것이고, 이 최소값을 찾아나가는 방법이 "경사하강법"입니다.

 

그리고, 비용함수 J가 최소 값일 때 w, b가 적절한 파라미터이므로 이 w, b를 갱신해가며 비용함수 J를 따라 함수값

 

이 최소 값이 되는 w, b를 찾아야겠죠.

 

그림2가 이에 대한 내용입니다. 

 

경사하강법을 본다면 결국 w를 갱신해나가는 것이고, 이 갱신은 기존 w에서 J(w)의 기울기 값에서 a(학습률)의 곱

 

을 빼 는 것으로 갱신해나간다고 합니다. 

 

즉, 기울기가 양일때는 w가 작아지는, 기울기가 음일때는 w가 커지면서 J(w)가 작은 global 미니마를 찾는것이죠. 

 

여기서 중요한 것은 우리가 w,b를 경사하강법으로 J(w,b)가 최소가 되는 w,b를 찾는 것이다.

 

어떻게?? 미분으로!!

 

그림 2의 모든 식들이 해당 내용 w := w - a* dJ(w,b)/dw b := b - a* dJ(w,b)/db  - 우리는 천천히 이해할 수 있습니다!

 

다음에는 미분으로 어떻게 찾아가는지 공부하면서 미분의 의미도 정립해보도록 하겠습니다.

728x90
반응형
2021-03-03 13:17:38
728x90
반응형

01. Keras

01. Keras란?

케라스는 딥러닝 모델을 간편하게 만들고, 훈련시킬 수 있는 파이썬을 위한 딥러닝 프레임워크로, 백엔드 엔진에서 제공하는 최적화된 텐서 라이브러리를 사용합니다.

케라스는 모듈 구조로 구성되어 있어 하나의 텐서 라이브러리에 국한하여 구현되어 있지 않고, 여러 가지 백엔드 엔진과 매끄럽게 연동됩니다.

현재는 TensorFlow, Theano, CNTK 3개를 백엔드 엔진으로 사용할 수 있습니다. (백엔드 엔진 변경하는 방법; https://keras.io/api/utils/backend_utils/)

 

02. Keras workflow

케라스를 사용하는 대부분의 작업 흐름은 다음과 같습니다.

  1. 입력 텐서와 타겟 텐서로 이루어진 훈련 데이터를 정의
  1. 입력과 타겟을 맵핑하는 층으로 이루어진 네트워크(모델)를 정의
  1. 손실함수, 옵티마이저, 모니터링하기 위한 측정지표를 선택하여 학습
  1. 훈련 데이터에 대해 모델의 fit() 메서드를 반복적으로 호출

 

02. Keras를 이용하여 MNIST 학습하기

01. 데이터 호출

가장 기본적인 예제인 MNIST 데이터셋을 이용하여 손글씨 데이터를 분류 예측하는 모델 제작.

케라스에서 MNIST 데이터셋을 numpy배열 형태로 호출이 가능하다.

# 필요한 라이브러리 불러오기
from keras.datasets import mnist
from keras import models
from keras import layers
from keras.utils import to_categorical

# MNIST 데이터셋 불러오기
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()

# 이미지 데이터 준비하기 (모델에 맞는 크기로 바꾸고 0과 1사이로 스케일링)
# 노말라이즈를 하는, 0~1의 이미지를 기준으로 한다. (왜그런지 보쟈)
train_images = train_images.reshape((60000, 28 * 28))
train_images = train_images.astype('float32') / 255
test_images = test_images.reshape((10000, 28 * 28))
test_images = test_images.astype('float32') / 255

02. 훈련, 테스트 데이터 설정

 

# 레이블을 범주형으로 인코딩
train_labels = to_categorical(train_labels) #범주형이라고하고, 원핫인코딩 필수적인 작업
#원핫 인코딩 왜하냐 알아보기.
test_labels = to_categorical(test_labels)

03. 모델 정의

# 모델 정의하기 (여기에서는 Sequential 클래스 사용)
model = models.Sequential()
model.add(layers.Dense(512, activation='relu', input_shape=(28 * 28,))) 512개의 perceptron

model.add(layers.Dense(10, activation='softmax'))
model.add(layers.Dense(len(train_labels[0]), activation='softmax'))

# 모델 컴파일 하기
model.compile(optimizer='rmsprop',
                loss='categorical_crossentropy',
                metrics=['accuracy'])

04. 모델 훈련

# fit() 메서드로 모델 훈련 시키기
model.fit(train_images, train_labels, epochs=5, batch_size=128)

05. 정확도 측정

# 테스트 데이터로 정확도 측정하기
test_loss, test_acc = model.evaluate(test_images, test_labels)
print('test_acc: ', test_acc)

06. 결과 보기

Epoch 1/5
469/469 [==============================] - 1s 2ms/step - loss: 0.4283 - accuracy: 0.8745
Epoch 2/5
469/469 [==============================] - 1s 2ms/step - loss: 0.1105 - accuracy: 0.9669
Epoch 3/5
469/469 [==============================] - 1s 2ms/step - loss: 0.0683 - accuracy: 0.9800
Epoch 4/5
469/469 [==============================] - 1s 2ms/step - loss: 0.0469 - accuracy: 0.9867
Epoch 5/5
469/469 [==============================] - 1s 2ms/step - loss: 0.0355 - accuracy: 0.9891
313/313 [==============================] - 0s 576us/step - loss: 0.0662 - accuracy: 0.9811
test_acc:  0.9811000227928162

03. 코드내용 학습하기

01. MNIST 데이터 셋에 대하여

01. MNIST 데이터 셋?

National Institute of Standards and Technology의 줄임말로, 미국 국립표준기술연구소의 손으로 쓴 글자 데이터셋에서 숫자만 따로 뽑아낸 데이터 셋.

0~255사이의 값을 가지는 흑백 이미지이며 28x28(784) 사이즈를 지니며 7만 개의 이미지(6만 개 트레이닝 셋, 1만 개 테스트 셋)으로 구성되어있다.

02. MNIST 데이터 셋 살펴보기

# 필요한 라이브러리 불러오기
from keras.datasets import mnist
from keras import models
from keras import layers
from keras.utils import to_categorical

# MNIST 데이터셋 불러오기
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()

------------------------------------------------------------------------------
test_image : shape : (10000,28,28) 28x28 이미지 10000장
test_label : shape : 10000 10000장 이미지 대한 0~9까지의 라벨
train_image : shape : (60000,28,28) 28x28 이미지 60000장
train_label : shape : 60000 60000장 이미지 대한 0~9까지의 라벨

* 각 한장에 28x28 배열이며 각 배열의 값들은 0~255의 값을 가지고 이미지로 보았을때 
0~9까지의 형상을 가진다

03. MNIST 데이터 셋 PLOT 해보기

import matplotlib.pyplot as plt
#train image의 5번째 이미지 추출
image = train_images[4]  #reshape전의 이미지

#plot the sample
fig = plt.figure
plt.imshow(image, cmap='gray')
plt.show()
print("train_image 4번째 라벨은", train_labels[4])
#실행결과 Console: train_image 4번째 라벨은 9 

04. 모델구조 파악하기

모델을 정의하는 방법은 두 가지로, Sequential 클래스함수형 API를 사용한다.

1) Sequential 클래스 : 가장 자주 사용하는 구조로, 층을 순서대로 쌓아 올린 네트워크

2) 함수형 API : 완전히 임의의 구조를 만들 수 있는 비순환 유향 그래프(DAG) 만듬 ( 공부가 필요)

 

해당 코드에서는, Sequential 클래스 형태로 모델화하였다.

모델은 2개의 Dense 층으로 되어있고, 각각 "relu", "softmax"의 활성함수를 가진다.

마지막 층은 10개의 확률 점수가 들어 있는 배열을 반환하는 소프트맥스층이며, 각 점수는 현재 숫자 이미지가 10개의 숫자 클래스 중 하나에 속할 확률을 나타낸다(?)

#model.summary() 통해 전체적인 구조
Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
dense (Dense)                (None, 512)               401920    
_________________________________________________________________
dense_1 (Dense)              (None, 10)                5130      
=================================================================
Total params: 407,050
Trainable params: 407,050
Non-trainable params: 0
_________________________________________________________________

05. 결과 파악하기

학습된 모델이 Test 모델을 판별할때, 98.34%로 MNIST의 숫자를 맞춘다는 의미이다.

즉, 테스트 데이터 10000개 중에서 200장 가량 틀렸다는 것으로 볼 수 있다.

Test loss: 0.08414454758167267
Test accuracy: 0.9817000031471252

 

 

예측 라벨과 실제 테스트라벨이 다른 결과들 16개를 랜덤하게 선정하여 보았을때, 실제로 사람이 보아도 판별하기 쉽이낳는 것들이 있는 것을 확인 할 수 있다.

04. 전체코드

01. 학습하기

 

# 필요한 라이브러리 불러오기
from keras.datasets import mnist
from keras import models
from keras import layers
from keras.utils import to_categorical
import matplotlib.pyplot as plt
from keras.utils import plot_model

# MNIST 데이터셋 불러오기
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()

# 이미지 데이터 준비하기 (모델에 맞는 크기로 바꾸고 0과 1사이로 스케일링)
train_images = train_images.reshape((60000, 28 * 28))
train_images = train_images.astype('float32') / 255
test_images = test_images.reshape((10000, 28 * 28))
test_images = test_images.astype('float32') / 255

# 레이블을 범주형으로 인코딩
train_labels = to_categorical(train_labels)
test_labels = to_categorical(test_labels)

# 모델 정의하기 (여기에서는 Sequential 클래스 사용)
model = models.Sequential()
model.add(layers.Dense(512, activation='relu', input_shape=(28 * 28,)))
model.add(layers.Dense(10, activation='softmax'))
model.summary()

# 구 조확인
from IPython.display import SVG
from keras.utils import model_to_dot

# SVG(model_to_dot(model, show_shapes=True).create(prog='dot',format='svg'))

# 모델 컴파일 하기
model.compile(optimizer='rmsprop',
                loss='categorical_crossentropy',
                metrics=['accuracy'])

# fit() 메서드로 모델 훈련 시키기
history=model.fit(train_images, train_labels,epochs=10, batch_size=64, verbose=1)
# batch size가 높을수록, 속도빠르고, 정화도가 낮아.

# 테스트 데이터로 정확도 측정하기
test_loss, test_acc = model.evaluate(test_images, test_labels, verbose=0)

print('Test loss:', test_loss)
print('Test accuracy:', test_acc)
# 학습 정확성 값과 검증 정확성 값을 플롯팅 합니다.

#결과파악.

import random
import numpy as np
predicted_result = model.predict(test_images)
predicted_labels = np.argmax(predicted_result, axis=1)

test_label = np.argmax(test_labels, axis=1)

wrong_result = []

for n in range(0, len(test_label)):
    if predicted_labels[n] != test_label[n]:
        wrong_result.append(n)

samples = random.choices(population=wrong_result, k=16)

count = 0
nrows = ncols = 4

plt.figure(figsize=(12,8))

for n in samples:
    count += 1
    plt.subplot(nrows, ncols, count)
    plt.imshow(test_images[n].reshape(28, 28), cmap='Greys', interpolation='nearest')
    tmp = "Label:" + str(test_label[n]) + ", Prediction:" + str(predicted_labels[n])
    plt.title(tmp)

plt.tight_layout()
plt.show()

02. 결과보기

from keras.datasets import mnist

# MNIST 데이터셋 불러오기
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()

import matplotlib.pyplot as plt
#train image의 4번째 이미지 추출
image = train_images[4]

#plot the sample
fig = plt.figure
plt.imshow(image, cmap='gray')
plt.show()
print("train_image 4번째 라벨은", train_labels[4])

num = 10
images = train_images[:num]
labels = train_labels[:num]

num_row = 2
num_col = 5

#plot images
fig, axes = plt.subplots(num_row, num_col, figsize=(1.5*num_col, 2*num_row))
for i in range(num):
    ax = axes[i//num_col, i%num_col]
    print(i//num_col, i%num_col)
    ax.imshow(images[i], cmap='gray')
    ax.set_title('Label: {}'.format(labels[i]))
plt.tight_layout()
plt.show()
728x90
반응형
2021-02-25 18:45:20
728x90
반응형

#1. Andrew Ng. Lecture.C1W2L01 ~ C1W2L03

강의 출처 : www.youtube.com/channel/UCcIXc5mJsHVYTZR1maL5l9w

01. Logistic Regression

  • 강의 목적 - "로지스틱 회귀가 어떤 것인가" 에 대한 간략한 전달
  • "로지스틱 회귀"는 "지도학습 문제"에서 출력 레이블 y가 0 or 1 일 경우 즉, 이진 분류에 사용되는 알고리즘

예를들어, 고양이 사진인지 아닌지 구분하는 경우라면? x라는 입력이 주어지면, y의 예측값을 출력하는 알고리즘이 필요

 

할 것 즉, x는 고양이 사진이고, y의 예측값은 고양이 사진일 확률 일것 문제는, 입력 x와 파라미터 w,b가 주어졌을

 

때, 어떻게 y의 예측값을 출력 할 수 있을까?

 

잘 안되는 방법은 w*x +b 와 같은 선형식으로 두는 것. 왜??

 

선형함수는 음수도 가질 수있기에, 이진 분류에는 좋은 방법이 아니다.

 

왜냐하면, 예측 값인 y는 확률로 항상 0<y<1 값을 가져야하기 때문!! 그렇기 때문에 0과 1로 표현이 잘 되어질 수 있는

 

활성 함수인 "시그모이드 함수" 를 주로 적용한다.

 

 

위 그림은 "시그모이드 함수" 그래프와 식을 나타낸다. 이를 보면 알 수 있듯이, z가 양의 값으로 클수록 z의 함수 값은 1

 

에, z가 음의 값으로 클수록 z의 함수 값은 0에 수렴한다.

 

그러므로 로지스틱 회귀를 구현할때, y가 1이 될 확률을 잘 예측하도록 파라미터 w,b를 학습해야 한다.

 

 

02. Lecture 09. Logistic Regression Cost Function

  • 강의 목적: 파라미터 w, b를 학습하려면, 비용함수의 정의가 필요. "로지스틱 회귀"를 학습할  수 있는 비용함수에 대해 알아보자.
  • 손실함수(loss function), 비용 함수 (cost function), 목적 함수 (objective function): 머신러닝을 통한 예측값이 실제값과 차이(오차)와 관련한 식(equation)

  • 예측값과 실제값의 오차를 최소화하려 하면 비용함수 혹은 손실함수라 함. 즉, 비용함수는 예측값의 오차를 최소화하기 위해 최적화된 식이어야 함

위 식에 대해 말해보자면, i번째 y의 예측값은 w*x(i) + b의 시그모이드이며, 이때 시그모이드 함수는 첫 번째 줄의

 

where 이후의 식으로 정의가 된다. 즉, w*x(i) + b가 i번째 z로 치환이 된다고 보면 된다.

 

1~m개의 주어진 훈련 데이터를 w, b를 찾아 학습할때, 우리가 원하는 값은 i번째 y의 예측값이 훈련 세트에 포함된 i번

 

째 y의 참값과 가까워지도록 하는 것.

 

이를 측정 할 수 있는 것이 손실함수(=오차함수=비용함수)이다. 손실함수를 L이라고 부르고, y^ = 예측값, y = 참값이

 

라 할때, 1/2(y^ - y)^2가 손실함수로 표현될 수 있으나, "로지스틱 회귀" 에서는 적절한 손실함수가 아니다.

 

여기서 명심할 것은 y의 예측값과 y 참값의 오차가 얼마나 큰지를 측정하는 것이 "손실함수"

 

  • 그렇다면, 로지스틱 회귀법에서 시그모이드 함수의 적절한 손실함수는 ??다음과 같이 표현 할 수 있다.

그 이류를 이해한대로 적어보자!

손실함수는 최소화 되어야하는 것을 전제로 한다. 

y^ 이 예측값, y가 참값이라 할때 y^는 로지스틱 회귀 함수를 따른다. 

y= 1 경우)  손실함수  L=  -log(y의 예측값)이 되고, 우리는 예측값이 1 이 되길 원하므로  손실함수는 최소가 되길 원할

 

것. 그럴려면, y의 예측값(y^)이 최대 값이 되도록 그려져야하고, y^은 로지스틱 회귀 함수를 따르기에 1에 수렴하도로

 

증가할 것이다.

반면에, y = 0 경우) 손실함수 L = -log(1-y의 예측값)이 되고, 우리는 예측값이 0 이 되길 원하므로  손실함수는 최소가

 

되길 원할 것이고, 그러므로, 1-y의 예측값이 최대 값이 되도록그려져야하고,  y^는 최소가 되도록 가야할 것이다. 

y^는 로지스틱 회귀 함수를 따르기에 0에 수렴하도록 감소할 것이다.

 

 

정말 어렵지만, 조금씩 알아가고 있는것 같아 기쁘다! 꾸준히 하자!

728x90
반응형