Python은 코드를 실행할 때 전체 RAM을 사용합니다.

Python은 코드를 실행할 때 전체 RAM을 사용합니다.

문제는 Python이 아니라 Linux의 전반적인 RAM 관리에 있는 것 같습니다. 코드는 다음과 같습니다.

!pip install numpy opencv-python pandas matplotlib tensorflow scikit-learn

import numpy as np
import cv2 as cv
import pandas as pd
import matplotlib.pyplot as plt
import os
import gc

gc.enable()
train_dir = 'fruits-360/Training'
classes = os.listdir(train_dir)
classes = classes[:30]

all_arrays=[]
img_size=100
for i in classes:
    path=os.path.join(train_dir, i)
    class_num=classes.index(i)
    for img in os.listdir(path):
    img_array=cv.imread(os.path.join(path, img))
    mig_array=cv.cvtColor(img_array, cv.COLOR_BGR2RGB)
    all_arrays.append([img_array, class_num])

test_dir = 'fruits-360/Test'
classes2 = os.listdir(test_dir)
classes2 = classes2[:30]

all_arrays2=[]
img_size=100
for i in classes2:
    path=os.path.join(test_dir, i)
    class_num2=classes.index(i)
    for img in os.listdir(path):
    img_array=cv.imread(os.path.join(path, img))
    mig_array=cv.cvtColor(img_array, cv.COLOR_BGR2RGB)
    all_arrays.append([img_array, class_num2])

import random
random.shuffle(all_arrays)

X_train=[]
Y_train=[]
for features, label in all_arrays:
    X_train.append(features)
    Y_train.append(label)
X_train=np.array(X_train)

random.shuffle(all_arrays2)

X_test=[]
Y_test=[]
for features, label in all_arrays:
    X_test.append(features)
    Y_test.append(label)
X_test=np.array(X_test)

X_train=X_train.reshape(-1, img_size, img_size, 3)
X_train=X_train/255
X_test=X_test.reshape(-1, img_size, img_size, 3)
X_test=X_test/255

from keras.utils import to_categorical
Y_train=to_categorical(Y_train, num_classes=30)
Y_test=to_categorical(Y_test, num_classes=30)

from sklearn.metrics import confusion_matrix, ConfusionMatrixDisplay
from sklearn.model_selection import train_test_split
from keras.models import Sequential
from keras.layers import Dense, Conv2D, Flatten, MaxPool2D, Dropout
from keras.callbacks import ReduceLROnPlateau
from keras.optimizers import Adam

x_train, x_val, y_train, y_val = train_test_split(X_train, Y_train, test_size=0.3, random_state=42)

model=Sequential()
model.add(Conv2D(filters=16, kernel_size=(5,5), padding='Same', activation='relu', input_shape=(100, 100, 3)))
model.add(MaxPool2D(pool_size=(2,2)))
model.add(Conv2D(filters=32, kernel_size=(5,5), padding='Same', activation='relu'))
model.add(MaxPool2D(pool_size=(2,2)))
model.add(Conv2D(filters=64, kernel_size=(5,5), padding='Same', activation='relu'))
model.add(MaxPool2D(pool_size=(2,2)))

model.add(Flatten())
model.add(Dense(128, activation='relu'))
model.add(Dropout(0.6))
model.add(Dense(30, activation='softmax'))

model.compile(optimizer=Adam(learning_rate=0.001), 
          loss='categorical_crossentropy', metrics=['accuracy'])
epochs=10
batch_size = 32

history=model.fit(x_train, y_train, batch_size=batch_size, epochs=epochs)

y_pred = model.predict(x_train)
y_pred_classes = np.argmax(y_pred, axis=1)
y_true = np.argmax(y_train, axis=1)
conf_mat = confusion_matrix(y_true, y_pred_classes)

disp = ConfusionMatrixDisplay(conf_mat, display_labels=classes)
fig, ax = plt.subplots(figsize=(15,15))
disp.plot(ax=ax)
plt.xticks(rotation=90)
plt.show()

model.summary()

만약을 대비해 문제는 코드 자체에 있는 것이 아닙니다. Windows의 jupyter 노트북에서 이 코드를 실행하면 전체 RAM 사용량은 약 9/16GB이고 코드는 정상적으로 실행되지만 Linux에서 코드를 실행하면 사용 가능한 모든 RAM과 스왑 파티션이 소비되고 jupyter가 충돌합니다. 다음 명령을 사용하여 jupyter 노트북을 실행하는 경우:

systemd-run --scope -p MemoryMax=8192M jupyter-notebook

Jupyter는 8GB에 도달하고 전체 스왑 공간을 사용한 후에도 계속 충돌합니다.

어떻게든 고칠 수 있는 방법이 있나요?

답변1

처음에 가비지 수집을 활성화했지만 gc더 이상 범위에 없는 항목에 대해서만 메모리를 해제하고 배치한 방식을 보면 모든 것이 범위 내에 있는 것 같습니다. 문제를 식별하는 데 도움이 되는 몇 가지 방법은 다음과 같습니다.

  • 코드를 보다 개별적인 기능으로 결합합니다. 즉, all_array 빌더 로직과 모델 빌더 로직을 별도의 함수로 분리한 다음 main.predecessor에서 시작합니다.
    def parse_classes(dir_path, ref_classes):
      out_arrays = []
      for i in ref_classes:
        ...
      return out_arrays
    
    train_arrays = parse_classes(train_dir, classes)
    test_arrays = parse_classes(test_dir, classes)
    
    def shuffle(arr):
      random.shuffle(arr)
      for features, labels, in arr:
        ...
      return X_train, Y_train
    # etc...
    
  • 그리고 사용tracemalloc각 지역에서 사용되는 메모리 양을 확인하여 현재 상황을 더 잘 이해할 수 있도록 도와줍니다.이것프로세스를 시작하는 데 도움이 될 수 있습니다.

관련 정보