세로형
Link
05-24 10:49
«   2022/05   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31        
Archives
Today
627
Total
2,239,973
관리 메뉴

꿈 많은 사람의 이야기

파이썬 케라스(keras)로CNN 딥러닝하자! cat dog binary image classification 본문

deep learning(딥러닝)

파이썬 케라스(keras)로CNN 딥러닝하자! cat dog binary image classification

이수진의 블로그 2018. 7. 4. 16:24

 

모든 코드는 아래 깃허브에 올려놓았습니다. 
https://github.com/lsjsj92/keras_basic

 


지난번까지 multi classification 이미지 분류를 해봤습니다

하지만 모든 카테고리 분류가 multi이지는 않죠~

그래서 이번에는 이진 분류(binary classification)을 해보겠습니다

 

cat dog로 해볼게요

개냐 고양이냐?를 판단하는 이미지 분류 작업입니다

 

 

폴더는 2개입니다

cat, dog 즉, 고양이 강아지 이렇게 입니다.

 

 

 

그리고 각 폴더 아래에 이렇게 고양이 사진들이 있죠.

고양이와 강아지(개) 사진은 크롤링해서 긁어 왔습니다

 

 

그리고 각 사진은 25000개 정도 있습니다.

데이터는 충분한 것 같네요

keras의 ImageDataGenerator를 굳이 사용안해도 될 것 같았습니다.

 

 

저는 사진 크기를 64x64 크기로 변환할 것입니다.

그래서 weight와 height를 64씩 주었습니다.

 

 

반응형

그 다음으로 이제 이미지 변환을 해줍니다.

각 이미지를 가지고 와서 RGB형태로 변환해준 뒤 resize해줍니다.

그리고 그 값을 numpy 배열로 바꾸고 배열에 추가해주죠.

동시에 category 값도 넣어줍니다(Y)

 

 

이제 컨볼루션 레이어(Conv2D)를 통해 이미지 인식 레이어를 구축합니다.

input_shape에는 64, 64, 3 값이 들어갑니다.

MaxPooling2D는 2x2사이즈로 지정해주고요

각 padding은 same, 마지막 출력층을 제외한 activation은 렐루(relu)로 합니다

그리고 얘는 2진 분류(카테고리가 2개)이니까 binary값으로 출력을 지정해줍니다.

 

 

val_loss값이 5번 이상 상승되지 않으면 자동적으로 멈추게 했습니다.(오버피팅, overfitting 방지)

batch_size는 64, epochs는 100번씩 돌면서 model을 fit 시켰습니다.

그 결과는 아래와 같습니다.

 

 

 

뭔가 불안정해 보이기도 하지만

훈련은 잘 되었습니다

정확도는 87%정도 나오네요

 

컨볼루션 레이어 계층들을 조금씩 수정해주거나 등등 하면 92%까지 올라가는 것을 확인했습니다.

 

이제 predict를 해볼까요?

해당 이미지 말고 전혀 다른 이미지로 예측을 해보았습니다.

 

 

테스트할 이미지를 변환할 소스입니다.

맨 처음 이미지를 RGB로 변환할 때와 같습니다.

300x250

 

그리고 해당 이미지를 predict합니다

테스트할 파일은 아래와 같이

 

 

2개의 폴더에 들어가있구요

 

 

전혀 다른 이미지로 구성되어 있습니다

이제 테스트를 해볼까요?

 

 

 

이렇게 나오네요

역시 100%가 아니라서 맞추지 못하는 것도 있습니다.

그래도 되긴되네요~

 

반응형
그리드형
95 Comments
  • 이전 댓글 더보기
  • 프로필사진 카카 2019.12.06 20:43 알약 이미지를 이용해서 train데이터 140개를 넣어서 모델을 완성했습니다.
    하지만 train 데이터에서 모델을 import 하려니
    ValueError: Error when checking input: expected conv2d_1_input to have 4 dimensions, but got array with shape (0, 1)
    라고 나와서 질문드립니다!!
  • 프로필사진 이수진의 블로그 2019.12.08 15:22 신고 안녕하세요.
    제 코드 기준에서 이미지를 넣으실 때 4 dimension으로 들어갑니다.
    근데 카카님께서 넣는 이미지는 2 dimension인 (0, 1)로 들어가시네요.

    보통 제 코드에서 해당 오류가 나오시는 분들을 보면 이미지 경로가 잘못 설정되어 있어서 이미지 upload를 못한 경우였습니다.

    한 번 참고해보셔요~
  • 프로필사진 윤가 2020.01.23 11:22 올려주신 포스팅과 소스코드로 공부중인 학생입니다! 마침 찾고있던 자료중 하나였는데 잘 설명해두어 주셔서 감사합니다~
    포스팅을 읽던중 궁금한 점이 있어 댓글남깁니다! 컨볼루션 레이어 계층을 수정하시고 정확도가 높아지셨다고 하셨는데
    어떻게 수정하신건가요?
    그리고 혹시 깃허브에 올려주신 소스코드는 컨볼루션 레이어 계층 수정후 정확도가 높아져 있는 소스코드인가요??
  • 프로필사진 이수진의 블로그 2020.01.23 13:30 신고 안녕하세요. 도움이 되셨다면 다행입니다.
    현재 올라가있는 코드는 CNN을 수정한 것이 아닐겁니다.
    CNN 수정은 단순히 layer를 더 쌓았고 필터 개수를 늘려준 것이 끝입니다~
  • 프로필사진 윤가 2020.02.21 16:12 답을 이제서야 확인했네요 감사합니다ㅎㅎㅎㅎ혹시 마지막 예측부분에서 얼마정도의 정확도를 나타내는지 텍스트로 출력하고싶은데 그런코드는 다른 게시글에서나 아니면 따로 없을까요?
  • 프로필사진 이수진의 블로그 2020.02.23 18:12 신고 안녕하세요~

    정확도 확인하는 부분은
    print("정확도 : %.4f" % (model.evaluate(X_test, y_test)[1]))

    이런식으로 하시면 됩니다 ㅎㅎ

    더 정확한 것은 제 git을 보시면 거의 마지막쯤에 정확도 부분 출력하는 것이 있을거에요~
  • 프로필사진 익명이 2020.04.08 23:19 CNN 공부 중인 학생입니다. 블로그 주인님의 코드를 그대로 돌려보았는데
    With n_samples=0, test_size=0.1 and train_size=None, the resulting train set will be empty. Adjust any of the aforementioned parameters.
    이러한 오류로 인해 더 이상 진행이 안되어서 이유를 혹시나 알 수 있을까 싶어 댓글 남깁니다. 구글링 열심히 했는데 해결책이 없네요..ㅠ
    예상으로는 scikit learn 버전이 달라서 에러 나는 거같은데 파이썬 버전이랑 sciki learn 버전을 알려주실 수 있나여?
  • 프로필사진 이수진의 블로그 2020.04.09 21:55 신고 안녕하세요.
    버저닝 문제가 아닌 것 같습니다.
    지금 에러 메세지를 보아하니 train set will be empty가 된다고 하네요. 현재 댓글 작성자님께서 구성하신 dataset에 데이터가 들어가져 있는지 확인을 해보셔야 할 것 같아요~
  • 프로필사진 2020.05.11 01:43 ./model/dog_cat_classify.model 경로는 어떤데 쓰이는 경로이고
    ./binary_img_data/img_test 경로는 어떤데 쓰이는 경로인지 궁급합니다.
  • 프로필사진 이수진의 블로그 2020.05.11 09:35 신고 안녕하세요.
    ./model/dog_cat_classify.model은 모델을 저장하는 또는 모델을 load하는 경로입니다.

    ./binary_img_data/img_test는 이진 분류 이미지 데이터에서 test 용 data set이 담겨있는 경로입니다.
  • 프로필사진 2020.05.11 10:50 앞에 쓴 사람입니다. 제가 경로문제때문에 오류가 나는것 같은데요 ./model/dog_cat_classify.model 경로가 빈공간 폴더를 두고 로드하면 오류데가 나는데 모델을 로드하는 폴더에는 무었이 들어가야 하나요?
    ./binary_img_data/imgs
    ./numpy_data/binary_image_data.npy
    ./binary_img_data/img_test
    ./model/dog_cat_classify.model
    /device:GPU:0
    각각 폴더의 의미가 무엇인지 넣어줘야 할 것,설정할 것이 무엇인지 어렵씁니다.ㅜㅜ
  • 프로필사진 이수진의 블로그 2020.05.11 13:46 신고 안녕하세요.

    ./model/에 들어가는 .model은 keras 모델을 training시키면 자동으로 .model 파일이 들어갑니다.
    따라서 미리 model 디렉토리를 만들어주셔야 해요.

    그리고 각종 파일은
    ./binary_img_data/imgs : 이미지 데이터
    ./numpy_data/binary_image_data.npy : 이미지 데이터가 numpy로 변환 된 데이터
    ./binary_img_data/img_test : 테스트용 이미지 데이터 셋
    ./model/dog_cat_classify.model : 위에서 말씀드린 모델
    /device:GPU:0 : 이거는 그냥 제 GPU환경입니다. 디렉토리가 아니에요~
  • 프로필사진 2020.05.11 18:12 감사합니다~
    몇가지 더 질문이 있는에요
    1)/numpy_data/binary_image_data.npy는 미리 만들어줘야 하나요 자동으로 생성되는 것인가요?
    2) prediction =model.predict(X)에서 오류가 나는데 경로를 다 지정을 했는데 오류가 나서요 파일을 만들어준게 지금 imgs 파일 폴더, imgtest폴더 그리고 model 폴더만 만들어주면 되나요??
    3)with K.tf_ops.device('/device:GPU:0'):
    을 적으면 오류가 나오는데 꼭 적어야 되는 것인가요? 사용하는 이유가 궁금합니다.
  • 프로필사진 이수진의 블로그 2020.05.12 10:27 신고 1) 은 코드 돌리면 생성되는 파일입니다.
    image -> numpy 형태로 바꿔주는 방법입니다.

    2) X에 넣는 데이터를 잘 지정해주셔야 합니다. X또한, numpy 형태로 바꿔주셔야 하구요.
    마찬가지로, 폴더 경로는 있어야하고, 그 안에 필요 데이터도 있어야 합니다. 그래야 동작합니다 ~

    3) 해당 옵션은 GPU를 사용하기 위한 옵션입니다~
  • 프로필사진 익명 2020.05.17 23:48 비밀댓글입니다
  • 프로필사진 익명 2020.05.18 10:11 비밀댓글입니다
  • 프로필사진 So 2020.05.18 12:13 비밀 댓글은 읽을수가 없나봅니다 ㅠㅠ
    답댓을 읽을 수가없네요
  • 프로필사진 이수진의 블로그 2020.05.18 15:18 신고 넵. 위 댓글 그대로 복붙할게요~

    1. 네 맞습니다. 3인 이유는 RGB이기 때문에 3입니다. gray를 하시려면 1로 하시면 됩니다 ~
    https://yashk2810.github.io/Applying-Convolutional-Neural-Network-on-the-MNIST-dataset/
    참고하세요~

    2. 음 Python 에서 이미지를 출력하는 옵션일 수도 있습니다. 그거까지는 정확하게 모르겠어요 ㅠㅠ 해본 경험이 없네요
  • 프로필사진 So 2020.05.19 01:08 정말 감사합니다.
    다른 참고 링크까지 올려주셔서 정말 많은 도움됐습니다.
    감사합니다!!
  • 프로필사진 이수진의 블로그 2020.05.19 09:36 신고 도움 되셨다면 다행입니다 ~
  • 프로필사진 min 2020.05.27 17:33 제가 이 블로그의 내용을 이용하여 모음 분류를 해보려고하는데, 아 에 이 오 우 정도의 폴더를 만들어 사진을 넣고 진행하려고합니다.
    이 예제를 통해서 응용이 가능할가요 아니면 다른 것을 찾아봐야될가요?ㅠㅠ
  • 프로필사진 이수진의 블로그 2020.05.28 09:16 신고 네 가능합니다~
    대신 이 글은 binary 분류이기 때문에 min님이 풀어보려고 하시는 것은 multi classification으로 푸셔야 합니다 ~
  • 프로필사진 real 2020.06.10 03:34 안녕하세요.
    for idx, cat in enumerate(categories):
    img_dir_detail = img_dir + "/" + cat
    files = glob.glob(img_dir_detail+"/*.jpg")
    이부분에 대해 질문드려도 될까요? img_dir_detail은 하위 폴더로 가는 것 같은데 그다음에있는 cat 부분이 이해가 안되네요 cat이 왜있는건지... 폴더 이름이면 밑부분처럼 ""를 썼을거같은데요..
  • 프로필사진 이수진의 블로그 2020.06.10 09:23 신고 안녕하세요.
    cat은 위에 for문에서 나와있듯이 category 정보입니다.
    카테고리 정보에 맞는 디렉토리에 들어가도록 코드를 만든 것입니다.

    말씀하신대로 밑부분처럼 손으로 하나하나 작성해도 되지만, 만약에 카테고리가 10000만개면 어떨까요? 손으로 하나하나 쓰기엔 너무 힘들겁니다. 그래서 저렇게 for문으로 도는것입니다.
  • 프로필사진 취준생 2020.06.16 12:50 이수진님의 방식을 추가해서 하는데, 계속 에러가 발생합니다. 도저히 잡을수가 없어서 도움을 요청합니다. ㅠ.ㅠ


    # 이미지 데이터 처리

    from PIL import Image
    import os, glob, numpy as np
    from sklearn.model_selection import train_test_split
    import cv2
    from keras.models import Sequential
    from keras.layers import Dropout, Activation, Dense
    from keras.layers import Flatten, Convolution2D, MaxPooling2D
    from keras.models import load_model
    from keras.layers import Dense, LSTM, Dropout, Conv2D
    from keras.preprocessing.image import ImageDataGenerator
    import sklearn.metrics as metrics


    ### 이미지 파일 불러오기 및 카테고리 정의
    # caltech_dir = './project/mini/images'
    caltech_dir = 'D:/Study-bit/project_mini/img'
    categories = ['dog_open', 'dog_closed']
    # categories = ['scooter', 'supersports', 'multipurpose', 'cruiser']
    nb_classes = len(categories)

    ### 가로, 세로, 채널 쉐이프 정의
    image_w = 64
    image_h = 64
    pixels = image_h * image_w * 3

    # 사진의 크기를 64*64 크기로 변환

    ### 이미지 파일 Data화 (이미지 파일 변환)
    X = []
    Y = []

    for idx, cat in enumerate(categories):
    label = [0 for i in range(nb_classes)]
    label[idx] = 1
    image_dir = caltech_dir + '/' + cat
    files = glob.glob(image_dir + "/*.jpg")
    print(cat, " 파일 길이 : ", len(files))

    for i, f in enumerate(files):
    img = Image.open(f)
    img = img.convert('RGB')
    img = img.resize((image_w, image_h))
    data = np.asarray(img)

    # 각 이미지를 가지고 와서 RGB형태로 변환해준 뒤, resize 해준다.
    # 그 값을 numpy배열로 바꾸고, 배열에 추가(append)한다.
    # 동시에 category 값도 넣어준다.(Y)
    # Y는 0 아니면, 1이니까 label값으로 넣는다.

    X.append(data)
    Y.append(label)

    if i % 700 == 0:
    print(cat, ':', f)

    x = np.array(X)
    y = np.array(Y)

    '''
    enumerate : 열거하다
    리스트가 있는 경우 순서와 리스트의 값을 전달하는 기능을 가집니다.
    이 함수는 순서가 있는 자료형(list, set, tuple, dictionary, string)을 입력으로 받아
    인덱스 값을 포함하는 enumerate 객체를 리턴합니다.
    보통 enumerate 함수는 for문과 함께 자주 사용됩니다.

    dog_open : 50개

    dog_closed : 50개
    '''

    print(x.shape) # (200, 100, 100, 3)
    print(y.shape) # (100, 2)

    # print(x.shape) # (100, 64, 64, 3)
    # print(y.shape) # (200, 4)


    ### 데이터 train_test_split
    x_train, x_test, y_train, y_test = train_test_split(x, y, train_size=0.8)
    xy = (x_train, x_test, y_train, y_test)

    print(x_train.shape) # (80, 64, 64, 3)
    print(x_test.shape) # (20, 64, 64, 3)
    print(y_train.shape) # (80, 2)
    print(y_test.shape) # (20, 2)

    # print(x_train.shape) # (160, 100, 100, 3)
    # print(x_test.shape) # (40, 100, 100, 3)
    # print(y_train.shape) # (160, 4)
    # print(y_test.shape) # (40, 4)

    ### 데이터 SAVE

    np.save('D:/Study-bit/project_mini/data.npy', xy)
    print('ok', len(y))

    cv2.waitKey(0)
    # X.append(img/256)
    # Y.append(label)

    np.save('./project_mini/data/multi_image_data.npy', xy)
    # print('ok', len(y))

    ### 데이터 load

    # X_train, X_test, Y_train, Y_test = np.load('D:/Study-bit/project_mini/data.npy')
    xy = np.load('D:/Study-bit/project_mini/data.npy', allow_pickle=True)

    print(xy)


    x_train = x_train.reshape(80, 64, 64, 3).astype('float32') /255
    x_test = x_test.reshape(20, 64, 64, 3).astype('float32') /255

    print(x_train.shape) # (80, 64, 64, 3)
    print(x_test.shape) # (20, 64, 64, 3)
    print(y_train.shape) # (80, 2)
    print(y_test.shape) # (20, 2)


    ### 모델 만들기

    model = Sequential()

    model.add(Conv2D(600,(4, 4), input_shape = x_train.shape[1:], activation = 'relu', padding = 'same'))
    model.add(Dropout(0.2))
    model.add(MaxPooling2D(pool_size = 2))

    model.add(Conv2D(500,(3, 3), activation = 'relu', padding = 'same'))
    model.add(Dropout(0.2))

    model.add(Conv2D(480,(2, 2), activation = 'relu', padding = 'same'))
    model.add(Dropout(0.2))

    model.add(Conv2D(450, (2, 2),activation = 'relu', padding = 'same'))
    model.add(Dropout(0.2))

    model.add(Conv2D(350, (2, 2),activation = 'relu', padding = 'same'))
    model.add(Dropout(0.2))

    model.add(Conv2D(200, (2, 2),activation = 'relu', padding = 'same'))
    model.add(Dropout(0.2))

    model.add(Conv2D(180,(2, 2), activation = 'relu', padding = 'same'))
    model.add(Dropout(0.2))

    model.add(Conv2D(140,(2, 2), activation = 'relu', padding = 'same'))
    model.add(Dropout(0.2))

    model.add(Conv2D(20,(3, 3),activation = 'relu', padding = 'same'))
    model.add(Flatten())

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

    model.summary()


    # callbacks
    from keras.callbacks import EarlyStopping, TensorBoard, ModelCheckpoint

    # earlystopping
    es = EarlyStopping(monitor = 'val_loss', patience = 50, verbose = 1 )

    # tensorboard
    ts_board = TensorBoard(log_dir = 'graph', histogram_freq = 0,
    write_graph = True, write_images = True)

    # modelcheckpotin
    modelpath = './model/{epoch:02d}-{val_loss:.4f}.hdf5'

    ckpoint = ModelCheckpoint(filepath = modelpath, monitor = 'val_loss',
    save_best_only = True)



    #3. 훈련

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

    hist = model.fit(x_train, y_train, epochs = 100, batch_size = 32,
    validation_split = 0.2, verbose = 2,
    callbacks = [es])



    #4. 평가, 예측 (evaluate, predict)

    print("-- Evaluate --")
    loss, acc = model.evaluate(x_test, y_test, batch_size = 32)

    print('loss: ', loss )
    print('acc: ', acc)
    여기까지는 출력이 되는데, 그 다음부터가... 안됩니다.
    ------------------------

    # 테스트할 이미지를 변환할 소스
    X = [ ]
    filenames = [ ]
    files = glob.glob(caltech_dir + "/*/*.*")
    for i, f in enumerate(files):
    img = Image.open(f)
    img = img.convert("RGB")
    img = img.resize((image_w, image_h))

    filenames.append(f)
    X.append(data)

    # 해당 이미지를 predict
    print("-- Predict --")
    # output = model.predict_generator(x_test, y_test, steps=5)

    # np.set_printoptions(formatter={'float': lambda x: "{0:0.3f}".format(x)})

    # print(x_test, y_test.class_indices)
    # print(output)

    np.set_printoptions(precision=3)
    predction = model.predict(X)
    # predction = model.predict(Y)
    np.set_predctions(formatter = {'float' : lambda x: "{0:0.3f}".format(x)})
    '''
    loss: 0.6998974084854126
    acc: 0.4000000059604645
    '''

    # graph
    import matplotlib.pyplot as plt
    plt.figure(figsize = (10, 5))

    # 1
    plt.subplot(2, 1, 1)
    plt.plot(hist.history['loss'], c= 'red', marker = '^', label = 'loss')
    plt.plot(hist.history['val_loss'], c= 'cyan', marker = '^', label = 'val_loss')
    plt.title('loss')
    plt.xlabel('epochs')
    plt.ylabel('loss')
    plt.legend()

    # 2
    plt.subplot(2, 1, 2)
    plt.plot(hist.history['acc'], c= 'red', marker = 'o', label = 'acc')
    plt.plot(hist.history['val_acc'], c= 'cyan', marker = 'o', label = 'val_acc')
    plt.title('accuarcy')
    plt.xlabel('epochs')
    plt.ylabel('acc')
    plt.legend()

    plt.show()

  • 프로필사진 이수진의 블로그 2020.06.17 09:34 신고 안녕하세요.
    어디서, 어떤 부분이 안되는지, 어떤 오류가 나오는지 작성해주셔야 제가 첨언을 해드릴 수 있을 것 같습니다 ㅠ
  • 프로필사진 익명 2020.06.23 18:04 비밀댓글입니다
  • 프로필사진 익명 2020.06.23 23:15 비밀댓글입니다
  • 프로필사진 글 잘읽었습니다~ 2020.06.29 15:54 안녕하세요ㅠㅠ 어제 질문하고 혼자 답찾아서 좋다고 난리친 사람 입니다...ㅠㅠ 도와주세요ㅠㅠ
    model = Sequential()
    model.add(Conv2D(32, (3,3), padding = "same", input_shape = X_train.shape[1:], activation = 'relu'))
    model.add(MaxPooling2D(pool_size = (2,2)))
    model.add(Dropout(0.25))

    model.add(Conv2D(64, (3,3), padding = "same", activation = 'relu'))
    model.add(MaxPooling2D(pool_size = (2,2)))
    model.add(Dropout(0.25))

    model.add(Conv2D(64, (3,3), padding = "same", activation = 'relu'))
    model.add(MaxPooling2D(pool_size = (2,2)))
    model.add(Dropout(0.25))

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

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

    model.fit(X_train, Y_train, batch_size = 32, nb_epoch = 100)
    score = model.evaluate(X_test, Y_test)
    print('loss==>', score[0])
    print('accuracy==>', score[1])
    이렇게 하고, model.save('T.h5')로 저장했는데
    module 'keras.optimizers' has no attribute 'TFOptimizer' 이런 오류가 났습니다ㅠㅠ 어떻게 해야할까요,,,,ㅠㅠ
  • 프로필사진 이수진의 블로그 2020.06.30 09:56 신고 안녕하세요.
    음... 해당 오류는 저도 처음보네요
    저장하는 부분에서 에러가 나는 것인가요?
    저도 찾아봐야 할 것 같은데요. ㅠ
  • 프로필사진 글 잘읽었습니다~ 2020.07.01 22:56 해결했습니다!(흐어ㅠㅠ)
    텐서플로우랑 케라스 설치 문제였던거 같아요~ 지우고 다시 처음부터 깔았더니 잘 실행 되었습니다!ㅎㅎ
  • 프로필사진 이수진의 블로그 2020.07.02 17:10 신고 아 ㅎㅎ 그렇군요 다행입니다 ~
  • 프로필사진 안녕하세요 2020.08.10 11:31 안녕하세요. 블로그 참고하면서 많이 배울수 있었습니다. 현재 개/고양이 데이터셋이 아닌 물체의 단면 사진을 학습시켜 OK/NG를 판단하는 모델을 만드는 중입니다.
    이 과정에서 train과 validation까지는 80%정도의 정확도를 얻을 수 있었는데 test set으로 예측했을 때 NG만 나오거나 OK만 나오는 상태입니다. prediction값을 확인해 보아도 NG일때 모든 예측값이 0.49에서 +-0.01정도로 측정됩니다..
    단면의 상태를 체크하는 모델을 만들고자 하는데 전체 이미지 중 단면이 차지하는 비율이 작다보니 특징 추출이 제대로 되지 않아서인지
    다른 이유가 있는건지 모르겠습니다 ㅜㅜ
    학습까지는 잘 되는데 테스트 과정에서 예측이 비슷한 값만 계속 나오는 현상이 왜 발생하는 걸까요?
    사진을 올릴수가 없어서 이미지 파일은 보여드리지 못하네요..

    전체 코드는 이렇습니다.
    #데이터를 불러들이기 위한 디렉토리 지정
    base_dir = './Laser_Img/NEW/LEARNING'
    train_dir = os.path.join(base_dir, 'TRAIN')
    validation_dir = os.path.join(base_dir, 'VALIDATION')
    test_dir = os.path.join(base_dir, 'TEST')

    train_NG = os.path.join(train_dir, 'NG')
    train_OK = os.path.join(train_dir, 'OK')
    validation_NG = os.path.join(validation_dir, 'NG')
    validation_OK = os.path.join(validation_dir, 'OK')

    #Train과 Validation의 NG, Ok에 해당하는 사진의 갯수
    num_NG_tr = len(os.listdir(train_NG))
    num_OK_tr = len(os.listdir(train_OK))
    num_NG_val = len(os.listdir(validation_NG))
    num_OK_val = len(os.listdir(validation_OK))

    #전체 Train, Validation 총 갯수
    total_train = num_NG_tr + num_OK_tr
    total_val = num_NG_val + num_OK_val

    BATCH_SIZE = 32
    IMG_SHAPE = 150

    #Generator
    train_image_generator = ImageDataGenerator(rescale=1./255)

    validation_image_generator = ImageDataGenerator(rescale=1./255)

    train_data_gen = train_image_generator.flow_from_directory(batch_size = BATCH_SIZE,
    directory = train_dir,
    shuffle = True,
    target_size = (IMG_SHAPE, IMG_SHAPE),
    class_mode = 'binary')

    val_data_gen = validation_image_generator.flow_from_directory(batch_size = BATCH_SIZE,
    directory = validation_dir,
    shuffle = False,
    target_size = (IMG_SHAPE, IMG_SHAPE),
    class_mode = 'binary')

    #Model
    model = tf.keras.models.Sequential([
    #Conv2D 컨볼루션 필터 수 / 커널(필터)의 행,열 / 활성함수 / Input Shape(최초 레이어에만 적용)
    tf.keras.layers.Conv2D(32, (3,3), activation='relu', input_shape=(IMG_SHAPE, IMG_SHAPE, 3)),
    tf.keras.layers.MaxPooling2D(2,2),
    tf.keras.layers.Dropout(0.2),

    tf.keras.layers.Conv2D(64, (3,3), activation='relu'),
    tf.keras.layers.MaxPooling2D(2,2),
    tf.keras.layers.Dropout(0.2),

    tf.keras.layers.Conv2D(128, (3,3), activation='relu'),
    tf.keras.layers.MaxPooling2D(2,2),
    tf.keras.layers.Dropout(0.2),

    tf.keras.layers.Conv2D(128, (3,3), activation='relu'),
    tf.keras.layers.MaxPooling2D(2,2),
    tf.keras.layers.Dropout(0.2),

    #Classification을 위해 Flatten()을 통해 1차원 데이터로 변경 후 Dense Layer로 입력
    tf.keras.layers.Flatten(),
    tf.keras.layers.Dense(256, activation='relu'),
    #출력층의 활성화함수는 이진분류를 위한 sigmoid함수를 사용
    tf.keras.layers.Dense(1, activation='sigmoid')
    ])

    #optimizer는 GradientDescent에 비해 발전된 최적화 기법인 adam을 사용
    #loss function은 이진분류를 위한 binary crossentropy
    model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])

    #Model의 구조를 요약해 출력해 줍니다.
    model.summary()

    #Model을 저장한다
    model.save('image_bin_classification.h5')

    #전체 Model을 학습하는 횟수
    EPOCHS = 10

    #Model을 학습시킨다
    #큰 크기의 데이터셋을 학습시키기 위한 fit_generator
    history = model.fit_generator(train_data_gen,
    steps_per_epoch=int(np.ceil(total_train / float(BATCH_SIZE))),
    epochs=EPOCHS, validation_data=val_data_gen,
    validation_steps=int(np.ceil(total_val / float(BATCH_SIZE))),
    )

    acc = history.history['acc']
    val_acc = history.history['val_acc']

    loss = history.history['loss']
    val_loss = history.history['val_loss']

    epochs_range = range(EPOCHS)

    #plot을 만들어 training set과 validation set의 accuracy, loss를 각각 구해줘 그래프로 표현한다.
    plt.figure(figsize=(8, 8))
    plt.subplot(1,2,1)
    plt.plot(epochs_range, acc, label='Training Accuracy')
    plt.plot(epochs_range, val_acc, label='Validation Accuracy')
    plt.legend(loc='lower right')
    plt.title('Training and Validation Accuracy')

    plt.subplot(1,2,2)
    plt.plot(epochs_range, loss, label='Training Loss')
    plt.plot(epochs_range, val_loss, label='Validation Loss')
    plt.legend(loc='upper right')
    plt.title('Training and Validation Loss')
    plt.show()

    ****************************************************************************************

    from PIL import Image
    import os, glob, numpy as np
    from tensorflow.keras.models import load_model
    import tensorflow as tf

    print('----------PREDICT-----------')
    test_dir = os.path.join(base_dir, 'TEST')

    #Test set 불러오기
    X = []
    filenames = []
    files = glob.glob(test_dir+"/*.*")
    for i, f in enumerate(files):
    img = Image.open(f)
    img = img.convert("RGB")
    img = img.resize((IMG_SHAPE, IMG_SHAPE))
    data = np.asarray(img)

    filenames.append(f)
    X.append(data)

    X = np.array(X)
    X = X.astype(float) / 255

    #Model 불러오기
    model = load_model('./image_bin_classification.h5')

    #예측
    prediction = model.predict(X)
    np.set_printoptions(formatter={'float': lambda x: "{0:0.3f}".format(x)})
    cnt = 0
    for i in prediction:
    if i >= 0.5:
    print("해당 " + filenames[cnt].split("\\")[1] + filenames[cnt].split("\\")[2] + " 이미지는 Ok 로 추정됩니다.")
    IMG = Image.open(files[cnt])
    IMG.save('./Laser_Img/NEW/LEARNING/PREDICTED/OK/OK'+f'{cnt}.png')

    else:
    print("해당 " + filenames[cnt].split("\\")[1] + filenames[cnt].split("\\")[2] + " 이미지는 NG 로 추정됩니다.")
    IMG = Image.open(files[cnt])
    IMG.save('./Laser_Img/NEW/LEARNING/PREDICTED/NG/NG'+f'{cnt}.png')

    cnt += 1

  • 프로필사진 이수진의 블로그 2020.08.11 06:26 신고 안녕하세요.
    음.. 정확히 어떤 데이터이고 어떤 특징이 있는지 모르기 때문에 정확한 답변을 드리기는 어려울 것 같네요.
    일단 제가 추측하기로는 training 과정에서 validation loss 까지 잘 떨어지시면 training과정은 문제가 없어 보입니다.

    다만 지금 의심되는 것은
    training 때와 test 일 때 data 전처리가 다르다는 것입니다.
    training때는 ImageDataGenertator를 활용하셨는데 Test 데이터 생성할 때는 PIL을 사용하셨네요.
    이 Test 부분을 Train 때와 일치시켜서 해보시겠어요??
  • 프로필사진 안녕하세요 2020.08.12 08:52 안녕하세요 달아주신 댓글 참고해서 성공했습니다 ㅜㅜ 이미지 전처리를 동일하게 하는게 답이었네요. 감사합니다. 한가지만 더 물어볼게 있는데 이미지 데이터셋 자체가 부족해서 augmentation 이후에 train/validation/test set으로 나눴는데 이 부분도 모델의 학습에 문제가 생길 소지가 있을까요?
  • 프로필사진 이수진의 블로그 2020.08.12 22:20 신고 안녕하세요.
    성공하셨다니 다행이네요 ㅎㅎ

    음 아무래도 임의로 만들어준 데이터다 보니 문제가 발생할 수도 있습니다.

    만들어둔 데이터 셋으로
    - train
    - validation
    - test
    를 잘 나눠서 학습을 하면 모델 결과는 우수하게 나올 수도 있습니다.
    하지만 실제 production 상에서 문제가 될 수도 있는것이죠. 아무래도 real 데이터가 아닌, 임의로 만들어진 데이터이니까요!
  • 프로필사진 안녕하세요 2020.08.13 10:29 덕분에 공부 많이 됐습니다 감사합니다~~
  • 프로필사진 berry_gayo 2020.09.22 10:53 안녕하세요 ~ 정리해주신 글을 보며 공부하고 있습니다~
    test image에서 강아지 / 고양이를 0과1로 이진분류 하지 않고
    확률로 받아서 그 외의 이미지로도 분류할 수 있을까요 ?

    예를들어 코끼리 사진이 test로 들어온다면
    개와 고양이가 아닙니다~ 라는 결과값을 얻고 싶습니다.
  • 프로필사진 이수진의 블로그 2020.09.22 21:48 신고 안녕하세요.
    네 물론이죠. 단순히 predict를 하면 확률 값으로 나옵니다.

    그래서 확률 값이 만약 i에 나온다면

    if i > 0.5 : 이렇게 조건을 달아서 할 수 있습니다.

    그러나, 해당 문제는 개/고양이에 대한 이진 분류이기 때문에 개/고양이에 대한 각각 확률을 뽑아줍니다.

    즉, 코끼리 사진이 들어오면 개 혹은 고양이 확률이 나오게 되는 것입니다. 그래서 개/고양이 외의 사진을 다른 분류로 풀고 싶으시면 개/고양이 외의 사진을 넣고 '그외' 이런 식으로 하나의 카테고리를 추가해줘서 학습시켜야 합니다.
  • 프로필사진 berry_gayo 2020.09.24 10:41 안녕하세요. 답글 감사합니다.

    https://codetorial.net/tensorflow/classifying_the_cats_and_dogs.html

    제가 이 코드를 참고하여 공부하고있습니다.
    sigmoid 로 분류시켰는데 결과값이 확률로 안떨어지고 0/1 값으로 나오는데 혹시 어디가 문제인지 아시나요 ?? ㅠㅠ
  • 프로필사진 이수진의 블로그 2020.09.25 14:35 신고 안녕하세요.

    sigmoid와 binary_crossentropy를 사용하시면 확률로 떨어질 겁니다!
  • 프로필사진 at home 2021.04.05 22:21 안녕하세요,
    혹시 jupyter에서 코드를 실행하는데 import keras.backend.tensorflow_backend as K 이부분에서 No module named 'keras.backend.tensorflow_backend'; 'keras.backend' is not a package 라는 오류가 뜨는데 이건 어떻게 해결할 방법이 없을까요,,?
  • 프로필사진 이수진의 블로그 2021.04.06 19:24 신고 안녕하세요.
    해당 오류는 keras 버전 문제 인 것 같습니다.
    제가 이 코드를 구성했을 때는 tensorflow1.x이고 keras2.x로 진행했습니다.

    아마 tensorflow2.x로 올라오면서 환경이 많이 바뀌었을겁니다.

    이거 참고해서 구글링 찾아보시면 될 것 같습니다!
  • 프로필사진 keras 2021.07.28 20:55 안녕하세요 이수진님
    from PIL import Image
    import os, glob, sys, numpy as np
    from sklearn.model_selection import train_test_split
    from keras.utils import np_utils

    img_dir = './ipynb/data/train'
    categories = ['Cat', 'Dog']
    np_classes = len(categories)

    image_w = 64
    image_h = 64


    pixel = image_h * image_w * 3

    X = []
    y = []

    for idx, cat in enumerate(categories):
    img_dir_detail = img_dir + "/" + cat
    files = glob.glob(img_dir_detail+"/*.jpg")


    for i, f in enumerate(files):
    try:
    img = Image.open(f)
    img = img.convert("RGB")
    img = img.resize((image_w, image_h))
    data = np.asarray(img)
    #Y는 0 아니면 1이니까 idx값으로 넣는다.
    X.append(data)
    y.append(idx)
    if i % 300 == 0:
    print(cat, " : ", f)
    except:
    print(cat, str(i)+" 번째에서 에러 ")
    X = np.array(X)
    Y = np.array(y)


    X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.1)

    xy = (X_train, X_test, Y_train, Y_test)
    np.save("./numpy_data/binary_image_data.npy", xy)
    맨처음 코드보고 데이터를 옮겨서 하고 난 다음

    from keras.models import Sequential
    from keras.layers import Conv2D, MaxPooling2D, Dense, Flatten, Dropout
    from keras.callbacks import EarlyStopping, ModelCheckpoint
    import matplotlib.pyplot as plt
    import tensorflow.python.keras.backend as K

    X_train, X_test, y_train, y_test = np.load('./numpy_data/binary_image_data.npy')
    print(X_train.shape)
    print(X_train.shape[0])
    print(np.bincount(y_train))
    print(np.bincount(y_test))
    부분을 하고 있는데
    X_train, X_test, y_train, y_test = np.load('./numpy_data/binary_image_data.npy')에서
    ValueError: Object arrays cannot be loaded when allow_pickle=False
    이러한 오류가 나와서 어떤 오류이고 어떻게 하면 고칠 수 있는지 알 수 있을까요?
  • 프로필사진 이수진의 블로그 2021.07.29 18:40 신고 안녕하세요~

    해당 오류는 numpy를 load할 떄 생기는 오류입니다.
    load시 allow_picke=True로 지정해주시면 됩니다

    https://stackoverflow.com/questions/55890813/how-to-fix-object-arrays-cannot-be-loaded-when-allow-pickle-false-for-imdb-loa
    참고해보시면 될 것 같습니다~
  • 프로필사진 익명 2021.11.21 16:01 비밀댓글입니다
  • 프로필사진 익명 2021.11.22 17:36 비밀댓글입니다
  • 프로필사진 익명 2022.01.28 10:36 img_dir = './binary_img_data/imgs' 처럼 처음 파일경로에 대한 이해가 잘 안되네요ㅠㅠ

    평소에 코랩에서 사진 데이터 저장한후 불러오곤 했는데, 저런 경로는 어떻게 쓰는지 잘 이해가 안됩니다,,

    np.save("./numpy_data/binary_image_data.npy", xy)
    저장하는 이 부분도 마찬가지네요..

    학습 이미지 파일을 각 폴더로 이진 분류한 상태인데, 이 이후에 어떻게 업로드하는지 모르겠습니다

    많이 배우고 있습니다. 감사합니다.
  • 프로필사진 이수진의 블로그 2022.02.01 20:20 신고 안녕하세요. 답변이 늦었습니다.

    경로에 대해서 궁금하시면 상대경로, 절대경로에 대해 알아두시면 될 것 같습니다~

    이 경로 개념만 알아두시면 환경에 관계없이 사용하실 수 있으실거에요~
  • 프로필사진 ssuuu 2022.02.18 15:39 안녕하세요 딥러닝관련하여 바이너리 실행파일을 이미지로 변환하는 방식은 어떤식으로 구현하면 될까요?
  • 프로필사진 이수진의 블로그 2022.02.21 18:16 신고 안녕하세요.

    음.. 제가 질문을 잘 이해하지 못하겠습니다.

    바이너리 실행 파일은 실행 파일인데 이걸 이미지로 변경한다는 말씀이실까요??
  • 프로필사진 QUES 2022.04.06 10:58 안녕하세요, 현재 개/고양이 이진분류 딥러닝 중입니다. training 및 Test 파일 이외의 새로운 고양이 파일올 넣어서 예측을 하려고 하는데
    jpg 파일을 하나씩 넣는데 predict에서 return 값 shape가 (1,2)로 나오네요 (training 및 test loss 는 정상적으로 수렴하는거 같습니다.)

    도움부탁드려요! 아 그리고, 지금까지도 많은 도움 주셔서 감사합니다. ㅎㅎ
  • 프로필사진 이수진의 블로그 2022.04.10 13:27 신고 안녕하세요.
    음. shape가 그렇게 나온다는 것은 데이터를 제대로 읽지 못한 것 같습니다.

    경로나, 이미지 불러오는 것의 중간 값, 등등을 잘 확인해보세요!
  • 프로필사진 park 2022.04.07 20:22 안녕하세요
    좋은 글 감사합니다.

    혹시 해당 학습 모델을 사용해서
    비디오 영상에 강아지가 나오면 강아지, 고양이가 나오면 고양이라고 영상 화면에서 예측해서 보여주는 것도 가능할까요?
  • 프로필사진 이수진의 블로그 2022.04.10 13:28 신고 안녕하세요.

    아 말씀주신 내용은 불가능합니다.
    제 예제는 단순히 이미지를 기반으로 한 것이고 비디오 영상에 강아지, 고양이를 바로 식별하는 것은 object detection 기술을 사용해야 할 것 같습니다!
댓글쓰기 폼