下一代 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 社区充满活力且提供支持,经验丰富的开发人员和数据科学家渴望提供帮助并分享他们的知识。 加入我们并与我们联系