[DAY11]_개발일지: Image Analysis(Dog vs Cat)

1. 학습내용

  1. Image Analysis(Dog vs Cat)

2. 상세내용


  • Image Analysis(Dog vs Cat)
  • !pip install tensorflow
    !pip install tensorflow-gpu
    import keras
    keras.__version__
    import os, shutil
    import tensorflow as tf
    tf.test.is_gpu_available()
    # 원본 데이터셋을 압축 해제한 디렉터리 경로
    original_dataset_dir = './datasets/cats_and_dogs/train'
    
    # 소규모 데이터셋을 저장할 디렉터리
    base_dir = './datasets/cats_and_dogs_small'
    if os.path.exists(base_dir):
        shutil.rmtree(base_dir)
    os.mkdir(base_dir)
    
    # 훈련, 검증, 테스트 분할을 위한 디렉터리
    train_dir = os.path.join(base_dir, 'train')
    os.mkdir(train_dir)
    validation_dir = os.path.join(base_dir, 'validation')
    os.mkdir(validation_dir)
    test_dir = os.path.join(base_dir, 'test')
    os.mkdir(test_dir)
    
    # 훈련용 고양이 사진 디렉터리
    train_cats_dir = os.path.join(train_dir, 'cats')
    os.mkdir(train_cats_dir)
    # 훈련용 강아지 사진 디렉터리
    train_dogs_dir = os.path.join(train_dir, 'dogs')
    os.mkdir(train_dogs_dir)
    
    # 검증용 고양이 사진 디렉터리
    validation_cats_dir = os.path.join(validation_dir, 'cats')
    os.mkdir(validation_cats_dir)
    # 검증용 강아지 사진 디렉터리
    validation_dogs_dir = os.path.join(validation_dir, 'dogs')
    os.mkdir(validation_dogs_dir)
    
    #테스트용 고양이 사진 디렉터리
    test_cats_dir = os.path.join(test_dir, 'cats')
    os.mkdir(test_cats_dir)
    #테스트용 강아지 사진 디렉터리
    test_dogs_dir = os.path.join(test_dir, 'dogs')
    os.mkdir(test_dogs_dir)
    
    # 처음 1000개의 고양이 이미지를 train_cats_dir에 복사합니다.
    print('Copy files.... ')
    print('---training file (cat)....')
    fnames = ['cat.{}.jpg'.format(i) for i in range(1000)]
    for fname in fnames:
        src = os.path.join(original_dataset_dir, fname)
        dst = os.path.join(train_cats_dir, fname)
        shutil.copyfile(src, dst)
    
    # 다음 500개 고양이 이미지를 validation_cats_dir 복사합니다.
    print('---validation file(s) (cat).... ')
    fnames = ['cat.{}.jpg'.format(i) for i in range(1000, 1500)]
    for fname in fnames:
        src = os.path.join(original_dataset_dir, fname)
        dst = os.path.join(validation_cats_dir, fname)
        shutil.copyfile(src, dst)
    
    # 다음 500개 고양이 이미지를 test_cats_dir 복사합니다.
    print('---test file(s) (cat).... ')
    fnames = ['cat.{}.jpg'.format(i) for i in range(1500, 2000)]
    for fname in fnames:
        src = os.path.join(original_dataset_dir, fname)
        dst = os.path.join(test_cats_dir, fname)
        shutil.copyfile(src, dst)
    
    # 처음 1000개의 강아지 이미지를 train_dogs_dir에 복사합니다.
    print('---traing file(s) (dog).... ')
    fnames = ['dog.{}.jpg'.format(i) for i in range(1000)]
    for fname in fnames:
        src = os.path.join(original_dataset_dir, fname)
        dst = os.path.join(train_dogs_dir, fname)
        shutil.copyfile(src, dst)
    
    # 다음 500개 강아지 이미지를 validation_dogs_dir 복사합니다.
    print('---validation file(s) (dog).... ')
    fnames = ['dog.{}.jpg'.format(i) for i in range(1000, 1500)]
    for fname in fnames:
        src = os.path.join(original_dataset_dir, fname)
        dst = os.path.join(validation_dogs_dir, fname)
        shutil.copyfile(src, dst)
    
    # 다음 500개 강아지 이미지를 test_dogs_dir 복사합니다.
    print('---test file(s) (dog).... ')
    fnames = ['dog.{}.jpg'.format(i) for i in range(1500, 2000)]
    for fname in fnames:
        src = os.path.join(original_dataset_dir, fname)
        dst = os.path.join(test_dogs_dir, fname)
        shutil.copyfile(src, dst)

    print('훈련용 고양이 이미지 전체 개수:', len(os.listdir(train_cats_dir)))
    print('검증용 고양이 이미지 전체 개수:', len(os.listdir(validation_cats_dir)))
    print('테스트용 고양이 이미지 전체 개수:', len(os.listdir(test_cats_dir)))
    print('훈련용 강아지 이미지 전체 개수:', len(os.listdir(train_dogs_dir)))
    print('검증용 강아지 이미지 전체 개수:', len(os.listdir(validation_dogs_dir)))
    print('테스트용 강아지 이미지 전체 개수:', len(os.listdir(test_dogs_dir)))

    from keras import layers
    from keras import models
    
    model = models.Sequential()
    model.add(layers.Conv2D(32, (3,3), activation='relu'))
    model.add(layers.MaxPooling2D((2,2)))
    model.add(layers.Conv2D(64, (3,3), activation='relu'))
    model.add(layers.MaxPooling2D((2,2)))
    model.add(layers.Conv2D(128, (3,3), activation='relu'))
    model.add(layers.MaxPooling2D((2,2)))
    model.add(layers.Conv2D(128, (3,3), activation='relu'))
    model.add(layers.MaxPooling2D((2,2)))
    model.add(layers.Flatten())
    model.add(layers.Dense(512, activation='relu'))
    model.add(layers.Dense(1, activation='sigmoid'))                   #맨끝에 출력는 하나만 하면됨
    from tensorflow.keras import optimizers
    
    model.compile(loss='binary_crossentropy',
                  optimizer=optimizers.RMSprop(lr=1e-4),
                  metrics=['acc'])
    from keras.preprocessing.image import ImageDataGenerator
    
    train_datagen = ImageDataGenerator(rescale = 1.0 / 255)
    validation_datagen = ImageDataGenerator(rescale = 1.0 / 255)
    
    train_generator = train_datagen.flow_from_directory(
        train_dir,
        target_size=(150, 150),
        batch_size=20,
        class_mode='binary'
    )
    
    validation_generator = validation_datagen.flow_from_directory(
        validation_dir,
        target_size=(150, 150),
        batch_size=20,
        class_mode='binary'
    )
    model.fit_generator(
        train_generator,
        epochs = 30,
        steps_per_epoch = 100,
        validation_data = validation_generator,
        validation_steps = 50
    )

    model.save('cats_and_dogs_small_1.h5')
    history = model.history
    
    import matplotlib.pyplot as plt
    
    acc = history.history['acc']
    val_acc = history.history['val_acc']
    loss = history.history['loss']
    val_loss = history.history['val_loss']
    
    epochs = range(len(acc))
    
    plt.plot(epochs, acc, 'bo', label='Training acc')
    plt.plot(epochs, val_acc, 'b', label='Validation acc')
    plt.title('Training and validation accuracy')
    plt.legend()
    
    plt.figure()
    
    plt.plot(epochs, loss, 'bo', label='Training loss')
    plt.plot(epochs, val_loss, 'b', label='Validation loss')
    plt.title('Training and validation loss')
    plt.legend()

    datagen = ImageDataGenerator(
          rotation_range=40,
          width_shift_range=0.2,
          height_shift_range=0.2,
          shear_range=0.2,
          zoom_range=0.2,
          horizontal_flip=True,
          fill_mode='nearest')
    
    # 이미지 전처리 유틸리티 모듈
    from keras.preprocessing import image
    
    fnames = sorted([os.path.join(train_cats_dir, fname) for fname in os.listdir(train_cats_dir)])
    
    # 증식할 이미지 선택합니다
    img_path = fnames[3]
    
    # 이미지를 읽고 크기를 변경합니다
    img = image.load_img(img_path, target_size=(150, 150))
    
    # (150, 150, 3) 크기의 넘파이 배열로 변환합니다
    x = image.img_to_array(img)
    
    # (1, 150, 150, 3) 크기로 변환합니다
    x = x.reshape((1,) + x.shape)
    
    # flow() 메서드는 랜덤하게 변환된 이미지의 배치를 생성합니다.
    # 무한 반복되기 때문에 어느 지점에서 중지해야 합니다!
    i = 0
    for batch in datagen.flow(x, batch_size=1):
        plt.figure(i)
        imgplot = plt.imshow(image.array_to_img(batch[0]))
        i += 1
        if i % 4 == 0:
            break

    model = models.Sequential()
    model.add(layers.Conv2D(32, (3, 3), activation='relu',
                            input_shape=(150, 150, 3)))
    model.add(layers.MaxPooling2D((2, 2)))
    model.add(layers.Conv2D(64, (3, 3), activation='relu'))
    model.add(layers.MaxPooling2D((2, 2)))
    model.add(layers.Conv2D(128, (3, 3), activation='relu'))
    model.add(layers.MaxPooling2D((2, 2)))
    model.add(layers.Conv2D(128, (3, 3), activation='relu'))
    model.add(layers.MaxPooling2D((2, 2)))
    model.add(layers.Flatten())
    model.add(layers.Dropout(0.5))
    model.add(layers.Dense(512, activation='relu'))
    model.add(layers.Dense(1, activation='sigmoid'))
    
    model.compile(loss='binary_crossentropy',
                  optimizer=optimizers.RMSprop(lr=1e-4),
                  metrics=['acc'])
    train_datagen = ImageDataGenerator(
        rescale=1./255,
        rotation_range=40,
        width_shift_range=0.2,
        height_shift_range=0.2,
        shear_range=0.2,
        zoom_range=0.2,
        horizontal_flip=True,)
    
    # 검증 데이터는 증식되어서는 안 됩니다!
    test_datagen = ImageDataGenerator(rescale=1./255)
    
    train_generator = train_datagen.flow_from_directory(
            # 타깃 디렉터리
            train_dir,
            # 모든 이미지를 150 × 150 크기로 바꿉니다
            target_size=(150, 150),
            batch_size=20,
            # binary_crossentropy 손실을 사용하기 때문에 이진 레이블을 만들어야 합니다
            class_mode='binary')
    
    validation_generator = validation_datagen.flow_from_directory(
            validation_dir,
            target_size=(150, 150),
            batch_size=20,
            class_mode='binary')
    
    history = model.fit_generator(
          train_generator,
          steps_per_epoch=100,
          epochs=100,
          validation_data=validation_generator,
          validation_steps=50)

    model.save('cats_and_dogs_small_2.h5')
    acc = history.history['acc'] 
    val_acc = history.history['val_acc'] 
    loss = history.history['loss'] 
    val_loss = history.history['val_loss']
    
    epochs = range(len(acc))
    
    plt.plot(epochs, acc, 'bo', label='Training acc')
    plt.plot(epochs, val_acc, 'b', label='Validation acc')
    plt.title('Training and validation accuracy')
    plt.legend()
    
    plt.figure()
    
    plt.plot(epochs, loss, 'bo', label='Training loss')
    plt.plot(epochs, val_loss, 'b', label='Validation loss')
    plt.title('Training and validation loss')
    plt.legend()
    
    plt.show()


    3. 금일소감

    <ol>
    	<li>오늘은 굉장히 많은 에러로 인하여 수업진행이 어려웠다</li>
    	<li>그리고 굉장히 많은 메모리를 소모하여 커널이 죽는 현상도 생겼다.</li>
        <li>오늘 수업을 들으면서 한번씩 보면서 AI쪽 언어에 익숙해져야겠다는 생각을 했다.</li>
        <li>내일부터는 Microsoft Azure를 사용하는데 지금부터가 진짜라고 생각한다.</li>
        <li>개발자는 장비가 중요하다 ( 오늘의 핵심 교훈 )</li>
    </ol>

    좋은 웹페이지 즐겨찾기