当前位置: 首页 > news >正文

写给大数据开发:在Databricks中自定义函数

你是否曾经在处理海量数据时感到力不从心?是否在重复编写相似代码时感到厌烦?如果是,那么Databricks中的自定义函数可能就是你一直在寻找的救星。在接下来的5分钟里,让我们一起探索如何利用这个强大的工具来revolutionize你的大数据开发工作流程。

目录

    • 为什么要在Databricks中使用自定义函数?
    • Databricks中自定义函数的类型
    • 如何在Databricks中创建自定义函数
      • 3.1 Python UDF
      • 3.2 Pandas UDF
      • 3.3 SQL UDF
    • 自定义函数的性能优化
    • 自定义函数的最佳实践
    • 常见问题和解决方案
    • 结语

为什么要在Databricks中使用自定义函数?

image.png

在大数据开发的世界里,效率就是生命。而Databricks的自定义函数(User-Defined Functions, UDFs)正是提升效率的利器。想象一下,你可以将那些反复使用的复杂逻辑封装成一个简单的函数调用,是不是很酷?

自定义函数不仅可以大大减少代码重复,还能提高代码的可读性和可维护性。更重要的是,它们能够seamlessly地集成到Spark SQL和DataFrame操作中,让你的数据处理pipeline更加流畅。

让我们来看一个简单的例子。假设你经常需要将温度从摄氏度转换为华氏度:

# 未使用自定义函数
df = spark.createDataFrame([(0,), (10,), (20,), (30,)], ["celsius"])
df_fahrenheit = df.withColumn("fahrenheit", (df.celsius * 9/5) + 32)# 使用自定义函数
from pyspark.sql.functions import udf
from pyspark.sql.types import DoubleType@udf(returnType=DoubleType())
def celsius_to_fahrenheit(celsius):return (celsius * 9/5) + 32df_fahrenheit = df.withColumn("fahrenheit", celsius_to_fahrenheit(df.celsius))

看到区别了吗?使用自定义函数后,我们的代码变得更加清晰,而且可以在任何需要的地方重复使用这个转换逻辑。

Databricks中自定义函数的类型

image.png

Databricks支持多种类型的自定义函数,以满足不同的需求:

  1. Python UDF: 使用Python编写,适用于简单的操作。
  2. Pandas UDF: 利用Pandas库的高性能,适用于复杂的数据操作。
  3. SQL UDF: 直接在SQL查询中使用,适用于SQL重度用户。

每种类型都有其特定的用途和优势。接下来,我们将深入探讨如何创建和使用这些不同类型的自定义函数。

如何在Databricks中创建自定义函数

3.1 Python UDF

Python UDF是最简单和最常用的自定义函数类型。它们易于编写,适用于大多数简单到中等复杂度的操作。
image.png
让我们创建一个稍微复杂一点的Python UDF,用于计算给定文本中的单词数:

from pyspark.sql.functions import udf
from pyspark.sql.types import IntegerType@udf(returnType=IntegerType())
def word_count(text):if text is None:return 0return len(text.split())# 创建示例DataFrame
df = spark.createDataFrame([("Hello world",),("This is a longer sentence",),(None,),("Databricks is awesome for big data",)
], ["text"])# 应用UDF
result_df = df.withColumn("word_count", word_count(df.text))# 显示结果
result_df.show(truncate=False)

输出结果:

+-----------------------------------+----------+
|text                               |word_count|
+-----------------------------------+----------+
|Hello world                        |2         |
|This is a longer sentence          |5         |
|null                               |0         |
|Databricks is awesome for big data |6         |
+-----------------------------------+----------+

在这个例子中,我们定义了一个word_count函数,它接受一个文本字符串作为输入,并返回单词数量。我们使用@udf装饰器将这个Python函数转换为Spark UDF,并指定返回类型为IntegerType()

注意我们如何处理了None值,这在处理真实世界的数据时非常重要。始终记住要考虑边界情况和异常情况。

3.2 Pandas UDF

image.png

当你需要处理更复杂的数据操作时,Pandas UDF是一个很好的选择。Pandas UDF允许你利用Pandas库的高性能数据处理能力,同时还能与Spark的分布式计算框架无缝集成。

让我们创建一个Pandas UDF来计算移动平均值:

import pandas as pd
from pyspark.sql.functions import pandas_udf
from pyspark.sql.types import DoubleType@pandas_udf(DoubleType())
def moving_average(values: pd.Series, window: int) -> pd.Series:return values.rolling(window=window, min_periods=1).mean()# 创建示例DataFrame
df = spark.createDataFrame([(1, 10.0),(2, 20.0),(3, 15.0),(4, 30.0),(5, 25.0),(6, 40.0)
], ["id", "value"])# 应用Pandas UDF
window_size = 3
result_df = df.withColumn("moving_avg", moving_average(df.value, window_size))# 显示结果
result_df.show()

输出结果:

+---+-----+------------------+
| id|value|        moving_avg|
+---+-----+------------------+
|  1| 10.0|              10.0|
|  2| 20.0|              15.0|
|  3| 15.0|              15.0|
|  4| 30.0|21.666666666666668|
|  5| 25.0| 23.33333333333333|
|  6| 40.0| 31.66666666666667|
+---+-----+------------------+

在这个例子中,我们定义了一个moving_average函数,它使用Pandas的rolling函数计算移动平均值。我们使用@pandas_udf装饰器将这个函数转换为Pandas UDF。

注意Pandas UDF的语法与Python UDF略有不同。这里我们明确指定了输入和输出的类型都是pd.Series。这种类型提示不仅提高了代码的可读性,还能帮助Spark优化执行计划。

Pandas UDF特别适合于需要在一组值上进行操作的场景,比如时间序列分析、统计计算等。它能够充分利用Pandas的向量化操作,大大提高处理效率。

3.3 SQL UDF

如果你更喜欢使用SQL进行数据处理,Databricks也支持创建SQL UDF。这种类型的UDF直接在SQL查询中定义和使用,非常适合那些习惯于SQL的数据分析师和工程师。
image.png

让我们创建一个SQL UDF来计算给定数字的阶乘:

-- 创建SQL UDF
CREATE OR REPLACE FUNCTION factorial(n INT)
RETURNS INT
RETURN CASE WHEN n <= 1 THEN 1ELSE n * factorial(n-1)END;-- 创建示例表
CREATE OR REPLACE TEMPORARY VIEW numbers AS
SELECT 1 AS n
UNION ALL SELECT 2
UNION ALL SELECT 3
UNION ALL SELECT 4
UNION ALL SELECT 5;-- 使用SQL UDF
SELECT n, factorial(n) AS factorial_n
FROM numbers
ORDER BY n;

输出结果:

+---+-----------+
|  n|factorial_n|
+---+-----------+
|  1|          1|
|  2|          2|
|  3|          6|
|  4|         24|
|  5|        120|
+---+-----------+

在这个例子中,我们首先定义了一个名为factorial的SQL UDF。这个函数使用递归方法计算阶乘。然后,我们创建了一个临时视图numbers,并在查询中使用我们的UDF。

SQL UDF的一大优势是它可以直接在SQL查询中使用,无需切换到Python环境。这对于那些主要使用SQL进行数据分析的用户来说非常方便。

但是要注意,SQL UDF通常比Python UDF或Pandas UDF的性能稍差,特别是在处理复杂逻辑时。因此,在选择使用SQL UDF时,要权衡便利性和性能需求。

自定义函数的性能优化

image.png

虽然自定义函数为我们提供了强大的功能,但如果使用不当,也可能成为性能瓶颈。以下是一些优化自定义函数性能的技巧:

  1. 选择正确的UDF类型: 对于简单操作,使用Python UDF;对于复杂的数据操作,特别是涉及到向量化操作时,使用Pandas UDF。

  2. 最小化数据传输: UDF的执行涉及到数据从Spark执行器到UDF执行环境的序列化和反序列化。尽量在UDF内部完成尽可能多的操作,减少数据传输。

  3. 使用广播变量: 如果你的UDF需要使用大型查找表或配置数据,考虑使用Spark的广播变量。

  4. 批处理: Pandas UDF默认就是批处理的,但对于Python UDF,你可以使用pandas_udfPandasUDFType.SCALAR类型来实现批处理。

  5. 避免在UDF中使用全局变量: 这可能导致不必要的数据shuffle。

让我们通过一个例子来说明如何优化UDF:

from pyspark.sql.functions import pandas_udf, PandasUDFType
import pandas as pd# 假设这是一个大型查找表
lookup_table = {i: f"value_{i}" for i in range(1000000)}# 使用广播变量
broadcast_lookup = spark.sparkContext.broadcast(lookup_table)@pandas_udf("string", PandasUDFType.SCALAR)
def optimized_lookup(keys: pd.Series) -> pd.Series:# 使用广播变量进行查找return keys.map(lambda x: broadcast_lookup.value.get(x, "not_found"))# 创建示例DataFrame
df = spark.createDataFrame([(i,) for i in range(10)], ["key"])# 应用优化后的UDF
result_df = df.withColumn("value", optimized_lookup(df.key))# 显示结果
result_df.show()

在这个例子中,我们使用了几种优化技巧:

  1. 我们使用了pandas_udf来创建一个批处理UDF,这比传统的Python UDF更高效。
  2. 我们使用了广播变量来分发大型查找表,避免了在每个任务中重复序列化和反序列化这个大表。
  3. 我们在UDF内部使用了Pandas的向量化操作(map),这比循环遍历每个元素要快得多。

通过这些优化,我们的UDF可以更高效地处理大量数据。

自定义函数的最佳实践

image.png

在Databricks中使用自定义函数时,遵循一些最佳实践可以帮助你写出更好的代码:

  1. 保持函数简单: 每个函数应该只做一件事,并且做好这件事。复杂的函数难以理解和维护。

  2. 适当的错误处理: 在函数中加入适当的错误处理逻辑,以防止因为异常数据导致整个作业失败。

  3. 详细的文档: 为你的函数添加清晰的文档字符串,说明函数的用途、参数和返回值。

  4. 测试: 在将UDF应用到大型数据集之前,先在小的数据样本上测试。

  5. 版本控制: 将你的UDF代码纳入版本控制系统,方便追踪修改和协作。

  6. 命名规范: 使用有意义的函数名和变量名,遵循PEP 8命名规范。

让我们通过一个例子来说明这些最佳实践:

from pyspark.sql.functions import udf
from pyspark.sql.types import StringType
import re@udf(returnType=StringType())
def clean_and_standardize_text(text: str) -> str:"""清理并标准化输入文本。此函数执行以下操作:1. 将文本转换为小写2. 移除所有非字母数字字符3. 将多个空格替换为单个空格4. 去除首尾空白字符参数:text (str): 需要清理的输入文本返回:str: 清理和标准化后的文本异常:TypeError: 如果输入不是字符串类型"""if not isinstance(text, str):raise TypeError("Input must be a string")try:# 转换为小写text = text.lower()# 移除非字母数字字符text = re.sub(r'[^a-z0-9\s]', '', text)# 将多个空格替换为单个空格text = re.sub(r'\s+', ' ', text)# 去除首尾空白字符return text.strip()except Exception as e:# 记录错误,但返回原始输入,以避免任务失败print(f"Error processing text: {e}")return text# 创建示例DataFrame
df = spark.createDataFrame([("Hello, World! 123",),("  Data   Science  is  AWESOME!!!  ",),("Python & Spark",),(None,)
], ["text"])# 应用UDF
result_df = df.withColumn("cleaned_text", clean_and_standardize_text(df.text))# 显示结果
result_df.show(truncate=False)

这个例子展示了以下最佳实践:

  1. 函数简单明了:函数只做一件事 - 清理和标准化文本。
  2. 错误处理:我们检查了输入类型,并在处理过程中捕获了可能的异常。
  3. 详细文档:函数有清晰的文档字符串,解释了它的用途、参数和返回值。
  4. 命名规范:函数名clean_and_standardize_text清楚地表明了其功能。

通过遵循这些最佳实践,我们创建了一个健壮、可读、可维护的UDF。

常见问题和解决方案

image.png

在使用Databricks自定义函数时,开发者可能会遇到一些常见问题。让我们探讨其中的一些问题及其解决方案:

  1. 性能问题

问题:UDF执行速度慢,特别是在处理大型数据集时。

解决方案:

  • 使用Pandas UDF代替普通Python UDF
  • 减少UDF内的数据移动
  • 考虑使用内置函数代替UDF(如果可能的话)

示例:

from pyspark.sql.functions import pandas_udf
from pyspark.sql.types import DoubleType
import pandas as pd# 低效的Python UDF
@udf(returnType=DoubleType())
def slow_square(x):return float(x ** 2)# 高效的Pandas UDF
@pandas_udf(DoubleType())
def fast_square(x: pd.Series) -> pd.Series:return x ** 2# 创建示例DataFrame
df = spark.range(1000000)# 比较性能
%time df.withColumn("squared_slow", slow_square(df.id)).count()
%time df.withColumn("squared_fast", fast_square(df.id)).count()
  1. 序列化错误

问题:在UDF中使用不可序列化的对象时出现错误。

解决方案:

  • 确保UDF中使用的所有对象都是可序列化的
  • 使用@pandas_udf并在函数内部创建不可序列化的对象

示例:

from pyspark.sql.functions import pandas_udf
from pyspark.sql.types import StringType
import pandas as pd
import nltk# 这会失败,因为nltk.tokenize.word_tokenize不可序列化
@udf(returnType=StringType())
def tokenize_udf_wrong(text):return " ".join(nltk.tokenize.word_tokenize(text))# 这样可以工作
@pandas_udf(StringType())
def tokenize_udf_correct(text: pd.Series) -> pd.Series:nltk.download('punkt', quiet=True)return text.apply(lambda x: " ".join(nltk.tokenize.word_tokenize(x)))# 创建示例DataFrame
df = spark.createDataFrame([("Hello world!",), ("How are you?",)], ["text"])# 应用正确的UDF
result_df = df.withColumn("tokenized", tokenize_udf_correct(df.text))
result_df.show(truncate=False)
  1. 数据类型不匹配

问题:UDF的返回类型与预期不符。

解决方案:

  • 明确指定UDF的返回类型
  • 在UDF内部进行适当的类型转换

示例:

from pyspark.sql.functions import udf
from pyspark.sql.types import IntegerType, StringType# 错误的UDF - 返回类型不匹配
@udf(returnType=IntegerType())
def length_udf_wrong(text):return len(text)  # 这会失败,因为Python的len()返回一个整数,但Spark期望一个可为null的整数# 正确的UDF
@udf(returnType=IntegerType())
def length_udf_correct(text):if text is None:return Nonereturn len(text)# 创建示例DataFrame
df = spark.createDataFrame([("hello",), (None,), ("world",)], ["text"])# 应用正确的UDF
result_df = df.withColumn("length", length_udf_correct(df.text))
result_df.show()

通过理解这些常见问题和解决方案,你可以更有效地在Databricks中使用自定义函数,避免常见的陷阱,并编写更高效、更可靠的代码。

结语

在这篇博客中,我们深入探讨了Databricks中自定义函数的世界。从基本的Python UDF到高性能的Pandas UDF,再到灵活的SQL UDF,我们已经涵盖了广泛的主题。我们学习了如何创建这些函数,如何优化它们的性能,以及如何遵循最佳实践来编写高质量的代码。
image.png

自定义函数是Databricks生态系统中的一个强大工具。它们允许我们将复杂的逻辑封装在可重用的单元中,大大提高了代码的可读性和可维护性。通过正确使用UDF,我们可以显著提升数据处理的效率和灵活性。

然而,重要的是要记住,UDF并不是万能的解决方案。在某些情况下,使用Spark的内置函数或者重新设计数据处理流程可能是更好的选择。作为开发者,我们需要权衡使用UDF的便利性和潜在的性能影响。

最后,我鼓励你在自己的Databricks项目中尝试使用自定义函数。从小规模开始,逐步扩大应用范围。记住要经常测试和优化你的UDF,以确保它们在大规模数据集上也能高效运行。

随着你在Databricks中积累更多经验,你会发现自定义函数是你工具箱中不可或缺的一部分,能够帮助你更有效地处理各种数据挑战。

祝你在Databricks的旅程中一切顺利,happy coding!

相关文章:

写给大数据开发:在Databricks中自定义函数

你是否曾经在处理海量数据时感到力不从心?是否在重复编写相似代码时感到厌烦?如果是,那么Databricks中的自定义函数可能就是你一直在寻找的救星。在接下来的5分钟里,让我们一起探索如何利用这个强大的工具来revolutionize你的大数据开发工作流程。 目录 为什么要在Databrick…...

VMware vSphere Client无法访问和连接ESXi虚拟主机解决思路

文章目录 前言1. 问题现象2. 问题原因3. 解决方法4. 参考文章 前言 注意 : 可以先看看参考文章那里&#xff0c;在回过来看 1 、 2 、3 1. 问题现象 版本&#xff1a;VMware vCenter Server 5.5.0 build-2442329 问题描述&#xff1a;用VMware vSphere Client 登录ESXI主机出…...

实现Kruskal算法连通游戏地图地牢

前置知识 c分享&#xff5c;并查集从入门到出门 - 力扣&#xff08;LeetCode&#xff09; 彻底搞懂克鲁斯卡尔&#xff08;Kruskal&#xff09;算法&#xff08;附C代码实现&#xff09; - QuanHa - 博客园 (cnblogs.com) 白色点矩形是地牢&#xff0c;其中白线是按照krsukal…...

turtle画图知识

Turtle库是Python编程语言中的一个库&#xff0c;用于创建各种类型的图形&#xff0c;包括简单圆形、线条、路径和图片。它支持多种图形类型&#xff0c;并且可以绘制出各种复杂的形状。 以下是一些基本的使用方法&#xff1a; 1. 创建一个新的Turtle对象&#xff1a; pytho…...

Elasticsearch简述

Elasticsearch简述 Elasticsearch产品介绍 Elasticsearch是一个基于Apache Lucene的开源的分布式搜索和分析引擎,设计用于云计算中,能够快速处理大量数据。它能够近实时地进行复杂的查询,并且可以用于全文检索、结构化搜索以及分析。Elasticsearch具有以下特性: 分布式搜索…...

SQL— DDL语句学习【后端 9】

SQL— DDL语句学习 在数据管理的广阔领域中&#xff0c;SQL&#xff08;Structured Query Language&#xff09;作为操作关系型数据库的编程语言&#xff0c;扮演着举足轻重的角色。它不仅定义了操作所有关系型数据库的统一标准&#xff0c;还为我们提供了强大的工具来管理、查…...

线程池介绍

1.线程池简介 import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; public class CallableDemo {public sta…...

如何备份电脑所有数据?有哪些方法值得参考借鉴?

备份电脑所有数据是防护数据丢失和泄密的重要一项措施&#xff0c;备份数据也有不同的方式和工具&#xff0c;正确的工具能帮你省时省力&#xff0c;下面盘点了几个方法&#xff0c;来看哪一种最适合你。 一、使用专业备份软件 第三方服务器文件自动备份软件&#xff1a;如安企…...

初识--树(1)

下面就是这篇博客要讲的内容 树 二叉树堆 树概念及结构二叉树的概念及结构二叉树的实现堆的概念及运用 这篇博客主要以二叉树为主要内容。 1、树的概念及结构 1.1树的概念&#xff1a; 树是一种非线性的数据结构&#xff0c;它是由n&#xff08;n>0&#xff09;个有限…...

渗透测试实战-菠菜站渗透测试(Nacos反序列化漏洞利用)

免责声明&#xff1a;文章来源于真实渗透测试&#xff0c;已获得授权&#xff0c;且关键信息已经打码处理&#xff0c;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本…...

Pytest框架直接右键运行 testcase.py,不执行最外层conftest

随笔记录 目录 1. 背景介绍 2. workaround method 2.1 通过命令行执行 某个测试用例 1. 背景介绍 Pytest 框架结构如下&#xff1a; TestCases:conftest.pyInstanta: conftest.pytest_instanta_tcpdump_pack_len.py# 当直接右键直接 运行 test_instanta_tcpdump_pack_l…...

Cxx primer-chap15-Object-Oriented Programming

面向对象编程的三个基本概念&#xff1a;数据抽象、继承和动态绑定&#xff08;多态&#xff09;&#xff1a;基类应该提供一些类型无关的成员函数定义&#xff0c;将与类相关的函数留给不同的派生类定义&#xff1a;&#xff0c;派生类是通过类派生列表(class derivation list…...

当黑神话遇上AI:悟空背后的策划逆袭战

声明&#xff1a;此篇为 ai123.cn 原创文章&#xff0c;转载请标明出处链接&#xff1a;https://ai123.cn/2192.html 哈喽&#xff0c;亲爱的游戏迷&#xff0c;随着《黑神话&#xff1a;悟空》的上线&#xff0c;大家都在忙着“直面天命”了吧&#xff1f;今天我想和大家分享最…...

外呼触发通知发送闪信(mod_cti基于FreeSWITCH)

文章目录 前言联系我们手动外呼配置方法例子一&#xff1a;接收到180或183时触发闪信发送例子二&#xff1a;挂断后触发闪信发送 自动外呼配置方法例子&#xff1a;接收到180或183时触发闪信发送 前言 在呼叫中心中间件中&#xff0c;自动外呼触发闪信发送&#xff0c;我们可以…...

8.Java基础概念-方法

欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 Facts speak louder than words&#xff01; 什么是方法 方法是程序…...

360安全浏览器如何彻底卸载

360安全浏览器是一款广泛使用的网络浏览工具&#xff0c;然而由于各种原因&#xff0c;用户可能需要将其从计算机中彻底移除。下面小编就给大家分享几种彻底卸载360安全浏览器的方法&#xff0c;避免留下影响系统性能的残留信息。&#xff08;本文由https://chrome.cmrrs.com/站…...

构建基于LLM的应用程序——使用LLM的搜索和推荐引擎

在上一章中&#xff0c;我们介绍了构建对话应用程序的核心步骤。我们从一个基础的聊天机器人开始&#xff0c;然后逐步添加了更复杂的组件&#xff0c;例如记忆、非参数化知识和外部工具。借助LangChain的预构建组件以及Streamlit的UI渲染&#xff0c;这一切都变得相对简单。尽…...

Unity3D 模型碰撞检测问题详解

前言 在Unity3D游戏开发中&#xff0c;模型碰撞检测是至关重要的一环&#xff0c;它负责处理物体之间的交互、触发事件以及物理效果的实现。通过精确的碰撞检测&#xff0c;游戏世界得以呈现出更为真实和动态的交互体验。本文将详细介绍Unity3D中的碰撞检测原理、技术实现以及…...

springcloud集成seata实现分布式事务

Seata 是一款开源的分布式事务解决方案&#xff0c;致力于在微服务架构下提供高性能和简单易用的分布式事务服务。 官网&#xff1a;Apache Seata 文章目录 一、部署1.下载2.修改配置&#xff0c;nacos作注册中心&#xff0c;db存储 二、集成到springcloud项目1.引入依赖2.修改…...

[Leetcode 61][Medium]-旋转链表

目录 一、题目描述 二、整体思路 三、代码 一、题目描述 原题链接 二、整体思路 首先发现这样的规律&#xff1a;当k大于等于链表中节点总数n时&#xff0c;会发现此时旋转后的链表和kk%n时的旋转后的链表一样。同时对于特殊情况n0和n1时&#xff0c;无论k的值为多少都可以…...

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道&#xff08;多模态 OCR → 语义检索 → 答案渲染&#xff09;、两级检索&#xff08;倒排 BM25 向量 HNSW&#xff09;并以大语言模型兜底”的整体框架&#xff1a; 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后&#xff0c;分别用…...

C++初阶-list的底层

目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...

CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型

CVPR 2025 | MIMO&#xff1a;支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题&#xff1a;MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者&#xff1a;Yanyuan Chen, Dexuan Xu, Yu Hu…...

HTML 列表、表格、表单

1 列表标签 作用&#xff1a;布局内容排列整齐的区域 列表分类&#xff1a;无序列表、有序列表、定义列表。 例如&#xff1a; 1.1 无序列表 标签&#xff1a;ul 嵌套 li&#xff0c;ul是无序列表&#xff0c;li是列表条目。 注意事项&#xff1a; ul 标签里面只能包裹 li…...

Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; &#x1f680; AI篇持续更新中&#xff01;&#xff08;长期更新&#xff09; 目前2025年06月05日更新到&#xff1a; AI炼丹日志-28 - Aud…...

【Go】3、Go语言进阶与依赖管理

前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课&#xff0c;做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程&#xff0c;它的核心机制是 Goroutine 协程、Channel 通道&#xff0c;并基于CSP&#xff08;Communicating Sequential Processes&#xff0…...

css的定位(position)详解:相对定位 绝对定位 固定定位

在 CSS 中&#xff0c;元素的定位通过 position 属性控制&#xff0c;共有 5 种定位模式&#xff1a;static&#xff08;静态定位&#xff09;、relative&#xff08;相对定位&#xff09;、absolute&#xff08;绝对定位&#xff09;、fixed&#xff08;固定定位&#xff09;和…...

Spring Boot+Neo4j知识图谱实战:3步搭建智能关系网络!

一、引言 在数据驱动的背景下&#xff0c;知识图谱凭借其高效的信息组织能力&#xff0c;正逐步成为各行业应用的关键技术。本文聚焦 Spring Boot与Neo4j图数据库的技术结合&#xff0c;探讨知识图谱开发的实现细节&#xff0c;帮助读者掌握该技术栈在实际项目中的落地方法。 …...

ardupilot 开发环境eclipse 中import 缺少C++

目录 文章目录 目录摘要1.修复过程摘要 本节主要解决ardupilot 开发环境eclipse 中import 缺少C++,无法导入ardupilot代码,会引起查看不方便的问题。如下图所示 1.修复过程 0.安装ubuntu 软件中自带的eclipse 1.打开eclipse—Help—install new software 2.在 Work with中…...

【python异步多线程】异步多线程爬虫代码示例

claude生成的python多线程、异步代码示例&#xff0c;模拟20个网页的爬取&#xff0c;每个网页假设要0.5-2秒完成。 代码 Python多线程爬虫教程 核心概念 多线程&#xff1a;允许程序同时执行多个任务&#xff0c;提高IO密集型任务&#xff08;如网络请求&#xff09;的效率…...