거친 이미지 분류기 만들어 보기(8) 학습2

카탈로그

  • 말도 안 되는 이미지 분류기 만들기 (1) 서장
  • 거친 이미지 분류기 만들기 (2) 데이터 수집 중 하나
  • 말도 안 되는 이미지 분류기 만들기 (3) 데이터 수집의 2
  • 말도 안 되는 이미지 분류기 만들기 (4) 데이터 수집 3
  • 거친 이미지 분류기 만들기 (5) 데이터 관리 1
  • 말도 안 되는 이미지 분류기 만들기 (6) 데이터 관리 2
  • 거친 이미지 분류기 만들어 보기(7) 학습 중 하나
  • 말도 안 되는 이미지 분류기 만들기 (8) 학습의 2 (본 보도)
  • 말도 안 되는 이미지 분류기 만들어 보기(9) 추론
  • 번외편:
  • EfficientNet B0~B7에서 학습 이미지 분류기 옮기기
  • EfficientNet B0의 Keeras 모델을 ONX 모델로 변환하여 추론
  • 유사한 이미지 검색 도구 만들기 (1) 서장
  • 계속 공부하다


    저번 데이터의 분할을 진행했다.이번에는 실제로 공부를 해야 한다.

    결론


    먼저 결론을 쓰면 정밀도(Acuracy) 85% 정도의 이미지 분류 모델을 얻을 수 있다.
    처음이라 거의 공을 들이지 않았고, 구성은 상당히 간단했다.각양각색의 수법을 응용함으로써 나는 수%의 정밀도를 더욱 높일 수 있다고 생각한다.

    데이터 사전 처리


    Keeras 학습 모델을 사용할 때 데이터의 읽기가 사용되었다tf.keras.preprocessing.image.ImageDataGenerator.(노동력과 자재를 줄이기 위해)ImageDataGenerator 특정한 디렉터리 구조를 전제로 기존의 이미지 데이터를 이 구조에 배치한다.
    파일을 복사하는 것은 무용지물이기 때문에 이번에 기호 링크를 만들었다.
    구체적으로, 유사한 /tmp/cache/pornography/<タイプ>/<ラベル>/オブジェクトID.jpg 경로를 통해 기호 링크를 만듭니다.
    스크립트는 다음과 같습니다.
    make_link.py
    #!/usr/bin/env python3
    
    import os
    import pathlib
    
    import pandas as pd
    
    def make_nested_id_path(dir, id, ext=""):
        return dir / id[0:2] / id[2:4] / (id + ext)
    
    MEDIA_DIR = pathlib.Path(os.environ.get("MEDIA_DIR"))
    OBJECT_DIR = MEDIA_DIR / "object"
    CACHE_DIR = pathlib.Path("/tmp/cache/pornography")
    CACHE_DIR.mkdir(parents=True, exist_ok=True)
    
    df = pd.read_csv("split_label.csv")
    
    for type in ["train", "test", "validation"]:
      for index, (object_id, value) in df[["objectId", "value"]][df["type"] == type].iterrows():
          image_path = make_nested_id_path(OBJECT_DIR, object_id)
          target_path = CACHE_DIR / type / str(value) / object_id
          target_path.parent.mkdir(parents=True, exist_ok=True)
          if not target_path.exists():
              target_path.symlink_to(image_path)
    

    학습 환경


    학습은 Docker 컨테이너 안에서 진행된다.Dockerfile는 다음과 같다.
    Dockerfile
    FROM nvidia/cuda:11.0.3-cudnn8-devel-ubuntu20.04
    RUN apt-get update \
      && DEBIAN_FRONTEND=noninteractive apt-get install --yes --no-install-recommends \
        build-essential \
        ca-certificates \
        python3-dev \
        python3-pip \
        python3-setuptools \
        tzdata \
      && rm --recursive --force /var/lib/apt/lists/*
    RUN python3 -m pip install --upgrade pip setuptools
    WORKDIR /opt/app
    COPY requirements.txt ./
    RUN python3 -m pip install --requirement requirements.txt
    ENV LANG C.UTF-8
    ENV TZ Asia/Tokyo
    
    또한requirements.txt은 다음과 같다.관련 주요 포장만 기재되어 있습니다.
    requirements.txt
    numpy==1.19.5
    pandas==1.2.3
    Pillow==8.2.0
    scipy==1.6.2
    tensorflow-estimator==2.4.0
    tensorflow-hub==0.11.0
    tensorflow==2.4.1
    
    또한 NVIDIA의 GPU를 사용하기 위해NVIDIA Container Toolkit가 필요합니다.

    배우다


    그럼 드디어 공부를 해야겠네요.주요 초변수 등은 다음과 같다.
  • 골간: EfficientNet B0
  • 헤드(Head): Fully Connected(FC: Fully Connected) + Sigmoid
  • optimizer:Adam
  • 입력 이미지 크기: 224 x 224
  • 볼륨 크기: 512
  • 열거수: 10
  • 학습에 사용된 스크립트는 다음과 같다.
    train.py
    #!/usr/bin/env python3
    
    import datetime
    
    import pandas as pd
    import tensorflow as tf
    import tensorflow_hub as hub
    
    BATCH_SIZE = 512
    TARGET_SIZE = (224, 224)
    EPOCHS = 10
    
    model = tf.keras.Sequential(
        [
            hub.KerasLayer(
                "https://tfhub.dev/tensorflow/efficientnet/b0/feature-vector/1",
                trainable=False,
            ),
            tf.keras.layers.Dense(1, activation="sigmoid"),
        ]
    )
    model.build([None, 224, 224, 3])
    model.compile(
        optimizer=tf.keras.optimizers.Adam(),
        loss="binary_crossentropy",
        metrics=["accuracy"],
    )
    model.summary()
    
    train_datagen = tf.keras.preprocessing.image.ImageDataGenerator(rescale=(1.0 / 255))
    train_generator = train_datagen.flow_from_directory(
        "/tmp/cache/pornography/train",
        target_size=TARGET_SIZE,
        batch_size=BATCH_SIZE,
        class_mode="binary",
    )
    
    validation_datagen = tf.keras.preprocessing.image.ImageDataGenerator(
        rescale=(1.0 / 255)
    )
    validation_generator = validation_datagen.flow_from_directory(
        "/tmp/cache/pornography/validation",
        target_size=TARGET_SIZE,
        batch_size=BATCH_SIZE,
        class_mode="binary",
    )
    
    test_datagen = tf.keras.preprocessing.image.ImageDataGenerator(rescale=(1.0 / 255))
    test_generator = test_datagen.flow_from_directory(
        "/tmp/cache/pornography/test",
        target_size=TARGET_SIZE,
        batch_size=BATCH_SIZE,
        class_mode="binary",
    )
    
    model.fit(
        x=train_generator,
        steps_per_epoch=train_generator.n // BATCH_SIZE,
        epochs=EPOCHS,
        workers=8,
        validation_data=validation_generator,
        validation_steps=validation_generator.n // BATCH_SIZE,
        callbacks=[
            tf.keras.callbacks.TensorBoard(
                log_dir="log/" + datetime.datetime.now().strftime("%Y%m%d_%H%M%S"),
                histogram_freq=1,
            )
        ],
    )
    
    model.evaluate(x=test_generator, steps=(test_generator.n // BATCH_SIZE), workers=8)
    
    model.save("model.h5")
    
    실행 결과는 다음과 같습니다.공부 시간은 약 10분입니다.
    $ ./src/train.py
    ...
    Model: "sequential"
    _________________________________________________________________
    Layer (type)                 Output Shape              Param #
    =================================================================
    keras_layer (KerasLayer)     (None, 1280)              4049564
    _________________________________________________________________
    dense (Dense)                (None, 1)                 1281
    =================================================================
    Total params: 4,050,845
    Trainable params: 1,281
    Non-trainable params: 4,049,564
    _________________________________________________________________
    Found 19658 images belonging to 2 classes.
    Found 1494 images belonging to 2 classes.
    Found 1488 images belonging to 2 classes.
    ...
    Epoch 1/10
    38/38 [==============================] - 68s 1s/step - loss: 0.6039 - accuracy: 0.6356 - val_loss: 0.4211 - val_accuracy: 0.8115
    Epoch 2/10
    38/38 [==============================] - 54s 1s/step - loss: 0.3425 - accuracy: 0.8594 - val_loss: 0.3497 - val_accuracy: 0.8447
    Epoch 3/10
    38/38 [==============================] - 52s 1s/step - loss: 0.3100 - accuracy: 0.8672 - val_loss: 0.3444 - val_accuracy: 0.8486
    Epoch 4/10
    38/38 [==============================] - 53s 1s/step - loss: 0.2925 - accuracy: 0.8726 - val_loss: 0.3309 - val_accuracy: 0.8506
    Epoch 5/10
    38/38 [==============================] - 53s 1s/step - loss: 0.2813 - accuracy: 0.8815 - val_loss: 0.3483 - val_accuracy: 0.8457
    Epoch 6/10
    38/38 [==============================] - 54s 1s/step - loss: 0.2754 - accuracy: 0.8820 - val_loss: 0.3282 - val_accuracy: 0.8545
    Epoch 7/10
    38/38 [==============================] - 52s 1s/step - loss: 0.2696 - accuracy: 0.8855 - val_loss: 0.3247 - val_accuracy: 0.8564
    Epoch 8/10
    38/38 [==============================] - 53s 1s/step - loss: 0.2603 - accuracy: 0.8900 - val_loss: 0.3111 - val_accuracy: 0.8672
    Epoch 9/10
    38/38 [==============================] - 53s 1s/step - loss: 0.2597 - accuracy: 0.8881 - val_loss: 0.3178 - val_accuracy: 0.8564
    Epoch 10/10
    38/38 [==============================] - 53s 1s/step - loss: 0.2523 - accuracy: 0.8911 - val_loss: 0.3320 - val_accuracy: 0.8477
    2/2 [==============================] - 8s 1s/step - loss: 0.3170 - accuracy: 0.8535
    
    학습 진전이 양호하다.테스트 데이터의 평가 정밀도는 약 85퍼센트다.
    TensorBoard를 통해 확인된 정밀도 차트는 다음과 같습니다.

    마찬가지로 Looss의 차트는 다음과 같습니다.

    향후의 전망


    특별한 시간이 없으면 상대적으로 높은 정밀도의 이미지 분류 모델을 만들 수 있다.다만, 임무로서는 비교적 간단하기 때문에 적어도 90퍼센트의 정밀도를 초과해야 한다.
    몇 가지 방법을 생각해 볼 수 있는 부분을 높여 보아라.
  • 정밀도를 높이기 위해:

  • Epoke 수 증가: 그래프를 보면 Epoke 수를 늘리면 계속 늘어날 것 같다.1분 정도면 끝나기 때문에 원가가 비교적 낮다.

  • 학습 데이터 증가: 데이터를 증가하면 정밀도를 높일 수 있습니다.다만, 원가가 매우 높다.

  • 데이터 품질 향상: 초기에 표시된 데이터는 표시 기준이 명확하지 않기 때문에 품질이 좋지 않은 라벨일 수 있습니다.모든 태그를 수정하여 정밀도를 높일 수 있습니다.하지만 이것도 고비용이다.

  • 학급의 편차를 감안하면 이번 학습 데이터에 포함된 '말도 안 되는 이미지' 는 '말도 안 되는 이미지' 의 약 2배에 달해 불균형이 생겼다.불균형을 고려해 정밀도 향상을 기대할 수 있다.

  • 데이터 확장(Data Augmentation): 데이터를 반전, 회전, 잡음 추가 등의 방식으로 추가하여 정밀도를 높일 수 있습니다.ImageDataGenerator를 사용했기 때문에 쉽게 시도할 수 있습니다.

  • B0보다 큰 모델 사용: EfficientNet은 B0에서 B7까지의 변화가 있고 숫자가 대규모일수록(하지만 처리 부하도 높음)더 큰 모델로 변경함으로써 정밀도를 높일 수 있다.

  • 정밀 조화: 이번에는 핵심 부분을 배우지 않고 특징량 추출기로 사용해서 머리만 배웠어요.골간을 포함한 내용을 학습함으로써 정밀도를 높일 수 있다.
  • 속도를 높이기 위해:

  • 이미지를 모두 메모리에 불러오기: 이번에 사용한 이미지는 약 2만 장으로 비교적 적고 이미지 사이즈도 비교적 작으며 4GB 수납.모든 그림을 메모리에 미리 불러와서 고속화할 수 있습니다.

  • 미리 축소 이미지: 입력 골간은 224×224로 사이즈가 상대적으로 작지만 매번 이 사이즈로 축소할 때마다 처리 효율이 떨어진다.데이터 확장의 호환성도 있지만 미리 처리할 수 있다면 고속화될 수 있다.

  • 골간과 머리를 분리하는 학습: 이것도 데이터 확장의 호환성이 있지만, 골간을 미리 사용하여 이미지를 특징량으로 변환하면 머리의 학습만으로 된다.세밀한 조정을 하려면 당연히 이 수단을 사용할 수 없다.
  • 학습 모델 정보


    학습한 모형이 있으면 공개를 요구합니다.16MB 정도 되니까 서류 넣을 곳 제안을 포함할 수 있다면 기쁠 것 같아요.

    이번에는 여기까지.


    마침내 공부할 지경에 이르렀다.앞으로 나는 라벨, 고정밀화, 고속화, 평가, 추론, 증류 등을 쓰고 싶다.오늘은 여기까지!
    이어'말도 안 되는 이미지 분류기 만들어 보기(9) 추론.

    좋은 웹페이지 즐겨찾기