Как избежать ошибки памяти при вызове метода Pandas pd.read_csv в сочетании с использованием GridSearchCV для модели DecisionTreeRegressor?

Вопрос или проблема

Я реализовал модель DecisionTreeRegressor в среде Anaconda с набором данных, полученным из CSV файла с 20 миллионами строк и 12 измерениями. Я мог получать части из набора данных с размером куска, установленным на 500 000 строк, и обрабатывать вычисление R-квадрат для обучающего/тестового наборов данных в каждой итерации по 500 000 строк до итерации №20.

sklearn.__version__: 0.19.0 
pandas.__version__: 0.20.3 
numpy.__version__: 1.13.1

Экземпляр GridSearchCV() использует сетку параметров с параметром max_depth, установленным на значения [4, 6].

Затем я вижу ошибки памяти в модуле numpy с интерпретатором Python Anaconda, выбрасывающим исключение.

Это исключение после итерации №20:

Оценка для модели, обученной на тестовом наборе данных:  -0.000287864727209
Лучшие параметры:  {'max_depth': 4} 
Лучшая точность кросс-валидации:  -0.00037759422675 

Traceback (последний вызов последним):

  File "<ipython-input-1-a28a1b71d60d>", line 1, in <module>
    runfile('C:/Kal/Stat-Work/Stat-Code/SciKit/Final/DecisionTreeRegression-MaximumDepthFour.py', wdir="C:/Kal/Stat-Work/Stat-Code/SciKit/Final")

  File "C:\Users\bkalahas\AppData\Local\Continuum\anaconda3\lib\site-packages\spyder\utils\site\sitecustomize.py", line 710, in runfile
    execfile(filename, namespace)

  File "C:\Users\bkalahas\AppData\Local\Continuum\anaconda3\lib\site-packages\spyder\utils\site\sitecustomize.py", line 101, in execfile
    exec(compile(f.read(), filename, 'exec'), namespace)

  File "C:/Kal/Stat-Work/Stat-Code/SciKit/Final/DecisionTreeRegression-MaximumDepthFour.py", line 21, in <module>
    for piece in chunker:

  File "C:\Users\bkalahas\AppData\Local\Continuum\anaconda3\lib\site-packages\pandas\io\parsers.py", line 978, in __next__
    return self.get_chunk()

  File "C:\Users\bkalahas\AppData\Local\Continuum\anaconda3\lib\site-packages\pandas\io\parsers.py", line 1042, in get_chunk
    return self.read(nrows=size)

  File "C:\Users\bkalahas\AppData\Local\Continuum\anaconda3\lib\site-packages\pandas\io\parsers.py", line 1023, in read
    df = DataFrame(col_dict, columns=columns, index=index)

  File "C:\Users\bkalahas\AppData\Local\Continuum\anaconda3\lib\site-packages\pandas\core\frame.py", line 275, in __init__
    mgr = self._init_dict(data, index, columns, dtype=dtype)

  File "C:\Users\bkalahas\AppData\Local\Continuum\anaconda3\lib\site-packages\pandas\core\frame.py", line 411, in _init_dict
    return _arrays_to_mgr(arrays, data_names, index, columns, dtype=dtype)

  File "C:\Users\bkalahas\AppData\Local\Continuum\anaconda3\lib\site-packages\pandas\core\frame.py", line 5506, in _arrays_to_mgr
    return create_block_manager_from_arrays(arrays, arr_names, axes)

  File "C:\Users\bkalahas\AppData\Local\Continuum\anaconda3\lib\site-packages\pandas\core\internals.py", line 4309, in create_block_manager_from_arrays
    blocks = form_blocks(arrays, names, axes)

  File "C:\Users\bkalahas\AppData\Local\Continuum\anaconda3\lib\site-packages\pandas\core\internals.py", line 4381, in form_blocks
    int_blocks = _multi_blockify(int_items)

  File "C:\Users\bkalahас\AppData\Local\Continuum\anaconda3\lib\site-packages\pandas\core\internals.py", line 4450, in _multi_blockify
    values, placement = _stack_arrays(list(tup_block), dtype)

  File "C:\Users\bkalahас\AppData\Local\Continuum\anaconda3\lib\site-packages\pandas\core\internals.py", line 4493, in _stack_arrays
    stacked = np.empty(shape, dtype=dtype)

MemoryError

Это код:

# Чтение набора данных в DataFrame из CSV файла тестовой регрессии. 
chunker = pd.read_csv('C:/Kal/Stat-Work/Stat-Code/SciKit/Test_Data_Set_Regression.csv',
             names=['ROW', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'RT'],
             chunksize=500000, low_memory=False)

for piece in chunker:
    # Создание обучающих и тестовых наборов данных. 
    X_train, X_test, y_train, y_test = train_test_split(
        piece[['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J']], piece['RT'], random_state=0)

    param_grid = {
                 'max_depth': [4, 6]
                 }

    # Создание экземпляра класса GridSearchCV с моделью DecisionTreeRegressor, сеткой параметров
    # для поиска param_grid и стратегией кросс-валидации, которую мы хотим использовать, 
    # скажем, 5-кратная (стратифицированная) кросс-валидация.
    grid_search = GridSearchCV(DecisionTreeRegressor(), param_grid, cv=5)

    # Вызов метода fit для выполнения кросс-валидации для каждой комбинации
    # параметров, которые мы указали в param_grid
    grid_search.fit(X_train, y_train)

    # Печать best_score, best_parameters и test_score.
    print("Оценка для модели, обученной на всем обучающем наборе данных: ", grid_search.score(X_train, y_train))

    # Оценка общей производительности обобщения, вызвав метод score на тестовом наборе данных.
    print("Оценка для модели, обученной на тестовом наборе данных: ", grid_search.score(X_test, y_test))
    print("Лучшие параметры: ", grid_search.best_params_)
    print("Лучшая точность кросс-валидации: ", grid_search.best_score_)

Вопросы:

  1. Пожалуйста, укажите способы преодоления исключения ошибки памяти Python.
  2. Какой лучший способ реализовать модель DecisionTreeRegressor на кластере из 4 машин с 16 ГБ ОЗУ и 2.5 ГГц ЦП (Linux или Windows)? Я вижу ошибки памяти даже с моделью DecisionTreeRegressor. Модель SVM не вычисляется полностью более чем на 20 000 строк в куске, и интерпретатор Python видит зависшие ЦП. Но известно, что SVM вычислительно сложна. Есть ли способ обойти такие ошибки памяти для моделей DecisionTree и Ensemble, когда они комбинируются с Pandas? Pandas является нашим аналитическим движком для работы с памятью.

Набор данных особенно большой (фактическое общее количество 100 миллионов строк в исходной базе данных, которая создается почти каждый день). Использование кросс-валидации на всем наборе данных в 100 миллионов строк является вычислительно сложной задачей.

Я придумал эту модель, похожую на Бэггинг, где набор данных разбивается на выборки по 500 000 строк, и для каждой выборки вычисляется среднеквадратичная ошибка. Цель состоит в том, чтобы вычислить усреднённую среднеквадратичную ошибку по всем выборкам.

Этот вопрос важен, поскольку он касается масштабов, что является повседневной вычислительной проблемой в алгоритмах машинного обучения. Я также был бы признателен за критические ответы по различным аспектам моего кода выше, а не за негативные оценки без причины. Спасибо.

Чтобы ответить на ваши вопросы:

  1. Первый способ выйти из ситуации: то, что вы уже сделали:

    Подумайте о структуре данных. Можете ли вы разделить, не теряя информации? Есть ли логические “кластеры” или точки разбиения в ваших данных? Если это все еще вызывает проблемы, вам следует подумать о дальнейшем обследовании. В вашем примере почему 20-ятая итерация дает сбой? Кажется, что достаточно памяти для одной итерации, что означает, что, в принципе, вы должны быть в состоянии выполнять итерации по всем своим кускам.

    Чтобы понять, что происходит, вы можете отслеживать использование памяти профилировать. Если вы знаете, что вызывает ошибку памяти, вы можете явно сохранять снимки на диск или освобождать память. Хотя я сам сталкивался с проблемами владения между python и базовыми классами C/C++.

    Попробовать можно было бы и такой подход: итерация по N кускам, запись результатов на диск, повторение до обработки всех строк. Затем объедините результаты.

  2. Вы имеете в виду кластеры с 4-16 ГБ на узел или вашу локальную машину с 4 потоками?

    Говоря в общем, как упоминал seanv507, найдите (масштабируемое) решение, которое работает для небольшой выборки ваших данных, а затем масштабируйте его для больших наборов. Убедитесь, что ваше распределение памяти не превышает системные лимиты.

Ответ или решение

Как избежать ошибок памяти при использовании метода pd.read_csv в сочетании с GridSearchCV для модели DecisionTreeRegressor?

Работа с большими наборами данных в Pandas и числовыми алгоритмами машинного обучения, такими как DecisionTreeRegressor, может привести к проблемам с памятью, особенно при работе с файлами размером в десятки миллионов строк. Рассмотрим подходы для решения данной проблемы и оптимизации обработки данных на примере вашей ситуации.

1. Способы устранения ошибок памяти

1.1. Разделение данных и построчная обработка

Вы уже применили chunksize, что позволяет обрабатывать данные по частям. Однако стоит дополнительно оптимизировать процесс, чтобы минимизировать потребление памяти:

  • Сохраняйте промежуточные результаты: Записывайте результаты вычислений в файл после обработки каждой порции данных. Это поможет избежать накопления больших объектов в памяти.

  • Освобождение памяти: После обработки каждой порции данных вызывать del для переменных, которые больше не нужны, и использовать gc.collect() для явного вызова сборщика мусора.

import gc

for piece in chunker:
    # Обработка данных...
    del piece  # освободите память
    gc.collect()  # явный вызов сборщика мусора

1.2. Оптимизация типов данных

Проверьте типы данных в вашем DataFrame. Pandas может использовать более эффективные типы данных, такие как category для строковых переменных и типы с меньшим объемом памяти, такие как float32 вместо float64. Это значительно уменьшит потребление памяти.

piece['A'] = piece['A'].astype('float32')

1.3. Использование генераторов для обработки данных

Создайте генератор, который будет обрабатывать данные порциями, что снизит память, используемую для хранения всех данных сразу.

def read_in_chunks(file, size=500000):
    for chunk in pd.read_csv(file, chunksize=size):
        yield chunk

1.4. Отказ от излишней загрузки данных

Если есть возможность, избегайте загрузки ненужных столбцов при чтении данных. Используйте параметр usecols в pd.read_csv.

chunker = pd.read_csv('your_file.csv', usecols=['A', 'B', 'C', 'RT'], chunksize=500000)

2. Оптимизация работы с кластером

2.1. Распараллеливание вычислений

Если у вас есть кластер из четырех машин с 16 ГБ ОЗУ каждая, рассмотрите возможность распараллеливания обработки данных. Используйте библиотеку Dask, которая поддерживает большие наборы данных и распределенные вычисления.

  • Использование Dask: Dask DataFrame можно использовать вместо Pandas для работы с данными, которые не помещаются в память, и автоматически справляется с распараллеливанием задач.
import dask.dataframe as dd

df = dd.read_csv('your_file.csv', assume_missing=True)

2.2. Настройка кластера

Убедитесь, что ваш кластер настроен для оптимального распределения ресурсов. Настройте параметры, такие как n_jobs в GridSearchCV, чтобы использовать несколько узлов кластера.

grid_search = GridSearchCV(DecisionTreeRegressor(), param_grid, cv=5, n_jobs=-1)

2.3. Выбор алгоритмов

Для больших объемов данных следует рассмотреть использование более легких алгоритмов, таких как RandomForestRegressor или XGBoost, которые оптимизированы для работы с большими наборами данных и могут обрабатывать их быстрее и эффективнее.

Заключение

Для успешной работы с большими наборами данных в машинном обучении необходимо применение практик оптимизации памяти, таких как правильное управление памятью, использование более эффективных типов данных и распараллеливание вычислений. Исследуйте возможность использования библиотек, оптимизированных для больших данных, а также техники, позволяющие работать с порциями данных, чтобы избежать ошибок памяти и улучшить эффективность ваших расчетов.

Оцените материал
Добавить комментарий

Капча загружается...