下一代 Anaconda Navigator


HoloViz Panel 是一个通用的 Python 库,它使开发人员和数据科学家能够轻松构建交互式可视化。 无论您是在进行机器学习项目、开发 Web 应用程序还是设计数据仪表板,Panel 都提供了一套强大的工具和功能来增强您的数据探索和演示能力。 在这篇博文中,我们将深入研究 HoloViz Panel 的令人兴奋的功能,探索它如何彻底改变您的数据可视化工作流程,并演示如何使用大约 100 行代码制作像这样的应用程序。
试用该应用程序并查看代码
ML/AI 已成为数据分析和决策过程不可或缺的一部分。 借助 Panel,您可以将 ML 模型和结果无缝集成到可视化中。 在这篇博文中,我们将探讨如何使用 OpenAI CLIP 模型进行图像分类任务。
CLIP 在大量的图像-文本对数据集上进行了预训练,使其能够理解图像和相应的文本描述,并适用于各种下游任务,例如图像分类。
我们使用了两个与 ML 相关的函数来执行图像分类任务。 第一个函数 load_processor_model 使我们能够从 Hugging Face 加载预训练的 CLIP 模型。 第二个函数 get_similarity_score 计算图像与提供的类标签列表之间的相似度。
@pn.cache
def load_processor_model(
processor_name: str, model_name: str
) -> Tuple[CLIPProcessor, CLIPModel]:
processor = CLIPProcessor.from_pretrained(processor_name)
model = CLIPModel.from_pretrained(model_name)
return processor, model
def get_similarity_scores(class_items: List[str], image: Image) -> List[float]:
processor, model = load_processor_model(
"openai/clip-vit-base-patch32", "openai/clip-vit-base-patch32"
)
inputs = processor(
text=class_items,
images=[image],
return_tensors="pt", # pytorch tensors
)
outputs = model(**inputs)
logits_per_image = outputs.logits_per_image
class_likelihoods = logits_per_image.softmax(dim=1).detach().numpy()
return class_likelihoods[0]
Panel 的主要优势之一是它能够将小部件绑定到函数。 此功能为用户提供了一个直观的界面,用于操作底层数据并通过交互获得更深入的见解。
在我们的示例中,我们有一个 process_input 函数,该函数将我们从图像分类模型获得的相似度分数格式化为具有良好 UI 的 Panel 对象。 实际函数使用了 async;如果您不熟悉 async,请不要担心! 我们将在后面的章节中进行解释,但请注意 async 不是 使用 Panel 的要求——Panel 只是支持它!
async def process_inputs(class_names: List[str], image_url: str):
"""
High level function that takes in the user inputs and returns the
classification results as panel objects.
"""
...
yield results
我们使用两个小部件与此函数进行交互。
image_url 是一个 TextInput 小部件,允许输入任何字符串作为图像 URL。class_names 是另一个 TextInput 小部件,它接受模型可以分类的可能的类名。image_url = pn.widgets.TextInput(
name="Image URL to classify",
value=pn.bind(random_url, randomize_url),
)
class_names = pn.widgets.TextInput(
name="Comma separated class names",
placeholder="Enter possible class names, e.g. cat, dog",
value="cat, dog, parrot",
)
根据 process_inputs 函数签名,它接受两个参数: class_names 和 image_url。 我们可以使用 pn.bind 将每个 arg/kwarg 绑定到一个小部件,如下所示
interactive_result = pn.panel(
pn.bind(process_inputs, image_url=image_url, class_names=class_names),
height=600,
)
为了澄清,如果小部件被命名为 image_url_input 而不是 image_url,那么调用将是
pn.bind(process_inputs, image_url=image_url_input, ...)
应用程序和仪表板的美观性在吸引受众方面起着至关重要的作用。 Panel 使您能够根据 Material 或 Fast 等流行的设计为可视化添加样式,从而使您能够创建具有视觉吸引力和专业外观的界面。
在此示例中,我们使用了 bootstrap 模板,我们可以在其中控制我们想要在多个区域(例如 title 和 main)中显示的内容,并且我们可以为各种组件指定大小和颜色
pn.extension(design="bootstrap", sizing_mode="stretch_width")
我们还将 Progress 栏设计设置为 Material。
row_bar = pn.indicators.Progress(
...
design=pn.theme.Material,
)
请注意,您也可以使用 styles 和 stylesheets!
某些数据处理任务可能在计算上很昂贵,从而导致性能迟缓。 Panel 提供了缓存机制,使您可以存储昂贵计算的结果并在需要时重用它们,从而显着提高应用程序的响应速度。
在我们的示例中,我们使用 pn.cache 装饰器缓存了 load_processor_model 的输出。 这意味着我们不需要多次下载和加载模型。 此步骤将使您的应用程序感觉更灵敏!
附加说明:为了进一步提高响应速度,还有 defer_loading 和 加载指示器。
@pn.cache
def load_processor_model(
processor_name: str, model_name: str
) -> Tuple[CLIPProcessor, CLIPModel]:
processor = CLIPProcessor.from_pretrained(processor_name)
model = CLIPModel.from_pretrained(model_name)
return processor, model
虽然 Panel 提供了丰富的一组交互式功能,但您有时可能需要可以通过 JavaScript 实现的其他功能。 将 JavaScript 代码与 Panel 可视化集成以扩展其功能非常容易。 通过弥合 Python 和 JavaScript 之间的差距,您可以创建高级可视化并添加超出 Panel 本机功能范围的交互式元素。
在我们的应用程序底部,您可能已经观察到一组代表 Panel 社交媒体帐户的图标,包括 LinkedIn 和 Twitter。 当您单击这些图标中的任何一个时,您将被自动重定向到相应的社交媒体个人资料。 这种无缝的点击和重定向功能是通过 Panel 的 JavaScript 与 js_on_click 方法集成实现的
footer_row = pn.Row(pn.Spacer(), align="center")
for icon, url in ICON_URLS.items():
href_button = pn.widgets.Button(icon=icon, width=35, height=35)
href_button.js_on_click(code=f"window.open('{url}')")
footer_row.append(href_button)
footer_row.append(pn.Spacer())
异步编程因其高效处理并发任务的能力而广受欢迎。 我们将讨论同步执行和异步执行之间的差异,并探讨 Panel 对异步操作的支持。 理解这些概念将使您能够在 Panel 中利用异步功能,从而在应用程序中提供增强的性能和响应能力。
在函数中使用 async 允许在单个线程中进行协作式多任务处理,并允许 IO 任务在后台发生。 例如,当我们从互联网获取随机图像时,我们不知道需要等待多久,并且我们不想在等待时停止程序。 Async 启用并发执行,允许我们在等待时执行其他任务,并确保应用程序具有响应性。 请务必添加相应的 awaits。
async def open_image_url(image_url: str) -> Image:
async with aiohttp.ClientSession() as session:
async with session.get(image_url) as resp:
return Image.open(io.BytesIO(await resp.read()))
如果您不熟悉 async,也可以用同步方式重写它! async 不是 使用 Panel 的要求!
def open_image_url(image_url: str) -> Image:
with requests.get(image_url) as resp:
return Image.open(io.BytesIO(resp.read()))
这里我们只探索了一个想法;您还可以尝试更多
查看我们的应用程序库以获取其他想法! 祝您实验愉快!
Panel 社区充满活力且提供支持,经验丰富的开发人员和数据科学家渴望提供帮助并分享他们的知识。 加入我们并与我们联系