অনেক বেশি প্রকাশ্য চিত্র সম্পর্কে সতর্কতা


166

এমন স্ক্রিপ্টে যেখানে আমি অনেকগুলি চিত্র তৈরি করি fix, ax = plt.subplots(...) , আমি সতর্কতা পেয়েছি রানটাইম ওয়ার্নিং : 20 টিরও বেশি পরিসংখ্যান খোলা হয়েছে। পাইপ্লট ইন্টারফেসের মাধ্যমে তৈরি চিত্রগুলি matplotlib.pyplot.figureস্পষ্টভাবে বন্ধ না হওয়া অবধি ধরে রাখা হয় এবং খুব বেশি স্মৃতি গ্রহণ করতে পারে।

তবে, আমি কেন এই সতর্কতাটি পাই তা বুঝতে পারি না , কারণ চিত্রটি সংরক্ষণ করার পরে fig.savefig(...), আমি এটি দিয়ে মুছে ফেলছি fig.clear(); del fig। আমার কোডের কোনও বিন্দুতে, আমার একসাথে একাধিক চিত্র খোলা আছে। তবুও, আমি অনেকগুলি মুক্ত পরিসংখ্যান সম্পর্কে সতর্কতা পেয়েছি। এর অর্থ কী / আমি কীভাবে সতর্কতা এড়াতে পারি?


9
আপনি যদি এগুলি অনেক কিছু করে চলেছেন এবং ইন্টারেক্টিভভাবে কিছু প্রদর্শন করছেন না, আপনি pltপুরোপুরি বাইপাস করা থেকে ভাল । উদাহরণস্বরূপ স্ট্যাকওভারফ্লো.com/a/16337909/325565 (আমার নিজের উত্তরগুলির একটি প্লাগ না করা, তবে এটিই আমি দ্রুত খুঁজে পেতে পারি ...)
জো কিংটন

1
@ জোকিটিংটন আপনাকে ধন্যবাদ এটি একটি আরও ভাল সমাধান
হাইহেল

জো কিংটনের উত্তরটি মূল উত্তর তালিকায় থাকা উচিত। এটি কাজ করে এবং plt.close () ডন কির্বির উল্লিখিত প্রোগ্রামটি ধীর করে দেওয়ার সমস্যার সাথেও সমস্যা সমাধান করে।
নাটালিএল

উত্তর:


198

ব্যবহার করুন .clfঅথবা .claআপনার চিত্র বস্তুর উপর একটি তৈরি করার পরিবর্তে নতুন চিত্রে। @ ডেভিডজুইকার থেকে

ধরে নিচ্ছি আপনি pyplotযেমন আমদানি করেছেন

import matplotlib.pyplot as plt

plt.cla()একটি অক্ষ সাফ করে , বর্তমান চিত্রটিতে বর্তমানে সক্রিয় অক্ষ is এটি অন্য অক্ষ অক্ষত রেখে দেয়।

plt.clf()সমস্ত বর্তমান চিত্রটি তার সমস্ত অক্ষ দিয়ে সাফ করে , তবে উইন্ডোটি খোলা ছেড়ে দেয়, যাতে এটি অন্য প্লটের জন্য পুনরায় ব্যবহার করা যেতে পারে।

plt.close()অন্যথায় নির্দিষ্ট না করা থাকলে একটি উইন্ডো বন্ধ করে দেয় যা বর্তমান উইন্ডো হবে। plt.close('all')সমস্ত উন্মুক্ত পরিসংখ্যান বন্ধ করবে।

del figকাজ না করার কারণটি হ'ল pyplotরাষ্ট্র-মেশিন চারপাশের চিত্রটির একটি রেফারেন্স রাখে (এটি অবশ্যই যদি 'বর্তমান চিত্র' কী তা জেনে থাকে)। এর অর্থ হ'ল এমনকি যদি আপনি চিত্রটি আপনার রেফ মুছে ফেলেন তবে কমপক্ষে একটি লাইভ রেফ রয়েছে, সুতরাং এটি কখনও আবর্জনা সংগ্রহ করা হবে না।

যেহেতু আমি এই উত্তরের জন্য এখানে সম্মিলিত জ্ঞানের পক্ষে ভোট দিচ্ছি, @ জোকিিংটন মন্তব্যগুলিতে উল্লেখ করেছেন plt.close(fig)যা পাইব্ল্যাব স্টেট মেশিন ( plt._pylab_helpers.Gcf ) থেকে একটি নির্দিষ্ট চিত্র উদাহরণ সরিয়ে ফেলবে এবং এটিকে আবর্জনা সংগ্রহের অনুমতি দেবে।


1
Mhh। ক্লাসের clfজন্য আছে figure, কিন্তু নেই closedel figপ্রকৃতপক্ষে চিত্রটি কেন বন্ধ করে মুছবেন না?
andreas-h

2
@ andreas-h আমার অনুমান: উইন্ডো ম্যানেজারের মতো জটিল কোনও কিছুর জন্য নিজস্ব হ্যান্ডলারের সাথে, কিছু সুযোগের বাইরে রাখার চেয়ে আরও পরিষ্কার-পরিচ্ছন্নতার প্রয়োজন হতে পারে। আপনার অধিকার যা closeফিগার অবজেক্টে কাজ করবে না plt.close(), তার পরিবর্তে এটিকে কল করুন fig.clf()
হুকড

5
@ অ্যান্ড্রেস-এইচ - মূলত, del figকাজ না করার কারণটি হ'ল এটিকে একটি __del__পদ্ধতি দেওয়া (যা মূলত কল করবে plt.close(fig)) এই নির্দিষ্ট ক্ষেত্রে বিজ্ঞপ্তিযুক্ত রেফারেন্সকে বাধা দেবে এবং figকোনও __del__পদ্ধতি থাকার কারণে অন্যান্য জিনিস আবর্জনা সংগ্রহ না করার কারণ হবে will । (বা এটি যাইহোক, আমার অস্পষ্ট স্মৃতি।) যে কোনও হারে এটি অবশ্যই কিছুটা বিরক্তিকর, তবে plt.close(fig)পরিবর্তে আপনার কল করা উচিত del fig। পার্শ্ব নোটে, ম্যাটপ্ল্লোলিব সত্যিই এর জন্য একটি প্রসঙ্গ পরিচালক ব্যবহার করতে পারে ...
জো কিংটন

6
@ হুকড - এটি আরও কিছুটা স্পষ্ট করার জন্য, আপনি আপনার প্রশ্নটি সম্পাদনা করে উল্লেখ plt.close(fig)করতে পারেন যে পাইলব স্টেট মেশিন ( plt._pylab_helpers.Gcf) থেকে একটি নির্দিষ্ট চিত্র উদাহরণ সরিয়ে ফেলবে এবং এটিকে আবর্জনা সংগ্রহের অনুমতি দেবে।
জো কিংটন

2
@ জোকিংটন pltকিছুটা গোলমাল করছে এবং এর একগুচ্ছ পুনরায় কীভাবে করা যায় সে সম্পর্কে চিন্তাভাবনা রয়েছে। প্রসঙ্গ পরিচালকটি কৌতূহলজনক .... দেখুন github.com/matplotlib/matplotlib/pull/2736 , github.com/matplotlib/matplotlib/pull/2624
ট্যাকসওয়েল

32

হুকডের উত্তরে প্রসারিত করার জন্য এখানে আরও কিছু বিশদ দেওয়া আছে । আমি যখন প্রথম উত্তরটি পড়েছিলাম, আমি clf() একটি নতুন চিত্র তৈরির পরিবর্তে কল করার নির্দেশটি মিস করেছি । clf()আপনি যদি যান এবং অন্য চিত্র তৈরি করেন তবে এটি নিজেই সহায়তা করে না।

এখানে একটি তুচ্ছ উদাহরণ যা সতর্কবার্তার কারণ দেয়:

from matplotlib import pyplot as plt, patches
import os


def main():
    path = 'figures'
    for i in range(21):
        _fig, ax = plt.subplots()
        x = range(3*i)
        y = [n*n for n in x]
        ax.add_patch(patches.Rectangle(xy=(i, 1), width=i, height=10))
        plt.step(x, y, linewidth=2, where='mid')
        figname = 'fig_{}.png'.format(i)
        dest = os.path.join(path, figname)
        plt.savefig(dest)  # write image to file
        plt.clf()
    print('Done.')

main()

সতর্কতা এড়াতে, আমাকে subplots()লুপের বাইরে কল টানতে হবে । আয়তক্ষেত্রগুলি দেখতে চালিয়ে যেতে, আমাকে স্যুইচ clf()করতে হবে cla()। এটি অক্ষটি নিজেই সরিয়ে না দিয়ে অক্ষ সাফ করে।

from matplotlib import pyplot as plt, patches
import os


def main():
    path = 'figures'
    _fig, ax = plt.subplots()
    for i in range(21):
        x = range(3*i)
        y = [n*n for n in x]
        ax.add_patch(patches.Rectangle(xy=(i, 1), width=i, height=10))
        plt.step(x, y, linewidth=2, where='mid')
        figname = 'fig_{}.png'.format(i)
        dest = os.path.join(path, figname)
        plt.savefig(dest)  # write image to file
        plt.cla()
    print('Done.')

main()

আপনি যদি ব্যাচগুলিতে প্লট তৈরি করে থাকেন তবে আপনাকে cla()এবং উভয়ই ব্যবহার করতে হতে পারে close()। আমি এমন একটি সমস্যায় পড়েছিলাম যেখানে একটি ব্যাচে অভিযোগ না করেই ২০ টিরও বেশি প্লট থাকতে পারে তবে এটি 20 ব্যাচের পরে অভিযোগ করবে। আমি cla()প্রতিটি প্লট এবং close()প্রতিটি ব্যাচের পরে ব্যবহার করে এটি স্থির করেছি ।

from matplotlib import pyplot as plt, patches
import os


def main():
    for i in range(21):
        print('Batch {}'.format(i))
        make_plots('figures')
    print('Done.')


def make_plots(path):
    fig, ax = plt.subplots()
    for i in range(21):
        x = range(3 * i)
        y = [n * n for n in x]
        ax.add_patch(patches.Rectangle(xy=(i, 1), width=i, height=10))
        plt.step(x, y, linewidth=2, where='mid')
        figname = 'fig_{}.png'.format(i)
        dest = os.path.join(path, figname)
        plt.savefig(dest)  # write image to file
        plt.cla()
    plt.close(fig)


main()

আমি ব্যাচের মধ্যে ফিগারটি পুনরায় ব্যবহার করার মতো কিনা তা দেখতে পারফরম্যান্সটি পরিমাপ করেছি এবং এই ছোট্ট নমুনা প্রোগ্রামটি 41s থেকে 49s (20% ধীর) হয়ে গেছে যখন আমি কেবল close()প্রতিটি প্লটের ডাক দিয়েছি ।


এটি একটি দুর্দান্ত উত্তর। গৃহীত উত্তরটি প্রকৃতপক্ষে আসল সমস্যাটির সমাধান করে না যা মেমরির খরচ।
কাইল

24

আপনি যদি জেনেশুনে অনেকগুলি প্লট স্মৃতিতে রাখার তাগিদ করেন তবে এ সম্পর্কে সতর্ক করতে চান না, আপনি পরিসংখ্যান তৈরির আগে আপনার বিকল্পগুলি আপডেট করতে পারেন।

import matplotlib.pyplot as plt
plt.rcParams.update({'figure.max_open_warning': 0})

এটি মেমরির যেভাবে পরিচালিত হয় সে সম্পর্কে কোনও পরিবর্তন না করে সতর্কতাটি নির্গত হতে আটকাবে।


একটি বৃহত্তর পরিবেশে, প্লটটি দেখানো ঘরটি যতক্ষণ না মেমরির বরাদ্দ থাকবে ততক্ষণ কি স্থির থাকে?
ম্যাটানস্টার

2
@ ম্যান্টস্টার, আমি এটি নিজের প্রশ্ন হিসাবে পোস্ট করব। আমি উত্তর দেওয়া শুরু করেছিলাম, তারপরে বুঝতে পেরেছিলাম যে সত্যিকার অর্থে জবাবটার কার্নেলের ব্যবস্থাপনা সম্পর্কে যথেষ্ট পরিমাণে আমি জানি না।
পয়গামপাইল

@ ম্যান্ট্যান্সার ব্যবহারকারী দ্বারা কার্নেল স্পষ্টভাবে বন্ধ না হওয়া পর্যন্ত তাদের জন্য বরাদ্দকৃত সমস্ত ভেরিয়েবল এবং মেমরি বিদ্যমান। এটি কোষগুলির সাথে লিঙ্কযুক্ত নয়। নতুন জুপিটার হাব-এ, সিস্টেম কার্নেলগুলি বন্ধ করতে পারে (এটি কনফিগার করা যায়)।
গ্রেটভোভান

0

নিম্নলিখিত স্নিপেটটি আমার জন্য সমস্যাটি সমাধান করেছে:


class FigureWrapper(object):
    '''Frees underlying figure when it goes out of scope. 
    '''

    def __init__(self, figure):
        self._figure = figure

    def __del__(self):
        plt.close(self._figure)
        print("Figure removed")


# .....
    f, ax = plt.subplots(1, figsize=(20, 20))
    _wrapped_figure = FigureWrapper(f)

    ax.plot(...
    plt.savefig(...
# .....

যখন _wrapped_figureসুযোগের বাইরে চলে যায় রানটাইমটি আমাদের __del__()পদ্ধতিটি plt.close()ভিতরে ভিতরে কল করে । _wrapped_figureকনস্ট্রাক্টরের পরে ব্যতিক্রম আগুন ছড়িয়ে পড়লেও এটি ঘটে ।


0

আপনি কেবলমাত্র অস্থায়ীভাবে সতর্কতাটি দমন করতে চাইলে এটিও কার্যকর:

    import matplotlib.pyplot as plt
       
    with plt.rc_context(rc={'figure.max_open_warning': 0}):
        lots_of_plots()
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.