简体   繁体   English

当我更改不应触发任何更新的按钮设置时,为什么我的 plot 会被面板更新(两次)? (面板霍洛维兹)

[英]Why is my plot updated by panel (twice) when I change a button setting that shouldn't trigger any updates? (Panel Holoviz)

I made a class to explore and train models.我制作了一个 class 来探索和训练模型。

When I change the value of dropdown 'choose_model_type' in the code example below, I would expect nothing to change in my dashboard, since there are no @param.depends('choose_model_type', watch=True) in my class.当我在下面的代码示例中更改下拉菜单“choose_model_type”的值时,我希望仪表板中没有任何变化,因为我的 class 中没有@param.depends('choose_model_type', watch=True) However, my dashboard gets updated, when I change the value of dropdown 'choose_model_type'.但是,当我更改下拉菜单“choose_model_type”的值时,我的仪表板会更新。 In this case function plot_y() gets triggered twice if I look at the logs:在这种情况下,如果我查看日志,function plot_y() 会被触发两次:

2019-09-26 11:24:42,802 starting plot_y 2019-09-26 11:24:42,802 开始 plot_y
2019-09-26 11:24:42,825 starting plot_y 2019-09-26 11:24:42,825 开始 plot_y

This is for me unexpected behavior.这对我来说是意想不到的行为。 I don't want plot_y() to be triggered when I change 'choose_model_type'.我不希望在更改“choose_model_type”时触发 plot_y()。
How do i make sure that plot_y gets triggered only when 'y' changes (and my plot is updated in the dashboard) and not when other parameters such as dropdown change?如何确保 plot_y 仅在“y”更改时触发(并且我的 plot 在仪表板中更新)而不是在其他参数(例如下拉菜单)更改时触发?
I want to control what gets triggered when, but for me there seems to be some magic going on.我想控制什么时候触发,但对我来说似乎有一些魔法正在发生。

Other related question is:其他相关问题是:
Why does plot_y() get triggered twice?为什么 plot_y() 被触发两次? If I change 'pred_target' it also triggers plot_y() twice.如果我更改 'pred_target' 它也会触发 plot_y() 两次。 Same happens when I change the value of 'choose_model_type': plot_y() gets triggered twice.当我更改“choose_model_type”的值时也会发生同样的情况:plot_y() 被触发两次。

# library imports    
import logging

import numpy as np
import pandas as pd

import hvplot
import hvplot.pandas

import holoviews as hv
from holoviews.operation.datashader import datashade, dynspread
hv.extension('bokeh', logo=False)

import panel as pn
import param

# create some sample data
df = pd.DataFrame(np.random.choice(100, size=[50, 2]), columns=['TARGET1', 'TARGET2'])

# class to train my models with some settings
class ModelTrainer(param.Parameterized):

    logging.info('initializing class')

    pred_target = param.Selector(
        default='TARGET1',
        objects=['TARGET1', 'TARGET2'],
        label='Choose prediction target'
    )

    choose_model_type = param.Selector(
        default='LINEAR', 
        objects=['LINEAR', 'LGBM', 'RANDOM_FOREST'],
        label='Choose type of model',
    )

    y = df[pred_target.default]


    # i expect this function only to be triggered when pred_target changes
    @param.depends('pred_target', watch=True)
    def _reset_variables(self):
        logging.info('starting reset variables')
        self.y = df[self.pred_target]

    # i expect plot_y() only to be triggered when y changes   
    @param.depends('y', watch=True)
    def plot_y(self):
        logging.info('starting plot_y')
        self.y_plot = dynspread(datashade(self.y.hvplot.scatter()))
        return self.y_plot

model_trainer = ModelTrainer()

# show model dashboard
pn.Column(
    pn.Row(model_trainer.param['pred_target']),
    pn.Row(model_trainer.param['choose_model_type']),
    pn.Row(model_trainer.plot_y)
).servable()

dropdown_changes_dashboard_shouldnt_happen

The problem here is one of validation, specifically the issue is here: @param.depends('y', watch=True) .这里的问题是验证之一,特别是问题在这里: @param.depends('y', watch=True) y is not a parameter in your example, therefore param.depends can't resolve it and ends up falling back to depending on all parameters. y在您的示例中不是参数,因此 param.depends 无法解决它并最终退回到取决于所有参数。 I've filed an issue to resolve this here .我已经提交了一个问题来解决这个问题 If you change your example to:如果您将示例更改为:

y = param.Series(default=df[pred_target.default])

It will work, however you will still have the issue with the callback being called twice.它会起作用,但是您仍然会遇到回调被调用两次的问题。 This is because you have set watch=True in the depends declaration.这是因为您在依赖声明中设置了watch=True Setting watch=True only makes sense for methods that have side-effects, if your method is something that returns a value then it will rarely make sense to set it.设置watch=True仅对具有副作用的方法有意义,如果您的方法是返回值的方法,那么设置它几乎没有意义。 To expand on that, when you pass the method to panel, eg pn.Row(model_trainer.plot_y) , it will automatically watch the parameters and call the method to update the plot when the parameters change.进一步扩展,当您将方法传递给面板时,例如pn.Row(model_trainer.plot_y) ,它将自动监视参数并在参数更改时调用该方法来更新 plot。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM