踩坑
最近在倒腾多模态相关的东西,主要是尝试用MMLM-多模态语言模型做一些Visual Grounding(视觉定位)的任务。
模型方面毋庸置疑选用的是目前最能打的Qwen2.5-VL系列,然而我在进行SFT实验的时候却绝望地发现:无论用多么高质量的数据集,或者多么花式地炼丹,最后得到的效果里bbox(bounding box)都会出现不同程度的漂移
。
我也是经过多番周折才解决了这个「大坑」问题。鉴于当时在github issue里留了微信之后有许多加好友前来咨询的朋友,因此觉得有必要写篇文章详细分享一下的「爬坑」之路。
觉得过程太啰嗦的朋友可以直接跳到后半段查看解决方案。
一开始在SFT之后,我用checkpoint进行预测的效果大概是下面这样(我的任务比较特殊,严格来说是版式识别,不过本质也是Grounding):
排除是自己的数据问题的可能性,同时也不太会是模型缺陷(毕竟官方也明确放话自己是支持Grounding任务的),那首先能想到的就是去GitHub上求助了。
果不其然,仅仅只是搜「shift」这个关键词就能发现大把类似的issues:
当时我挨个看了一圈,没有一个是问题得到完美解决了的。
尝试向里面几个有相同经验的网友留言也石沉大海,最后实属无奈只好自己也发了个Issue[1]。
亏得Qwen2.5-VL社区的大佬们百忙之中抽空答复了我几次,一来一回地终于把问题给解决了。
这里我主要总结一下症结所在,以及我最终的解决方案,以供大家参考。
爬坑实录
第一个潜在问题来自transformers库本身的bug,我最开始是从这个issue[2]里获取到这个信息的。
有遇到相同问题的网友通过更新transformers库到最新的commit就解决了问题,
我大致查看过这个commit里的更改,主要涉及的是QwenVL模型Processor内部一些if else逻辑的调整,但细节方面我也没有太过深究,感兴趣的朋友可以自行探索一下。
于是我效仿这个方案做了测试,发现漂移情况有了显著的改善,不过至少在我的任务里仍然存在。
根据目前的信息看来transformers的版本需要更新到至少4.51.0或之后。
第二个潜在问题来自训练框架LLaMA-Factory[3],这里要格外感谢QwenVL团队大佬的赐教[4]。关于这个问题我打算详细叙述一下。
一切的根源其实来自「resizing」
熟悉现在主流MMLM的朋友应该知道,为了实现动态分辨率,模型的ViT部分会对于传入的图片进行resize(详细原理请参考技术报告或者网上的技术博客解读)。
对于绝大多数多模态的任务而言这个处理不会造成什么负面影响,然而对于需要通过生成方式输出bbox坐标的grounding任务来说可就不一样了。
因为SFT过程中,模型是在resize之后的图片输入基于给出的ground truth里的坐标进行学习的,所以如果训练数据二者没有百分百适配,就会导致类似上面这种「漂移」的出现。
因此正确的数据预处理逻辑应该是:
- \1. 对于训练数据中的图片统一进行预resize的处理,得到会实际输入模型进行处理的input_width和input_height(注意这里其实并没有真正resize图片,而是通过一个函数计算出了需要resize到的尺寸而已,当然也没有必要实际resize图片+保存)
- \2. 将原训练数据里的输出坐标进行调整,转换成相对上面得到input_width/input_height下的绝对坐标
举个例子👇:
假设原始输入图片的尺寸是1000x2000(height*width),其中一个检测对象(比如小汽车)的bbox框用xyxy体系表示是**[100, 200, 300, 400]**。
而经过qwenvl的resize逻辑之后的尺寸是616x1260(height_new*width_new,这里的具体逻辑稍后再说明),那么这条喂给模型的数据里的小汽车bbox坐标就需要从原先在1000x2000上的绝对坐标转换成在616x1260的绝对坐标。
scale_x = width_new / width =1260/2000=0.630
scale_y = height_new / height =616/1000=0.616
x1, y1, x2, y2 = bbox
new_x1 =round(x1 * scale_x)=63
new_y1 =round(y1 * scale_y)=123
new_x2 =round(x2 * scale_x)=189
new_y2 =round(y2 * scale_y)= 246
我们将得到的这个新坐标作为这个bbox的真值传入模型,才是与图片特征相匹配的ground truth label。
其实这一步我在数据预处理时候是有认真按照这个逻辑处理的,但结果还是出现了巨大漂移,除了可能有transformers库版本的原因之外,一个更潜在的风险就是上面Issue里QwenVL社区大佬回复我的那个:
LLaMA-Factory框架出于未知的原因采用了自己的一套resize实现逻辑,而这就很有可能与QwenVL自己的逻辑有一定的出入,最后造成的局面就是:我们的label严格按照QwenVL的逻辑修正了坐标,而数据进入模型的时候却在训练框架这里进行了不符合预期的预处理,与我们修正后的坐标依然存在不匹配。
知道了问题所在,解决方案也很简单,要么和框架保持一致来重新预处理数据,要么让框架使用和预处理时相同的逻辑。
由于重做数据预处理还是挺费时间的,因此我遵照大佬的建议采取了后者。
调整方法我也已经在Issue里贴上了,这里再放一遍,需要修改的是LLaMA-Factory/src/llamafactory/data/mm_plugin.py[5]:
import qwen_vl_utils
from typing importSequence,List
qwen_vl_utils.vision_process.MIN_PIXELS =512*28*28
qwen_vl_utils.vision_process.MAX_PIXELS =1024*28*28
@dataclass
classQwen2VLPlugin(BasePlugin):
@override
def_regularize_images(
self, images:Sequence["ImageInput"],**kwargs
)->List["ImageObject"]:
r"""
Regularizes images to avoid error. Including reading and pre-processing.
"""
results =[]
for image in images:
ifisinstance(image,(str,BinaryIO)):
image =Image.open(image)
elifisinstance(image,bytes):
image =Image.open(BytesIO(image))
elifisinstance(image,dict):
if image["bytes"]isnotNone:
image =Image.open(BytesIO(image["bytes"]))
else:
image =Image.open(image["path"])
ifnotisinstance(image,ImageObject):
raiseValueError(
f"Expect input is a list of images, but got {type(image)}."
)
ele ={"image": image}
sampled_image = qwen_vl_utils.fetch_image(ele)
if sampled_image.mode !="RGB":
sampled_image = sampled_image.convert("RGB")
results.append(sampled_image)
return{"images": results}
加上这个调整之后,我主观感受上模型在相同训练时长上的checkpoint效果有了进一步提升(在更新transformers库的基础之上)。
一些小细节
我这里最后提几个我感觉需要注意的细节点:
-
\1. 采用和QwenVL官方提供的resize逻辑时要注意MIN_PIXELS和MAX_PIXELS这两个参数,分别代表了resize图片时的最小和最大分辨率;而由于Qwen2.5-VL的里ViT的实现逻辑,这两个值最好设置成28的倍数,例如上面代码里的:
qwen_vl_utils.vision_process.MIN_PIXELS = 512 * 28 * 28 qwen_vl_utils.vision_process.MAX_PIXELS = 1024 * 28 * 28
-
\2. 推理阶段对processor初始化的时候,也一定要记得将上述两个参数传递(或者修改processor的config文件):
processor = AutoProcessor.from_pretrained( model_path, n_pixels=MIN_PIXELS, max_pixels=MAX_PIXELS )
否则依然会由于采用了默认的值而使得图像处理逻辑与预测结果不匹配的情况。
-
\3. Grounding任务大家一般都会直接在图片上绘制bbox来直观地查看效果,在原图上绘制的话请务必记得将模型预测结果里的bbox坐标「resize back」到原图尺寸下的绝对坐标,或者也可以在resize后的图片上绘制。可别因为这个导致画图画得不对,对原本训练得没问题的模型产生效果怀疑。
如何学习AI大模型 ?
“最先掌握AI的人,将会比较晚掌握AI的人有竞争优势”。
这句话,放在计算机、互联网、移动互联网的开局时期,都是一样的道理。
我在一线互联网企业工作十余年里,指导过不少同行后辈。帮助很多人得到了学习和成长。
我意识到有很多经验和知识值得分享给大家,故此将并将重要的AI大模型资料包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。【保证100%免费】🆓
CSDN粉丝独家福利
这份完整版的 AI 大模型学习资料已经上传CSDN,朋友们如果需要可以扫描下方二维码&点击下方CSDN官方认证链接免费领取 【保证100%免费】
读者福利: 👉👉CSDN大礼包:《最新AI大模型学习资源包》免费分享 👈👈
对于0基础小白入门:
如果你是零基础小白,想快速入门大模型是可以考虑的。
一方面是学习时间相对较短,学习内容更全面更集中。
二方面是可以根据这些资料规划好学习计划和方向。
👉1.大模型入门学习思维导图👈
要学习一门新的技术,作为新手一定要先学习成长路线图,方向不对,努力白费。
对于从来没有接触过AI大模型的同学,我们帮你准备了详细的学习成长路线图&学习规划。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。(全套教程文末领取哈)
👉2.AGI大模型配套视频👈
很多朋友都不喜欢晦涩的文字,我也为大家准备了视频教程,每个章节都是当前板块的精华浓缩。
👉3.大模型实际应用报告合集👈
这套包含640份报告的合集,涵盖了AI大模型的理论研究、技术实现、行业应用等多个方面。无论您是科研人员、工程师,还是对AI大模型感兴趣的爱好者,这套报告合集都将为您提供宝贵的信息和启示。(全套教程文末领取哈)
👉4.大模型落地应用案例PPT👈
光学理论是没用的,要学会跟着一起做,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。(全套教程文末领取哈)
👉5.大模型经典学习电子书👈
随着人工智能技术的飞速发展,AI大模型已经成为了当今科技领域的一大热点。这些大型预训练模型,如GPT-3、BERT、XLNet等,以其强大的语言理解和生成能力,正在改变我们对人工智能的认识。 那以下这些PDF籍就是非常不错的学习资源。(全套教程文末领取哈)
👉6.大模型面试题&答案👈
截至目前大模型已经超过200个,在大模型纵横的时代,不仅大模型技术越来越卷,就连大模型相关的岗位和面试也开始越来越卷了。为了让大家更容易上车大模型算法赛道,我总结了大模型常考的面试题。(全套教程文末领取哈)
👉学会后的收获:👈
• 基于大模型全栈工程实现(前端、后端、产品经理、设计、数据分析等),通过这门课可获得不同能力;
• 能够利用大模型解决相关实际项目需求: 大数据时代,越来越多的企业和机构需要处理海量数据,利用大模型技术可以更好地处理这些数据,提高数据分析和决策的准确性。因此,掌握大模型应用开发技能,可以让程序员更好地应对实际项目需求;
• 基于大模型和企业数据AI应用开发,实现大模型理论、掌握GPU算力、硬件、LangChain开发框架和项目实战技能, 学会Fine-tuning垂直训练大模型(数据准备、数据蒸馏、大模型部署)一站式掌握;
• 能够完成时下热门大模型垂直领域模型训练能力,提高程序员的编码能力: 大模型应用开发需要掌握机器学习算法、深度学习
CSDN粉丝独家福利
这份完整版的 AI 大模型学习资料已经上传CSDN,朋友们如果需要可以扫描下方二维码&点击下方CSDN官方认证链接免费领取 【保证100%免费】
读者福利: 👉👉CSDN大礼包:《最新AI大模型学习资源包》免费分享 👈👈