KT 에이블스쿨 31일차(1)

박기범·2023년 3월 15일
0

에이블스쿨

목록 보기
36/95

오늘은 시각지능_딥러닝 3일차로 CNN복습과 모델 저장, InceptionV3 모델 가져오기, YOLO를 실습해보았습니다.



복습

kernel_size는 필터의 사이즈입니다. 근데 코드 작성시 kernel_size = (3,3)이런식으로 필터의 크기만 작성했는데 원래는 depth를 같이 표기해주어야 합니다. 하지만 자동으로 앞의 레이어의 depth를 가져오기 때문에 생략해도 됩니다.

※추가 내용 : 차원을 추가해주는 넘파이 함수로 expand_dims가 있습니다.



모델을 저장하고 불러오기

코랩을 사용할 때 세션이 끊기면 다시 모델링을 작업해야하는 치명적인 단점이 있습니다. 이런 문제를 방지하고자 모델을 학습하는 경우에 저장하고 불러오는 방법을 알아보겠습니다.

먼저 데이터 모델링까지 작업이 완료됐다고 가정하겠습니다.

▶모델 체크 포인트 만들어주기

	mcp = ModelCheckpoint(filepath='/content/model_save.h5',
                      monitor='val_loss',
                      verbose=1,
                      save_best_only=True,
                      save_weights_only=False)

filepath는 모델이 저장되는 위치를 지정해주는 옵션입니다.
save_best_only는 제일 좋은 모델만 저장합니다.
save_weights_only는 가중치만 저장하는 옵션으로 False값을 설정해주면 모델구조와 가중치 모두를 저장합니다.

▶모델 학습

		model.fit(datagen.flow(train_x, train_y, batch_size=1024),
                    epochs=10000, validation_data=(val_x, val_y),
                    verbose=1, callbacks=[es, mcp])

해당 코드를 보게 되면 먼저 증강 기술을 사용한 것을 알 수 있습니다. 어제는 train_gen이라고 따로 변수를 만들어서 넣어주었는데 이번 코드에서는 그냥 flow를 바로 선언해서 넣어주었습니다. 그리고 callbacks의 옵션을 보면 위에 선언해준 mcp를 추가해준 것을 확인할 수 있습니다.

해당 코드는 모델이 학습하면서 해당 모델링을 수시로 저장하는 코드입니다. 그러면서 최선의 성능인 모델로 계속 갱신하면서 저장하는 코드입니다.

▶학습이 완료된 모델 저장
만약 모델링이 완료된 모델을 저장하고 싶다면 아래의 코드를 사용하면 됩니다.

	model.save('my_first_save.h5')

※두 가지 방법 모두 .h5 확장자를 이용해서 저장해주어야 합니다.

위에 체크 포인트는 학습 도중에 저장하는 것이라면 .save()는 모델이 학습 완료된 후에 저장을 합니다.

▶저장된 모델 불러오기
이제 위 방법으로 모델을 저장했다면 모델을 불러와서 사용하는 방법은 아래와 같습니다.

	model = keras.models.load_model('my_first_save.h5') #모델구조와 가중치를 한번에 불러옴

▶불러온 모델 사용하기

    pred_train = model.predict(train_x)
    pred_test = model.predict(test_x)

    single_pred_train = pred_train.argmax(axis=1)
    single_pred_test = pred_test.argmax(axis=1)

    logi_train_accuracy = accuracy_score(train_y.argmax(axis=1), single_pred_train)
    logi_test_accuracy = accuracy_score(test_y.argmax(axis=1), single_pred_test)

    print('CNN')
    print(f'트레이닝 정확도 : {logi_train_accuracy*100:.2f}%')
    print(f'테스트 정확도 : {logi_test_accuracy*100:.2f}%')

위 코드의 방법으로 이제 세션이 끊기는 것을 대비해서 모델을 저장하고 불러오기가 가능합니다.



flow_from_directory

모델링과 혹은 모델을 불러온 것이 완료됐다는 가정하에 코드를 작성해주면 됩니다. 해당 방식은 디렉토리 경로로부터 이미지 데이터를 읽어와서 배치 단위로 처리할 수 있습니다.
먼저 저는 환경이 캐글이기 때문에 구글 드라이브에 폴더를 만들었다는 가정하에 작성하겠습니다.

	train_idg = idg.flow_from_directory('/content/drive/폴더주소',
                        save_to_dir='/content/temp/',
                        save_prefix='temp',
                        save_format='jpg',
                        target_size=(28,28),
                        color_mode='grayscale',)

이것을 제대로 사용할려면 각 폴더에 클레스명을 지어주어 같은 클레스인 것들을 저장해주는 각 폴더를 따로 생성해주어야합니다.

그리고 save를 통해 temp폴더에 증강 기술로 인해 생성된 파일들을 넣어줍니다.

나머지 방식은 이제 모델링하면 끝입니다.

※캐글에서 /content/ 경로는 구글 코랩에서 사용되는 경로로써 세션이 끊기면 만들어둔 폴더는 지워집니다. 지워지지 않는 것을 원하면 드라이브에 직접 만들고 해당 경로로 접근하면 됩니다



남이 만든 CNN사용하기(InceptionV3 모델 가져오기)

먼저 내가 해결하고자 하는 문제에 적합한 CNN 모델이라면 그냥 가져와서 사용해서 모델링을 하는 것을 Pretrained Model이라고 합니다.

▶필요패키지 불러오기
먼저 필요한 패키지를 불러오겠습니다. 해당 실습에서는 InceptionV3 모델을 활용하겠습니다.

	from tensorflow.keras.applications.inception_v3 import InceptionV3
    from tensorflow.keras.applications.inception_v3 import preprocess_input
    from tensorflow.keras.applications.inception_v3 import decode_predictions

    from tensorflow.keras.preprocessing import image

    import numpy as np
    import matplotlib.pyplot as plt

inception_v3를 사용하기 위한 패키지 호출을 완료했습니다.

▶인셉션 모델 가져오기

	model = InceptionV3(weights='imagenet', # 이미지넷 데이터 바탕으로 미리 학습된 것
                    include_top=True,   # 마지막 레이어까지 전부
                    input_shape= (299,299,3))

먼저 인셉션 모델에 간략하게 설명하자면 구글에서 만든 CNN 구조로 더 정밀한 이미지 분류가 가능합니다.

▶내 이미지 불러오기
이제 내가 분류하고자 하는 이미지를 준비해줍니다.

import glob
files = glob.glob('img1/*')
images = []

#여러개의 이미지를 준비함
for path in files :
    img = image.load_img(path, grayscale = False, target_size = (299,299) )
    img = image.img_to_array(img)
    img = preprocess_input(img)
    images.append(img)
    
images = np.array(images)

#내가 가져온 이미지들을 위에 선언한 인셉션 모델로 분류해보기
features = model.predict(images)
predictions = decode_predictions(features, top=3)# 모델이 고민한 3개의 클레스 보기

for i in range(images.shape[0]) :
    print(predictions[i])
    plt.imshow(image.load_img(files[i]))
    plt.show()

그러면 이제 위에 같은 결과를 얻을 수 있습니다.



남이 만든 모델을 고쳐쓰기(Tansform Learning)

남이 만들어둔 모델을 내가 원하는 문제 해결로 고칠 수 있어야 합니다.

▶필요한 패키지 호출

	import tensorflow as tf
    from tensorflow import keras

    from tensorflow.keras.applications.inception_v3 import InceptionV3
    from tensorflow.keras.applications.inception_v3 import preprocess_input
    from tensorflow.keras.applications.inception_v3 import decode_predictions
    from tensorflow.keras.callbacks import EarlyStopping, ReduceLROnPlateau

    from tensorflow.keras.preprocessing import image
    from tensorflow.keras.preprocessing.image import ImageDataGenerator
    from tensorflow.keras.utils import to_categorical
    from tensorflow.keras.layers import GlobalAveragePooling2D, Dense

    from sklearn.model_selection import train_test_split

    import random
    import numpy as np
    import matplotlib.pyplot as plt
    import glob

먼저 앞서 사용했던 인셉션 모델을 사용할 예정이라 아까처럼 패키지를 불러와줍니다. 또 이번에는 추가적으로 ReduceLROnPlateau를 가져왔는데 해당 패키지는 Learning Rate를 조절해주는 도구입니다. GlobalAveragePooling2D은 전체를 대상으로 AveragePooling2D를 해주는 도구입니다.

▶코랩에 구글 드라이브 연결
저는 코랩의 환경에서 작업을 하기 때문에 코랩에 구글 드라이브를 연결해주어 구글 드라이브에 있는 데이터에 접속할 수 있어야합니다.

	from google.colab import drive
	drive.mount('/content/drive') #구글 드라이브에 연결하기
	!cd /content/drive/MyDrive/작업파일 경로
    files = glob.glob('/작업환경 경로/my_data/transfer/*/*')

먼저 위의 코드를 살패보면 위의 두줄이 구글드라이브와 연동하기 위한 코드입니다. 연동이 되면 !cd명령어를 통해작업 파일 경로로 이동해준 후 files라는 변수에 작업 파일 경로에 있는 내가 분석하고자 하는 데이터들을 담아줍니다. 저는 transfer안에 각 클레스들의 이름을 가지는 파일을 만들고 해당 파일에 각 각 데이터들을 넣어주었습니다.

▶전처리
(추가 이해가 필요해서 이해하면 추가하도록 하겠습니다)

▶인셉션 모델 불러오기
전처리까지 완료가 되었다면 인셉션 모델을 호출합니다.

	keras.backend.clear_session()

    base_model = InceptionV3(weights='imagenet',       # 이미지넷 데이터 바탕으로 미리 학습된 것
                             include_top=False,        # 마지막 레이어 빼고!
                             input_shape= (299,299,3)) # 입력 데이터의 형태

    new_output = GlobalAveragePooling2D()(base_model.output)
    new_output = Dense(3, # class 갯수를 작성합니다.
                      activation = 'softmax')(new_output)

    model = keras.models.Model(base_model.inputs, new_output)

    model.summary()

▶레이어 고정
이제 남의 모델을 가져왔으면 일정 레이어에 대해서는 학습을 하고 나머지 레이어에 대해서는 학습을 하지 않습니다.

	for idx, layer in enumerate(model.layers) :
    if idx < 213 :
        layer.trainable = False
    else :
        layer.trainable = True

layer.trainable = True의 의미는 later의 가중치를 조절하겠다는 의미이고
layer.trainable = False는 학습된 가중치를 더 학습시키지 않고 멈추는 것을 의미합니다.
따라서 213개의 레이어에 대해서는 가중치 학습을 하지 않고 나머지 레이어에 대해서 학습을 진행한다는 의미입니다.

▶모델 학습

	model.compile(loss='categorical_crossentropy', metrics=['accuracy'],
             optimizer=keras.optimizers.Adam(learning_rate=0.001) )

▶Callbacks 설정

	lr_reduction = ReduceLROnPlateau(monitor='val_loss',
                                 patience=4,
                                 verbose=1,
                                 factor=0.5,
                                 min_lr=0.000001)

    es = EarlyStopping(monitor='val_loss',
                       min_delta=0, # 개선되고 있다고 판단하기 위한 최소 변화량
                       patience=15, # 개선 없는 epoch 얼마나 기달려 줄거야
                       verbose=1,
                       restore_best_weights=True)

ReduceLROnPlateau는 학습속도를 동적으로 조절할 수 있습니다.

▶증강 기술
다음으로 제가 수집한 데이터를 가지고 증가해줍니다.

      datagen = ImageDataGenerator(
          rotation_range=180, # randomly rotate images in the range (degrees, 0 to 180)
          zoom_range = 0.3, # Randomly zoom image 
          width_shift_range=0.3,  # randomly shift images horizontally (fraction of total width)
          height_shift_range=0.3,  # randomly shift images vertically (fraction of total height)
          horizontal_flip=True,  # randomly flip images
          vertical_flip=True)  # randomly flip images

      datagen.fit(train_x)

▶모델 학습
이제 최종적으로 모델을 학습합니다.

	model.fit(datagen.flow(train_x, train_y),
                 epochs=1000, validation_data=(valid_x, valid_y),
                 verbose=1, callbacks=[es, lr_reduction] )

▶모델 평가
마지막으로 평가를 진행합니다.

	model.evaluate(test_x, test_y)



정리

만약 내가 해결하고자 하는 문제 해결에 맞는 모델이면 그대로 가져다 쓰면 됩니다. 이를 Pretrained Model이라고 합니다.

만약 구조가 살짝 바꿔서 우리 문제 해결에 맞추기 위해 Input~Hidden레이어까지 Frozen하거나 Output 직전 또는 Output레이어만 고쳐쓰는 것을 Transfer Learning이라고 합니다. 여기서 Frozen한다는 것은 가중치 업데이트를 안한다는 것입니다.(위 코드에서 레이어를 고정해준는 것을 참고)



추가 자료

저번에도 포스팅했지만 다시 한번 알아두면 좋은 걸로
딥러닝의 모델 구조를 보기위해 사용하는 시각화 도구로는 아래와 같습니다.

    from tensorflow.keras.utils import plot_model
    plot_model(model, show_shapes=True, show_layer_names=True)

vstack(), hstack() 넘파이에서 사용되는 함수입니다. vstack은 수직으로 배열을 쌓고 hstack은 수평으로 배열을 쌓아줍니다.







이번 포스팅은 모델을 저장하고 불러오는 것에 집중되어 있습니다. 다음 포스팅에 Object Detection에 대해 포스팅하겠습니다.




※공부하고 있어 다소 틀린점이 있을 수 있습니다. 언제든지 말해주시면 수정하도록 하겠습니다.
※용어에 대해 조금 공부 더 해서 수정하겠습니다.

profile
개발자가 되기 위한 한걸음

0개의 댓글