当我更改不应触发任何更新的按钮设置时,为什么我的图由面板更新(两次)? (Holoviz小组)

时间:2019-09-26 09:48:44

标签: python holoviews holoviz panel-pyviz

我上了一堂课来探索和训练模型。

当我在下面的代码示例中更改下拉列表'choose_model_type'的值时,我希望仪表板中没有任何更改,因为我的班级中没有@param.depends('choose_model_type', watch=True)。 但是,当我更改下拉菜单“ choose_model_type”的值时,仪表板会更新。在这种情况下,如果我查看日志,则函数plot_y()被触发两次:

  

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

这对我来说是意外行为。我不希望在更改“ choose_model_type”时触发plot_y()。
我如何确保仅当“ y”更改(并且仪表板中的绘图已更新)时,plot_y才会触发,而下拉列表等其他参数更改时,则不会触发?
我想控制什么时候触发,但是对我来说似乎正在发生某种魔术。

其他相关问题是:
为什么plot_y()被触发两次?如果更改“ pred_target”,它还会触发两次plot_y()。当我更改“ 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

1 个答案:

答案 0 :(得分:1)

这里的问题是验证之一,具体地说,这里的问题是:@param.depends('y', watch=True)y在您的示例中不是参数,因此param.depends无法解析它,最终取决于所有参数。我提出了一个问题来解决此here。如果您将示例更改为:

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

它将起作用,但是您仍然会遇到两次调用回调的问题。这是因为您在depends声明中设置了watch=True。设置watch=True仅对具有副作用的方法有意义,如果您的方法返回一个值,则对其进行设置几乎没有意义。为了扩展这一点,当您将方法传递给面板时,例如pn.Row(model_trainer.plot_y),它将在参数更改时自动监视参数并调用方法以更新绘图。