np.load와 cv2.resize의 RAM 사용량에 대한 질문

2022.12.22 22:52 1,594 조회

이미지 데이터 전처리를 하는 과정에서 RAM 사용량이 용량을 뛰어넘어 런타임이 다운되는 상황을 겪고 있습니다.

(train_set = 약 8,000개의 이미지 데이터, test_set = 약 2,000개의 이미지 데이터)

np.load를 통해 다른 노트북에서 np.save를 해두었던 넘파이로 된 데이터를 가져오는 과정에서 RAM 사용량이 늘어나는 것을 보았고,

center_cropping을 하는 과정에서 cv2.resize를 사용하는데 RAM 사용량이 늘어나 런타임이 다운되고 있습니다.

RAM 모니터링을 한 결과 cv2.resize에서 런타임이 주로 다운되는 것 같습니다.


del 명령을 통해 사용했던 객체들을 삭제해서 RAM을 줄이라는 조언도 봤지만 코드에서 사용할 수 있는 부분이 보이지 않아 어려움을 겪고 있습니다.


결론적으로 제가 하고 싶은 방향은

  1. np.load를 통해 넘파이로 된 데이터를 가져오기
  2. center cropping을 통한 데이터 전처리
train_set = np.load('/content/drive/MyDrive/cat_n_dog/data_numpy/train_set.npy', allow_pickle=True)
test_set = np.load('/content/drive/MyDrive/cat_n_dog/data_numpy/test_set.npy', allow_pickle=True)


train_target = np.load('/content/drive/MyDrive/cat_n_dog/data_numpy/train_target.npy', allow_pickle=True)
test_target = np.load('/content/drive/MyDrive/cat_n_dog/data_numpy/test_target.npy', allow_pickle=True)


# image_preprocessing: center cropping
def crop_center(img):
    y, x, z = img.shape
    crop_size = min(y, x)


    start_x = x // 2 - (crop_size // 2)
    start_y = y // 2 - (crop_size // 2)
    img = img[start_y:start_y + crop_size, start_x:start_x + crop_size]
    return cv2.resize(img, (256, 256))


# 이 셀에서 런타임이 다운 됨.
train_scaled = []


for i, img in enumerate(train_set):
    img_crop = crop_center(img)
    img_scaled = minmax_scaler(img_crop)
    train_scaled.append(img_scaled)


train_scaled = np.array(train_scaled)

이 2가지를 하고 싶은데 효율적인 방법이 없고, 다른 좋은 방법이 있다면 그 부분도 조언을 받고 싶습니다.

어떤 방식으로 RAM을 줄일 수 있는지 혹은 다른 방법이 있는지 조언 부탁 드립니다.

로그인이 필요합니다
0 / 1000
Doby_
2022.12.22 23:42

이것저것 시도해보다가 cv2.resize가 RAM을 많이 잡아먹지 않는다는 것을 알았습니다. cv2.resize가 진작에 RAM을 많이 잡아먹었다면 진작에 여러 커뮤니티에서 이에 대해 얘기가 나왔을텐데 라는 아차 싶은 생각을 했습니다. 문제는 다름 아닌 minmax_scaler였습니다. Normalization을 하면서 unit8에서 float64로 타입이 변하면서 8배나 넘는 메모리를 사용했기 때문입니다. 이 점을 문제로 삼고 어떻게 해결할 지가 관건인 거 같습니다.

문제에 관심을 가져주셔서 감사합니다.

파이썬초보만
2022.12.23 13:22

좋은 해결이네요
float32로 낮추는건 어떨까요

Doby_
2022.12.28 09:42

Normalization을 하면서 직접적으로 type을 float32를 쓰는 방법 아시나요?

Redix6
2022.12.28 16:09

몇가지 방법이 있습니다.
첫째는 Normalization 전처리를 안하는겁니다. min max scaler정도의 cost는 저장된 np파일을 불러오는 io보다 낮습니다. 어차피 np파일 불러오는정도의 io cost를 감당할 수 있는 수준이라면 불러온 이후에 전처리를 해도 충분해 보입니다.
둘째는 하나의 이미지를 처리한 이후 list에 저장하지 않고 바로 하나의 파일로 저장하는 것 입니다. 메모리에 전부 load시켜서 발생하는 문제니, 하나씩 로드하면서 저장한다면 전혀 문제가 없습니다. 이미지를 이용하는 방식은 대부분 1:1로 저장하는 방식을 사용합니다. 용량이 크기 때문에 한번에 메모리에 로드하지않고 필요한 부분만 로드하면서 처리하기 때문입니다.
이 외에도 많은 방식이 있습니다만, 저 둘 중 하나만으로도 충분해 보입니다.

Doby_
2022.12.28 23:43

좋은 의견 감사합니다. 저도 파일을 저장해서 가져와볼까 라는 생각을 해봤지만 시도하지 않았던 이유는 keras.preprocessing.image의 load_img를 통해 가져오는데 이는 시간이 오래 걸려서 메모리를 잡아먹더라도 numpy로 저장하고 로드하는 방법을 택했었습니다. 혹시 파일에서 빠르게 가져오는 방법이 있을까요?

Redix6
2022.12.29 21:42

keras.utils.image_dataset_from_directory 를 이용하시거나 tf.data를 이용하는 방법이 있습니다.
아래 내용을 참고해보세요.
https://www.tensorflow.org/guide/data_performance?hl=ko

Doby_
2022.12.29 23:08

많은 도움이 될 거 같아요! 감사합니다 :)