#python #python-3.x #matplotlib #anaconda #mplfinance
#python #python-3.x #matplotlib #анаконда #mplfinance
Вопрос:
Я пытаюсь сделать много (~ 1,7 млн) изображений (диаграммы подсвечников с объемом) для CNN. Тем не менее, скрипт, который у меня есть в настоящее время, продолжает увеличивать использование памяти после каждой итерации примерно на 2-5 МБ на итерацию, насколько я могу судить. Это увеличивается до тех пор, пока моя память не будет полностью заполнена, независимо от того, сколько экземпляров я запускаю скрипта. (16 ГБ, из которых скрипт в конечном итоге использует 11-12 ГБ).
Цель состоит в том, чтобы запустить несколько экземпляров скрипта одновременно. Я попробовал параллельную обработку, но получилось не очень хорошо. Поэтому я просто использую несколько ядер. Я перепробовал множество методов, чтобы уменьшить использование памяти, но, похоже, ничего не работает.
Я использую ноутбуки Jupyter (Python 3.8.5) (anaconda) в VS code, имею 64-разрядную систему Windows. 16 ГБ оперативной памяти и Intel i7 8-го поколения.
Первая ячейка вызывает пакеты, загружает данные и задает параметры.
# import required packages
import matplotlib.dates as mpdates
import matplotlib.pyplot as plt
import mplfinance as mpf
import matplotlib as mpl
from PIL import Image
import pandas as pd
import math as math
import numpy as np
import io as io
import gc as gc
import os as os
#set run instance number
run=1
#timeframe
tf = 20
#set_pixels
img_size=56
#colors
col_up = '#00FF00'
col_down = '#FF0000'
col_vol = "#0000FF"
#set directory
direct = "C:/Users/robin/1 - Scriptie/images/"
#loading the data
data1 = pd.read_csv(r'D:1 - SchoolEconometrics2020 - 2021ScriptieExplainable AIScriptsDatatest_data.csv',header=[0, 1] , index_col = 0 )
data1.index=pd.to_datetime(data1.index)
#subsetting the data
total_symbols = math.floor(len(data1.columns.unique(level=0))/6)
symbols1 = data1.columns.unique(level=0)[(run-1)*total_symbols:run*total_symbols]
#set the plot parameters
mc = mpf.make_marketcolors(up = col_up ,down = col_down, edge='inherit', volume= col_vol, wick='inherit')
s = mpf.make_mpf_style(marketcolors=mc)
Вторая ячейка определяет функцию, используемую для построения графиков:
# creating candlestick chart with volume
def plot_candle(i,j,data,symbols,s,mc,direct,img_size, tf):
#slicing data into 30 trading day windows
data_temp=data[symbols[j]][i-tf:i]
#creating and saving the candlestick charts
buf = io.BytesIO()
save = dict(fname= buf, rc = (["boxplot.whiskerprops.linewidth",10]),
pad_inches=0,bbox_inches='tight')
mpf.plot(data_temp,savefig=save, type='candle',style=s, volume=True, axisoff=True,figratio=(1,1),closefig=True)
buf.seek(0)
im = Image.open(buf).resize((img_size,img_size))
im.save(direct "/" str(symbols[j]) "/" str(i-tf 1) ".png", "PNG")
buf.close()
plt.close("all")
Третья ячейка перебирает данные и вызывает функции во 2-й ячейке.
#check if images folder excists, if not, create it.
if not os.path.exists(direct):
os.mkdir("C:/Users/robin/1 - Scriptie/images")
for j in range(0,len(symbols1)):
#Check if symbol folder excists, if not, create it
if not os.path.exists(direct "/" symbols1[j]):
os.mkdir(direct "/" symbols1[j])
for i in range(tf,len(data1)) :
#check if the file has already been created
if not os.path.exists(direct "/" str(symbols1[j]) "/" str(i-tf 1) ".png"):
#call the functions and create the
plot_candle(i , j , data1 , symbols1 ,s ,mc ,direct , img_size, tf)
gc.collect()
Комментарии:
1. Можете ли вы попробовать сделать
matplotilb.use('agg')
, прежде чем создавать первую фигуру? Я предполагаю, что в памяти висит целая куча объектов, связанных с графическим интерфейсом, ожидающих запуска цикла событий, чтобы позволить им самим быть снесенными.2. @tacaswell , работает как шарм! Спасибо, использование памяти стабильно составляет около ~ 330 МБ. Вы только что сохранили мою диссертацию ;). Быстрый вопрос, что
matplotlib.use('agg')
на самом деле делает? Однако я просмотрел документацию, она довольно ограничена.
Ответ №1:
Продвижение из комментария:
Проблема заключается в том, что по умолчанию Matplotlib пытается использовать серверную часть на основе графического интерфейса (он создает окно графического интерфейса для каждого графика). Когда вы закрываете их, мы разрушаем нашу сторону вещей и говорим GUI, чтобы разрушить его (основанную на c ) сторону вещей. Однако это разрушение происходит в цикле событий GUI, который в этом случае никогда не запускается, поэтому объекты на стороне c накапливаются в состоянии «вот-вот будут удалены», пока не закончится память.
Установив для серверной 'agg'
части значение, мы вообще не пытаемся создавать какие-либо окна с графическим интерфейсом, чтобы не было объектов GUI для удаления (лучшая оптимизация — не делать этого ;)). Я бы ожидал, что это также будет немного быстрее по времени (потому что, опять же, не выполняйте работу, которую вам не нужно делать!).
Видишь https://matplotlib.org/tutorials/introductory/usage.html#backends для получения более подробной информации о бэкэндах см. https://matplotlib.org/users/interactive.html и ссылки там на то, как работает интеграция с графическим интерфейсом.