Cách chính xác hiện tại để cập nhật động các lô trong Jupyter / iPython là gì?


93

Trong các câu trả lời về cách cập nhật động một âm mưu trong một vòng lặp trong sổ ghi chép ipython (trong một ô) , một ví dụ được đưa ra về cách cập nhật động một âm mưu bên trong sổ ghi chép Jupyter trong vòng lặp Python. Tuy nhiên, điều này hoạt động bằng cách phá hủy và tạo lại cốt truyện trên mỗi lần lặp lại và một nhận xét trong một trong các chuỗi lưu ý rằng tình huống này có thể được cải thiện bằng cách sử dụng %matplotlib nbaggphép thuật mới, cung cấp một nhân vật tương tác được nhúng trong sổ ghi chép, thay vì hơn một hình ảnh tĩnh.

Tuy nhiên, nbaggtính năng mới tuyệt vời này dường như hoàn toàn không có tài liệu theo như tôi có thể nói và tôi không thể tìm thấy ví dụ về cách sử dụng nó để cập nhật động một cốt truyện. Vì vậy, câu hỏi của tôi là, làm thế nào để cập nhật một cách hiệu quả một âm mưu hiện có trong sổ ghi chép Jupyter / Python, bằng cách sử dụng phụ trợ nbagg? Vì cập nhật động các lô trong matplotlib nói chung là một vấn đề phức tạp, nên một ví dụ làm việc đơn giản sẽ là một trợ giúp to lớn. Một con trỏ đến bất kỳ tài liệu nào về chủ đề này cũng sẽ cực kỳ hữu ích.

Để rõ ràng những gì tôi đang yêu cầu: những gì tôi muốn làm là chạy một số mã mô phỏng trong một vài lần lặp, sau đó vẽ một biểu đồ về trạng thái hiện tại của nó, sau đó chạy nó thêm một vài lần lặp, sau đó cập nhật biểu đồ để phản ánh trạng thái hiện tại, v.v. Vì vậy, ý tưởng là vẽ một cốt truyện và sau đó, không có bất kỳ sự tương tác nào từ người dùng, hãy cập nhật dữ liệu trong cốt truyện mà không phá hủy và tạo lại toàn bộ.

Đây là một số mã được sửa đổi một chút từ câu trả lời cho câu hỏi được liên kết ở trên, đạt được điều này bằng cách vẽ lại toàn bộ hình mỗi lần. Tôi muốn đạt được kết quả tương tự, nhưng sử dụng hiệu quả hơn nbagg.

%matplotlib inline
import time
import pylab as pl
from IPython import display
for i in range(10):
    pl.clf()
    pl.plot(pl.randn(100))
    display.display(pl.gcf())
    display.clear_output(wait=True)
    time.sleep(1.0)

Câu trả lời:


62

Đây là một ví dụ cập nhật một âm mưu trong một vòng lặp. Nó cập nhật dữ liệu trong hình và không phải vẽ lại toàn bộ hình mỗi lần. Nó thực hiện khối, mặc dù nếu bạn quan tâm đến việc chạy một tập hợp mô phỏng hữu hạn và lưu kết quả ở đâu đó, nó có thể không phải là vấn đề đối với bạn.

%matplotlib notebook

import numpy as np
import matplotlib.pyplot as plt
import time

def pltsin(ax, colors=['b']):
    x = np.linspace(0,1,100)
    if ax.lines:
        for line in ax.lines:
            line.set_xdata(x)
            y = np.random.random(size=(100,1))
            line.set_ydata(y)
    else:
        for color in colors:
            y = np.random.random(size=(100,1))
            ax.plot(x, y, color)
    fig.canvas.draw()

fig,ax = plt.subplots(1,1)
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_xlim(0,1)
ax.set_ylim(0,1)
for f in range(5):
    pltsin(ax, ['b', 'r'])
    time.sleep(1)

Tôi đưa điều này lên nbviewer ở đây.

Có một phiên bản IPython Widget nbagghiện đang được hoàn thiện tại kho lưu trữ Matplotlib . Khi có sẵn, đó có thể sẽ là cách tốt nhất để sử dụng nbagg.

CHỈNH SỬA: cập nhật để hiển thị nhiều ô


1
Tuyệt vời, điều đó có vẻ hoạt động tốt. Việc thiếu tính tương tác trong khi nó đang chạy không phải là vấn đề lớn đối với tôi. Một điều hơi kỳ lạ: nếu tôi thay đổi thành while True:vòng lặp for, khi vòng lặp kết thúc, tôi sẽ nhận được hai hình ảnh tĩnh của âm mưu cuối cùng, thay vì một hình ảnh nbagg tương tác. Bất kỳ ý tưởng tại sao đó là?
Nathaniel

Tôi đã đổi vòng lặp while thành vòng lặp for và thử nó trên tmpnb.org nhưng tôi không thấy hình ảnh thứ hai hoặc mất tương tác. Chụp trong bóng tối, nhưng bạn có thể thử di chuyển vòng lặp xung quanh lệnh gọi đến hàm, thay vì có vòng lặp trong hàm. cho e trong phạm vi (10): pltsin (rìu) time.sleep (1)
khí nén

3
@pneumatics Thật không may, nó có một số vấn đề với Matplotlib 2.0 trên màn hình Retina: trong các ô vòng lặp nhỏ hơn thông thường hai lần.
Alexander Rodin

1
Có vẻ như hình không có thời gian để thay đổi kích thước chính xác. Vì vậy, tôi đã có trải nghiệm tốt hơn nhiều khi đặt một plt.show()và di chuyển vòng lặp for sang ô tiếp theo.
Tầm quan

2
Hãy chắc chắn rằng bạn có sổ ghi chép% matplotlib trong cùng ô sổ ghi chép jupyter với ô của bạn - Tôi đã dành hơn 2 giờ hôm nay để khắc phục sự cố này vì tôi có sổ ghi chép% matplotlib trong ô đầu tiên có trạng thái nhập
aguazul

12

Tôi đang sử dụng jupyter-lab và điều này phù hợp với tôi (điều chỉnh nó cho phù hợp với trường hợp của bạn):

from IPython.display import clear_output
from matplotlib import pyplot as plt
import collections
%matplotlib inline

def live_plot(data_dict, figsize=(7,5), title=''):
    clear_output(wait=True)
    plt.figure(figsize=figsize)
    for label,data in data_dict.items():
        plt.plot(data, label=label)
    plt.title(title)
    plt.grid(True)
    plt.xlabel('epoch')
    plt.legend(loc='center left') # the plot evolves to the right
    plt.show();

Sau đó, trong một vòng lặp, bạn điền từ điển và chuyển nó vào live_plot():

data = collections.defaultdict(list)
for i in range(100):
    data['foo'].append(np.random.random())
    data['bar'].append(np.random.random())
    data['baz'].append(np.random.random())
    live_plot(data)

đảm bảo bạn có một vài ô bên dưới ô, nếu không, chế độ xem sẽ ổn định mỗi khi ô được vẽ lại.


1
điều này tạo ra một âm mưu mới mỗi lần hơn là cập nhật các âm mưu hiện
khí nén

2
Chính xác. Tôi chưa tìm ra cách tốt hơn để có một âm mưu động lực học trong phòng thí nghiệm jupyter.
Ziofil

1
Có cách nào để đặt khoảng thời gian chờ giữa các lần lặp lại không? chứ không phải chỉ có 'chờ đợi = Đúng'
Ahmad Moussa

1
Mỗi khi âm mưu được vẽ lại, biểu đồ sẽ nhấp nháy. Có cách nào để khắc phục vấn đề này? Tôi có một vài ô trống trong cốt truyện, nhưng điều đó dường như không hữu ích.
MasayoMusic

@MasayoMusic xem "Đầu ra nhấp nháy và nhảy" trong buildmedia.readthedocs.org/media/pdf/ipywidgets/latest/…
leo

0

Tôi đã điều chỉnh câu trả lời @Ziofil và sửa đổi nó để chấp nhận x, y làm danh sách và xuất ra một biểu đồ phân tán cộng với xu hướng tuyến tính trên cùng một biểu đồ.

from IPython.display import clear_output
from matplotlib import pyplot as plt
%matplotlib inline
    
def live_plot(x, y, figsize=(7,5), title=''):
    clear_output(wait=True)
    plt.figure(figsize=figsize)
    plt.xlim(0, training_steps)
    plt.ylim(0, 100)
    x= [float(i) for i in x]
    y= [float(i) for i in y]
    
    if len(x) > 1:
        plt.scatter(x,y, label='axis y', color='k') 
        m, b = np.polyfit(x, y, 1)
        plt.plot(x, [x * m for x in x] + b)

    plt.title(title)
    plt.grid(True)
    plt.xlabel('axis x')
    plt.ylabel('axis y')
    plt.show();

bạn chỉ cần gọi live_plot(x, y)bên trong một vòng lặp. đây là cách nó trông: nhập mô tả hình ảnh ở đây

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.