心法利器
本栏目主要和大家一起讨论近期自己学习的心得和体会。具体介绍:仓颉专项:飞机大炮我都会,利器心法我还有。
2024年新的文章合集已经发布,获取方式看这里:再添近20万字-CS的陋室2024年文章合集更新,更有历史文章合集,欢迎下载。
往期回顾
- 心法利器[128] | 2024年算法小结-个人成长-打开思路-生日
- 心法利器[129] | deepseek-R1自测效果分析和选择建议
- 心法利器[130] | RAG效果调优经验
- 心法利器[131] | 盘点踩过大模型多轮对话的坑
- 心法利器[132] | 大模型系统性能优化trick
在很久以前,我曾经写过一篇文章:心法利器[47] | 为什么我的BERT不行?,那会的版本热门就是Bert系列相关模型,声名远扬但很多人用起来总感觉名不副实。最近的大模型用起来,也有不少人会反馈类似的问题,今天来和大家一起讨论一下大模型效果不好的原因和对应解决方案吧。
在开始之前,还是先提一下我这个系列文章:(心法利器[37-40,115] | bad case治疗术:合集),很多所谓的效果不好都有迹可循,还是希望大家尝试这个流程,发现并解决问题,从根本上解决自己只会换模型、改prompt之类的困境。
我把问题分为几个部分来进行讲解,也是希望借此希望和大家分享我自己的问题解决思路。
- 老生常谈的非模型问题
- 端到端的局限性
- 并非大模型的优势领域
- 数学计算
- 成熟系统下收益受限
- 信息更新能力
- 打开方式的问题
- 只考虑单兵作战
- 无脑扔进大模型
- 完全信任大模型输出
- 没有预留“替代品”
- 其他问题
- 模型和代码层面的问题
- 怀疑大模型的自身能力
- 需要树立的思想
- 小结
老生常谈的非模型问题
在很多情况下,尤其是初期的项目,往往会有很多数据层面甚至是问题定义层面的问题,这些问题会导致无论是什么模型都很难把事情解决。
首先是问题的定义层面,我列举几个问题并给一些例子,方便大家理解。
- 问题的定义是否清晰,类似“帮我总结一下会议内容”,如果是开放域那这么说也没毛病,但有些潜在的要求,如需要重点提取某些内容,如会议主题、谁提了什么关键内容、后续谁跟进等。如果不明确指出,则做出来很可能不符合预期,这不仅是大模型,哪怕是人之间都不一定能有统一的理解。
- 业务问题的边界界定。为了更好的处理问题,我们通常会把问题拆解分配,分属很多模块负责,但很多时候边界就是模糊的,甚至可能要多个模块分别处理才能完成的,最近听说的一个场景,某个文物展品,该归属那个博物馆之类的部门,这些条条框框非常多,仍旧难以划分,这便是边界模糊。
- 问题对“正确”和“错误”的理解。仍旧是上面这个问题“会议内容”,要求必须提出来的是哪些,需要以什么格式返回,这些都是要求,如果不按照类似的格式或者要求,则被认为是错误,这个是需要明确定义好的。
- 效果好坏的定义。在对正确错误有明确定义后,最终需要出一个可观测对比的指标,在一定量的数据下,准确率(当然可以是别的指标)达到XX则认为是可以上线的,多少叫做好多少叫做不好,都需要定义,坚决杜绝测了几个脑子里想象的例子就说好坏的情况。有些时候,我们得到的所谓“效果不好”的结论,很可能是错的,是因为评价指标、好坏的定义出现问题,我们的测定不科学,那得到的结论就会出错。
然后是数据层面,先说测试集,测试集的好坏直接影响我们对问题解决情况判断的准确性(没看错,我们是可能会对此存在误判的),因此合理的测试集非常重要。
- 标注质量。运气好我们可能会有标注数据,此时我们应该仔细验证这个标注的质量,有没有标错(不要以为人工标注就一定都对,例如可能会因为问题定义层面的模糊、人为懈怠、人工知识水平不足等原因出现错误),有没有不符合预期的标注(如数据转化格式错误)等,需要仔细验证。
- 数据分布。要注意,尽量让数据集的分布符合 实际应用 或者 测试目标场景 下的分布。举例,为了想要突破难题,所以准备了很多难题放到测试集,但实际场景并无这么多难题,更多是简单题,此时测出来难题好并不代表这个方案就可以使用,类似最近的deepseekR1这样的深度思考模型是很可能难题解决不错而简单题翻车的。
- 数据量。前文有提到“坚决杜绝测了几个脑子里想的例子就说好坏的情况”,数据量要足,哪怕人力不足或者问题困难,也得准备至少50条以上的数据,这样准确率之类的指标才可靠。
紧接着是训练集,大模型的微调、in-context learning之类的都是需要训练集的,然而训练集不好,模型自然容易训歪,相信有过训练经历的大家都应该理解。
- 数据质量和数据量的问题,不赘述了,和上面的类似,但大家记得要校验。
- 数据分布,训练集往往是结果导向,某些问题下的数据不足(模型没学会)自然是需要补充的,确保模型有足够的数据可以学会,而不需要拘泥于和测试集保持一致,我们可以结合测试集的效果情况做特定的降采样或者增强。
最后是输入和输出的关联性,这点要重点说出来,我发现这点大模型出来后发生的频率有提升的趋势,大概率是出于对大模型的信任吧。很多问题的解决需要依赖足够的信息支撑,大模型虽说有很强的“世界知识”,但并非所有信息都能从这个“世界知识”中获取,我举一些例子。
- 例如推荐系统里的点击率预估,用户的点击行为、偏好是千人前面的。
- 私域知识,即外界人不知道的信息,某些机密,某个公司、部门的领导是谁,部门有多少人之类的问题。
- 更新速度快的知识,天气、新闻等。
- 通话摘要、意图识别、实体抽取等,需要根据给定内容来做判断的。
- 某些决策下的关键信息,例如股票的预测对应公司、行业甚至相关政策的背景信息。
这些内容,只要信息没给够,什么模型都没法得到非常突出的效果,哪怕让人来都不行,如果还想看更详细的分析,可以考虑看看这篇文章(心法利器[45] | 模型需要的信息提供够了吗)。
再次强调,这些非模型的问题,在很多时候反而制约了模型的发挥,在真正开始做模型的训练之前,就要开始留意这些问题,而且在后续的迭代优化里,也不能掉以轻心。
端到端的局限性
这点绝对值得单独拿出来讲,大家在使用过程中,会出现两个情况,这两个情况下,大模型的压力都会很大,效果出现下降。
- 把一个复杂任务交给大模型,然后一次性解决。无论是输入还是输出的内容变多,都会令大模型的输出骤然下降,从模型原理上看,attention结构要求从整句中找到重点去关注,输入句子长重点多则会让句子信息被稀释(极端地想,句子2个重点,那就是1/2,10个重点,那就是1/10),如此而言难度骤升,效果也会不好了。
- 往一个大模型堆砌很多不同的任务,对于prompt可能上限会比较受限,而对微调则在任务变多时难以兼顾,迭代期间原有的任务效果还可能被严重影响。
这两个情况,我想把原因归结在端到端模型的局限性上。
对复杂一次性解决这个事,其核心点在“复杂”上,复杂的问题的考量点和分析点众多,还可能依赖很多外部信息,简单地prompt描述或者微调训练很难体现,上限更高的方案,往往是把任务拆解成多步来解决,这里提供几种可行的思路。
- 如果任务比较固定,步骤也比较明确可枚举,则可以人工拆分,分多步、分多个模块来解决,每个子任务可以考虑不同方案,当然,大模型也可以考虑。
- 大模型自动化拆分,也是分多步多模块,不过需要注意的是,大模型的拆分,或者说planning,注意也要充分评估好最终的准确情况(按照我自己的经验,在线的拆解往往准确率比较尴尬,主要是和实际业务需要会存在差距,注意严格把控)。有关拆分这事,可以是离线用作参考,在线推理只考虑按着步骤执行,也可以是在线直接一案一拆。
一个模型完成很多任务,是很多技术人所追求的一种浪漫,但在实践过程中这种浪漫可能会制约实际高优先级的任务的效果,可能会有如下几个情况。
- 微调影响原有大模型的对话能力,出现幻觉、重复之类的问题。
- 持续增加任务,微调同一个模型,会影响原有任务的效果,而且新的任务也可能出现“训不动”、“效果差”的原因。
比较简单的sft往往很容易出现上面的情况,如果是一两个任务其实还好,多了以后上面的情况就会出现的比较多了,我们可以考虑如下几个解决思路。
- 最直接的,用不同的微调大模型,例如任务A/B比较接近,微调一个大模型X,任务C/D则微调一个大模型Y,各自完成各自的任务,X和Y可以考虑用比较小的模型,例如7B这个级别的,相比微调32B,其实成本还是下降了,而且微调下效果差距不会很明显,不过还是有问题,大模型的数量会比较多。
- 如果还要压成本,可使用轻量化微调方案,例如lora系列,每个任务使用一个lora,配合部署引擎可以轻松进行任务拓展,不同的任务执行执行不同的lora组件。
- 有些不叫简单的任务,例如分类、向量召回、实体抽取啥的,完全可以用效果较好的大模型做预标注来训练bert级别甚至更小的模型来完成,成本和灵活性都很高,小模型每个只完成一个任务,各自也不会互相影响。
并非大模型的优势领域
很多时候,大模型的效果不好,很可能只是因为,大模型在这些方面本身就做得并不是很好,那就不能对他有大的期待,效果自然不也会很好,也比不过该领域本身就有的模型,或者可以考虑配合其他的模块,让大模型做他擅长的事,不擅长的位置交给擅长的来做。
数学计算
24年以来,各种模型都有在数学计算上做优化,已经少了很多之前23年所提的数值错误、数据错位的问题,在计算方法、公式比较明确的场景下,质量还挺高,还是会有如下的现象:
- 在公式明确的场景,本来直接计算就完事了,根本不会出错,非要用大模型的话,准确率反而难保100%,花了时间做了事还会出错,除了“大模型”的噱头没别的收益。
- 对于数字类型的特征处理和理解,会比较困惑,类似价格、金额、年龄、次数、体重,经常会存在误读甚至会忽略数字,对数字本身的大小没有概念。
- 直接进行微调训练,收益好像没有经典的LSTM之类的结构有效。
我的理解还是,LLM自己本身还是对文本处理的模型,数学计算属于能用但如果有更好的方案,并不建议投入过多,没必要强人所难了。
成熟系统下收益受限
大模型诚然有很多优势,但在一些情况下,大模型的优势并不能很好地体现出来。在一些场景下的效果对比中,很多人会发现新的大模型并没有原有的方案效果好,没有体现出大模型“该有的优势”,对不少人而言,这是非常意外的。
以推荐系统为例,我和好几个做推荐系统的朋友有过交流,也在各种平台上看到很多人的讨论,会发现对大模型在推荐系统的使用效果评价还跟不一致,有的人认为效果不好,有的人则认为效果还不错,经过分析后,我理解到了实际原因。
- 对于已经比较成熟的推荐系统而言,各种信息处理的都比较好,此时再用大模型,收益就很不明显甚至会有负向。
- 对偏新的推荐系统,各种信息都很缺乏,用户行为也不多,此时借助大模型的“常识”,总能得到一些收益。
我曾经讨论过王喆老师的一个比较总结性的观点(心法利器[122] | 效果提升的根本来源讨论),效果提升的两个核心原因,新的有效信息和更好的信息处理模式,和上述的现象也是非常匹配的。大模型的优势在于能基于给定的信息,给出基于他自己的学习推导出来的内容,因为现在大模型的推理能力基本都不弱,因此推理出来的内容多半都是“有道理”的,这些“有道理”的信息,往往为比较早期的项目提供很好的意见支撑,效果提升则非常明显,然而对于比较成熟的推荐系统而言,各种物料的信息比较完善,借助用户行为也有很好的用户偏好表征,甚至按照日期统计,有实时、短中长期的偏好,而且实验了大量的模型,最终收敛到了很好地效果,此时再用大模型介入,效果收益就很小了,甚至,大模型自己的常识可能不完全适用于当下场景,会得到负向的效果。
基于这个说法,我们可以再换一些场景,以我自己比较擅长的意图识别为例,上个版本的主流方案就是用bert来做,通过标注之类的方式获取大量标注数据,通过训练达到可用甚至是优秀的效果,此时想用大模型来做对比,可能会有如下情况。
- prompt方案。
- prompt写下来,类目过多不好写进prompt里,多了效果反而不好。
- 简单的意图概念,模型理解的好像会有偏差,和实际预期有差别。
- 总体效果大概率比不过微调的小模型。
- 微调。
- 类目确实可以做得更多,效果相比prompt应该有比较明显的提升。(如果没提升,很可能数据层面有问题)
- 从结果来看,可能效果相比微调的小模型提升不明显,甚至可能略低。
这种情况很可能就是因为,目前的小模型已经足够处理现有的任务,大模型自身的优势在这里的收益并不是很好。
需要补充说的是,并非说大模型在这个任务或者场景就“效果不好”,毕竟在从无到有或者是早期的项目下,基础工作比较少,此时大模型配合prompt很大概率能获得收益,而是说,在一些发展比较完善的场景,大模型的应用并不一定就可以获得提升,我们能有这样的预期和理解。
信息更新能力
这不仅是大模型的劣势,而是各种需要经过训练模型的劣势。随着业务迭代、信息更新,大模型肯定是需要更新的,对大功能、新功能级别的大更新,我们可以通过微调、调整prompt之类的模式来更新,但是如果是一两条说法,一两个bad case,次数比较频繁,显然微调模型的性价比低,敏捷度也不足,prompt也无法做很细节的雕刻,但是这类似的问题是数据库的优势,通过类似RAG之类的方式能快速解决这个问题,只要这个问题不解决,RAG类似的技术应该都不至于被淘汰。
打开方式的问题
很多时候,我们没有取得预期的效果,很可能是因为我们的使用方式不对。
只考虑单兵作战
很多时候,让我们用大模型,我们就是很粗暴地,把输入扔给大模型,然后祈祷他能按我们的预期来输出,结果发现并没有什么效果。举个例子,我们考虑用大模型做ctr预估,直接那个qwen2.5之类的模型做,效果不好。
此时,我们考虑配合,和原有的模型做个配合,说不定会有奇效。继续上面的例子,我们不直接输出ctr,而是让大模型给出一个建议,把这个建议放到原有的ctr预估模型里,说不定就有效果。
无脑扔进大模型
在一些场景,无脑把所有东西都扔进大模型,可能会有各种风险,不合法的、高频的、简单的、易错的,全都通过大模型自己的能力,借助prompt和微调来处理,可以说是非常费心了,此时,很多问题,我们可能不需要都扔进大模型里,我们可以做前处理完成。
- 对于不合法的,输出结果内容不可控的,我们可以提前做卡控,例如黄反擦边的,提前拒识并做好兜底回复。
- 高频和简单的,很多模型反而容易翻车,为了确保在线不出问题,提前做好回复,甚至审核好,存数据库里,缓存好,是个比较安全的方案。
- 易错的,也可以和不合法内容类似,先卡控拒识,等后续解决了再重新打开。
完全信任大模型输出
很多时候大模型总会不可控地输出一些我们意料之外的(例如和人骂起来了)或者是不合法的(例如没按要求的json格式输出)内容,我们并不好控制,此时我们还是需要做好后处理和校验,对不合法的内容及时卡控(我看deepseek就有,在思考过程有输出敏感词,就直接把整个答案屏蔽),或者是加一层后处理进行修复来完成。
没有预留“替代品”
提取类任务我做的比较多,很多时候会发现模型会提取一些不在原文中的内容,即使约束了“如果没有则不提取”,可能效果收益也不是很大,这点我自己理解是在模型训练过程没有学习到在“无”的处理方式,这点和我们人在考试时的行为类似,大题不会多少也会编点东西在卷子上,典型的例子是作文,小学生39.5度爸妈抱着我跑去医院的经典作文,而对于选题,即使自己算的4个选项都不对,也会猜一个。
这类型问题的解决方案是,为模型,提供一个,在没提取到或者是置信度不足的时候,可以选择的答案,例如,“如果原文中没有没有提到作者名称,则作者字段写'无'”,或者是“原文未提及作者”,而不是不提取,此时会好很多,如果不需要这种“无”的字段,后处理删掉就好了。
这种情况其实并不罕见,文本分类之前也遇到过,对于一些拿不准的case,或者是类目体系并非覆盖的case,模型会倾向于把他都扔套特定一个类目里去,导致这个类目的效果异常低,比较好的解决方案就是构造一个other类,让模型把拿不准的和类目体系并没覆盖的内容都扔里面就完事了,最好在卡个阈值。
因此,很多时候,我们需要考虑给模型一个“替代品”,在意外、拿不准的情况下有解决方案。当然了,如果是训练,还是要尽量考虑训练好,否则模型容易出现惰性,都扔这个替代品里面了。
其他问题
模型和代码层面的问题
这个在之前那个bert效果不好的篇章里(心法利器[47] | 为什么我的BERT不行?)有提到,但是在这里我却没作为重点,核心原因是目前大模型的版本下,很多人微调基本都用框架去玩了,llama_factory之类的工具基本就是配置化就完事了,能主动去改模型结构,改训练策略啥的,真的凤毛麟角,真要写代码,大模型也能写,逻辑错误已经非常稀少了。
当然,我个人还是推荐大家可以自己去尝试写写看看,通用的是最快的,但定制的才是最合适的,推荐系统发展至今,虽说沉淀了大量经典的模型,但在实际场景大家还是很愿意自己动手去优化模型结构,能达到最优的效果,因此还挺推荐大家自己玩一玩的,配合大模型下很多自己的想法实现起来其实并不会很慢。
怀疑大模型的自身能力
怀疑大模型自身能力这点并没有太大毛病,在早期大模型选型的时候就应该选比较靠谱,例如这个时间点下我就会考虑qwen2.5和deepseekR1的各种size(qwen3用起来感觉不如qwen2.5实用),此时发现大模型的短板后,其实就不要考虑是千问或者是ds的问题了,而要考虑是不是大模型这个技术路线问题即可,市面上最好的产品都满足不了需求那就不是产品本身的问题而是这类型产品的通病了,此时要做的是更换产品类型而不是纠结于产品本身,就像锤子切菜就是不合适。
需要树立的思想
最后列举几个需要树立的思想,方便大家尽快走出误区快速解决问题。
- 认清大模型的作用边界,避免盲目信任大模型。大模型有自己的优势领域和劣势领域,也有很多让他表现不佳的原因,不要觉得用了大模型效果就会变好,他是技术,不是法术。
- 从“效果不好”这四个字中解脱出来,这和写代码说“报错”是一样的,仔细分析报的什么错,耐心从数据等途径探究问题根源,配合有关的论文和实践经验定位问题,从而找到合适的解决方案。
- 平时就要重积累,重观察,重记录,医生之所以能治病,是因为了解多种治疗手段,能对症下药,如果见识不足,手里能拿得出来的方案就少,自然容易无从下手。
- 从模型思维转变为系统思维。一个问题的解决,是可以通过多个模块共同完成的,学会拆解问题,分工合作,不要局限在一个模型完成全部事情的定式里。
小结
适逢劳动节假期,我想打算总结一些大模型相关任务的调优trick,然而比较零散很多内容无法串起来,正好前段时间后台有过提问,很多时候大模型的应用不及预期,越做越感觉大模型盛名之下其实难符,信心不足了,我便选择了这个方式来总结,帮助大家更好的理解问题并解决问题,希望对大家有用吧。
另外,有什么可以补充的技巧,也可以在评论区补充,互相讨论。