거친 이미지 분류기 만들어 보기(8) 학습2
카탈로그
계속 공부하다
저번 데이터의 분할을 진행했다.이번에는 실제로 공부를 해야 한다.
결론
먼저 결론을 쓰면 정밀도(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가 필요합니다.배우다
그럼 드디어 공부를 해야겠네요.주요 초변수 등은 다음과 같다.
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) 추론.
Reference
이 문제에 관하여(거친 이미지 분류기 만들어 보기(8) 학습2), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://zenn.dev/kleamp1e/articles/202104-pornography-classifier-8텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)