为什么当我更改不应触发任何更新的按钮设置时,面板会更新我的绘图(两次)? (Panel Holoviz)
Why is my plot updated by panel (twice) when I change a button setting that shouldn't trigger any updates? (Panel Holoviz)
我做了一个 class 来探索和训练模型。
当我在下面的代码示例中更改下拉列表 'choose_model_type' 的值时,我希望我的仪表板不会发生任何变化,因为我的 class 中没有 @param.depends('choose_model_type', watch=True)
。
但是,当我更改下拉列表 'choose_model_type' 的值时,我的仪表板会更新。在这种情况下,如果我查看日志,函数 plot_y() 会被触发两次:
2019-09-26 11:24:42,802 starting plot_y
2019-09-26 11:24:42,825 starting plot_y
这对我来说是意外的行为。我不想在更改 'choose_model_type'.
时触发 plot_y()
我如何确保 plot_y 仅在 '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()
这里的问题是验证之一,具体问题在这里:@param.depends('y', watch=True)
。 y
不是您示例中的参数,因此 param.depends 无法解析它并最终退回到取决于所有参数。我已经提交了一个问题来解决这个 here。如果您将示例更改为:
y = param.Series(default=df[pred_target.default])
它会起作用,但是您仍然会遇到回调被调用两次的问题。这是因为您在 depends 声明中设置了 watch=True
。设置 watch=True
只对有副作用的方法有意义,如果你的方法是 returns 一个值,那么设置它几乎没有意义。为了扩展这一点,当您将方法传递给面板时,例如pn.Row(model_trainer.plot_y)
,会自动监听参数,当参数变化时,会自动调用方法更新绘图
我做了一个 class 来探索和训练模型。
当我在下面的代码示例中更改下拉列表 'choose_model_type' 的值时,我希望我的仪表板不会发生任何变化,因为我的 class 中没有 @param.depends('choose_model_type', watch=True)
。
但是,当我更改下拉列表 'choose_model_type' 的值时,我的仪表板会更新。在这种情况下,如果我查看日志,函数 plot_y() 会被触发两次:
2019-09-26 11:24:42,802 starting plot_y
2019-09-26 11:24:42,825 starting plot_y
这对我来说是意外的行为。我不想在更改 'choose_model_type'.
时触发 plot_y()
我如何确保 plot_y 仅在 '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()
这里的问题是验证之一,具体问题在这里:@param.depends('y', watch=True)
。 y
不是您示例中的参数,因此 param.depends 无法解析它并最终退回到取决于所有参数。我已经提交了一个问题来解决这个 here。如果您将示例更改为:
y = param.Series(default=df[pred_target.default])
它会起作用,但是您仍然会遇到回调被调用两次的问题。这是因为您在 depends 声明中设置了 watch=True
。设置 watch=True
只对有副作用的方法有意义,如果你的方法是 returns 一个值,那么设置它几乎没有意义。为了扩展这一点,当您将方法传递给面板时,例如pn.Row(model_trainer.plot_y)
,会自动监听参数,当参数变化时,会自动调用方法更新绘图