首页 > 解决方案 > 在 Python 和 Bokeh 中选择 K;滑块小部件未更新 Python 代码

问题描述

我正在尝试使用 Python 创建一个聚类函数,并使用 Bokeh 上的滑块小部件进行交互。滑块小部件允许用户选择 K 的值(即要查找的集群数)。

这是代码示例:-

from bokeh.models.annotations import Label
import numpy as np
from sklearn import cluster, datasets
from sklearn.preprocessing import StandardScaler

from bokeh.layouts import column, row
from bokeh.plotting import figure, output_file, show
from bokeh.models import CustomJS, Select, Slider
from bokeh.io import curdoc
print("\n\n*** This example may take several seconds to run before displaying. ***\n\n")

N = 50000
PLOT_SIZE = 400

# generate datasets.
np.random.seed(0)
noisy_circles = datasets.make_circles(n_samples=N, factor=.5, noise=.04)
noisy_moons = datasets.make_moons(n_samples=N, noise=.05)
centers = [(-2, 3), (2, 3), (-2, -3), (2, -3)]
blobs1 = datasets.make_blobs(centers=centers, n_samples=N, cluster_std=0.4, random_state=8)
blobs2 = datasets.make_blobs(centers=centers, n_samples=N, cluster_std=0.7, random_state=8)

colors = np.array([x for x in ('#00f', '#0f0', '#f00', '#0ff', '#f0f', '#ff0')])
colors = np.hstack([colors] * 20)




k_slider = Slider(title = "Select K", value=3, start = 2, end = 6)

k = k_slider.value

kmeans   = cluster.KMeans(n_clusters= k)

def update_k(attr,old,new):
    k = k_slider.value
    kmeans   = cluster.KMeans(n_clusters= k)
    return kmeans

k_slider.on_change('value', update_k)

algorithm = kmeans



plots =[]
for dataset in (noisy_circles, noisy_moons, blobs1, blobs2):
    X, y = dataset
    X = StandardScaler().fit_transform(X)

    algorithm.fit(X)
    if hasattr(algorithm, 'labels_'):
        y_pred = algorithm.labels_.astype(int)
    else:
        y_pred = algorithm.predict(X)
    p = figure(output_backend="webgl", title=algorithm.__class__.__name__,width=PLOT_SIZE, height=PLOT_SIZE)
    p.circle(X[:, 0], X[:, 1], color=colors[y_pred].tolist(), alpha=0.1,)
    plots.append(p)




layout = column(k_slider,row(plots[:2]), row(plots[2:]))

output_file("clustering.html", title="clustering with sklearn")

curdoc().add_root(layout)

K 的默认值为 3,但我希望滑块小部件将其更改为 2-6 之间的任何值。我用 bokeh serve 启动了这个应用程序,它显示了带有 3 个可视化集群的图。但是,当我更改滑块时,它不允许我更新绘图。

我咨询了以下内容:-

滑块值未更新 Bokeh Python

运行散景服务器

但我的问题的解决方案并不明显。谁能告诉我/添加我的代码缺少什么?

非常感谢 :)

标签: pythonwidgetdata-visualizationbokehk-means

解决方案


  1. 更新散景图意味着更新data_source它的渲染器,在本例中为circle. 所以你要这样做:

plots[0].renderers[0].data_source.data['x'] = NEW_X[:, 0] plots[0].renderers[0].data_source.data['y'] = NEW_X[:, 1] plots[0].renderers[0].data_source.change.emit()

colors...一样

  1. 看起来您需要for在 Python 回调中重复整个循环,algorithmkmeans取决于K. 如果您K的平均聚类数和每个聚类由一个图表示,则意味着您需要动态删除/添加图,依赖于K.

  2. 因此,如果 2) 为真,则无需在回调中更新现有图,但您可以尝试删除现有root图并添加包含新图的新图。所以在你的回调中你可以这样做:

def update_k(attr,old,new):
    k = k_slider.value
    kmeans   = cluster.KMeans(n_clusters= k)
    
    plots =[]
    for dataset in (noisy_circles, noisy_moons, blobs1, blobs2):
        ...
        plots.append(p)

    curdoc().remove_root()
    curdoc().add_root(column(k_slider,row(plots[:2]), row(plots[2:])))

它应该可以工作,但请务必查阅有关如何使用remove_root()的文档

或者,您可以操纵/替换以下内容而不是删除根目录layout.children[k_slider, row1, row2]


推荐阅读