使用mplfinance/matplotlib时可能会出现内存泄漏问题。如何解决?

4

我正在为卷积神经网络(CNN)制作大量图像(蜡烛图与成交量),约1.7百万张。然而,目前的脚本在每次迭代后内存使用量都会增加,每次增加2-5MB,直到无论我运行多少个实例,内存都已满(16GB,脚本最终使用11-12GB)。

我的目标是同时运行多个脚本实例。我尝试了并行处理,但效果不佳。因此,我只是使用了多个内核。我已经尝试了许多减少内存使用的方法,但似乎没有什么作用。

我正在使用Jupyter笔记本(Python 3.8.5)(anaconda)在VS code中,拥有64位Windows系统。16GB RAM和Intel i7第八代处理器。

第一个单元格调用软件包,加载数据并设置参数。

# 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 - School\Econometrics\2020 - 2021\Scriptie\Explainable AI\Scripts\Data\test_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")

第三个单元格循环遍历数据并调用第二个单元格中的函数。
#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()

3
您能否在创建第一个图之前尝试使用 matplotilb.use('agg')?我猜测可能有很多与 GUI 相关的对象挂起在内存中,等待事件循环运行以允许它们被拆除。 - tacaswell
1
@tacaswell,太棒了!谢谢,内存使用稳定在约330Mb左右。你刚刚救了我的论文;)快速问题,matplotlib.use('agg')实际上是做什么的?我查看了文档,但是文档非常有限。 - RKoppe
1个回答

5

从评论中推广:

问题是默认情况下Matplotlib尝试使用基于GUI的后端(为每个绘图制作一个GUI窗口)。当您关闭它们时,我们会拆除我们的部分并告诉GUI拆除其(基于c ++的)部分。然而,在这种情况下,拆卸发生在从未运行的GUI事件循环上,因此c ++ -side对象正在积累到“即将被删除”的状态,直到它耗尽内存。

通过将后端设置为'agg',我们根本不尝试制作任何GUI窗口,因此没有GUI对象需要拆除(最佳优化是不要做这件事; ))。我希望它在墙上时间上也稍微快一点(因为再次,不要做你不需要做的工作!)。

有关后端的更多详细信息,请参见https://matplotlib.org/tutorials/introductory/usage.html#backends,有关GUI集成的工作方式,请参见https://matplotlib.org/users/interactive.html以及其中的链接。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接