大语言模型训练“参数”到底改怎么调???

模型的训练参数,到底应该怎么调?这应该是我听过最多的问题了,不如说。我最开始研究训练的时候也特别在乎参数到底应该怎么搭配?这样调是不是不够好?那样改是不是发挥不出模型本身的能力?这么多的参数都是什么意思?我有选择困难症,到底应该怎么做?

我在这里先直接说我的观点好了,调参是一个非常复杂的东西。但是确确实实是有效果的,只不过需要你有相当大的耐心,因为这个是和经验主义绑定的相当夸张的。我们调参的目的是激发你数据集里最大的潜力,就好比你本来可以考90分,但是你不会学,乱学一通。最后只考了70分。我们的目的就是通过调参。让模型无限接近最为优秀的分数。

调参就是需要实实在在上手的东西。就是因为不同参数之间的搭配太多了。实在太复杂了,所以基本没什么可以套的“模版”。即便有一个模版,但是换了另一种数据集,可能完完全全又是另一种调参方式了。

我想这是很多新入门的同学特别头疼的一件事。如果你也处于这种对参数无法理解,半懂不懂,甚至完全不了解的情况下,那么就由我带领你把“参数”这块内容给捋清楚吧。

我会首先介绍训练参数的各个含义,以及他们的使用方法。

首先,为了让大家可以实际用到我说的参数,我将直接基于llama-factory这个项目中基于它的界面介绍,且只讲关键的。

第一个:learning_rate

图片

一般简写为lr 

它是学习率的意思。这是一个很重要的超参数。可以直接影响你模型的最终效果。其中'e' 的意思是"10的次方"。

比如说:

5e5指的是:前面的5 乘以后面的 10 的 5 次方 ,也就是500000

这只是举例,我们不可能用5e5的学习率,所以我们会加上“-”负号

也就是5e-5 前面的5 乘以后面的 -10 的 5 次方 ,就是0.00005

为什么要这样计数呢?想象一下,如果一个数是 0.00000005,这样写很容易数错零对吧?但如果写成 5e-8,就简单多了。所以,'e' 就是个小技巧,也更省力。

那学习率有什么用呢?问的好!理论上来说,学习率越大,模型学的速度也就越快,但是学的不精。学习率越小,模型学的速度越慢。但是学的很精细。

为了让大家更好的理解,我来举一个例子。

学习率大:假设你想看一本关于模型训练的书。打算花一天的时间就看完。所以为了赶紧看完,你一目十行。基本不怎么思考。虽然看的快,但是也可能漏了很多关键信息和细节,没有太多的停留。最终可能你好像学会了,但是又好像没学到什么。甚至可能还会错误理解其中的一些内容。

优点:能快速了解书的大致内容,知道了整体大概框架。

缺点:可能错过重要细节,理解不深,记住的内容有限。

学习率小:这次换成你打算静下心来好好读模型训练书。所以打算花更长的时间学习。你准备花一个星期好好的研读。这期间你每天读一部分,然后细细评味其中的原理和实际的运用方法。这次你虽然花了很多的时间,但是你收获很大,远远比第一次学到了更为详细的内容。

这就是学习率小的情况

优点:能深入理解内容,记住更多细节,收获更多。

缺点:相对来说需要更长的时间,如果时间有限,可能无法完成整本书。

看完了上面的内容,你可能会说:学习率低的缺点好像可以接受啊!只要能学好我给它的数据,那慢一点又何妨呢?

对此,我想说 no no no 

如果真的那么简单那也不需要调整学习率了。

学习率很低的情况下,你的模型可能会收敛的非常非常的慢,慢到你甚至以为它根本就没有在训练。而且最致命的问题是,它可能会去“抠字眼”也就是说在某个地方会死脑筋,不会联系整个内容框架。一根筋的去研究每一段内容,甚至每一个字。如果你的数据集噪声很大,它甚至会去非常认真的去学习噪声。

所以这种情况很容易出现过拟合现象。也是学成书呆子了。这也是我们常说的模型陷入了局部最优的情况。(即在某一个区间找到了最优质的点。但是这个点在整个区间上并不是最优的。)

所以,一般来说,我们都是使用学习率调度器,例如:cosine

它会首先在你设定的学习率的初始值逐渐减小,也就是说。你的学习率并不是一直固定不变的。而是随着模型的不断学习一直在对应下降的。

这个在大多数的模型训练中已经是被默认选择了,是一个十分有效的策略。

个人经验:

虽然但是,理论是理论,实践是实践。我建议大家一开始使用比较小的学习率比较好,例如5e-5、4e-5 这种。然后看情况看模型效果,慢慢调高或者。特别是小数据集的朋友们,一开始不要用特别大的学习率。例如1e-4、2e-4这种的。总的来说,小一点的学习率确实比较好拟合。也有不错的效果。

第二个:num_train_epochs

图片

其中这个epoch直译是"轮、周期"的意思。整个 num_train_epochs 的含义就是“训练轮数”

其实指的就是在训练的时候,模型完整的在你的数据集上面完完整整学了一遍的意思。例如1个epoch指的就是模型它在你给它的数据集上训练了一轮。3个epoch就是完整的在数据集里训练了3轮。以此类推。

那我们要怎么判断到底要用多少epoch呢?实际上,这个没有一个固定的值。因为不同的数据最终目标不同、token量不同。模型也不同。这些等等都会有区别。但是。一般来说,数据集越少,所需要的epoch就越多。数据集越多,需要的epoch就越少。

所以我们一般不怎么看epoch。而是看loss的下降。只要保证loss下降到合适的区间,我们甚至可以手动停止训练。如果loss没有下降到合适区间,即便已经练完了,我们可能还是需要增大epoch。所以,epoch只是一个控制模型训练的时长工具。而决定模型最终对象是loss  这里不要搞错了。 

个人经验:

一般建议最好控制在10个epoch以内。尽可能在10个epoch里面将模型拟合到0.7~1.4范围的loss中

第三个:cutoff_len

图片

这个cutoff_len正如图片上显示的“截断长度”

顾名思义,意思就是你数据集里面,单条数据内容加起来超过了设定的1024这个长度,就会自动截断。它的单位是token (这个token你可以简单理解为一个汉字的意思)什么意思呢?

例如我说了一段话:

“今天我简单说两句,要说什么呢?其实也没什么,就是简单说一下,主要啊,就是这个啊。怎么说呢。就是懂得人自然懂,不懂的说了也不懂。啥也不说了,干一个!”

假设我把这个cutoff_len设定为10,那么也就是说超过了10个token就会被强行截断。如果你的数据集超过了。可能最终传给模型的就是这样的内容:

“今天我简单说两句,要说”

发现了吗?这段话被直接截断了。最终模型训练的就是这断了的数据。有的时候你发现训练完了,模型好像只说了一半的现象。这个时候建议去看看自己的数据集是否超过了这个截断的长度。是不是这里出的原因。

这个截断的长度可以自行手动调整,但是cutoff_len也直接影响训练的资源。也就是显存的占用,所以这个取决于你的数据集的平均长度。来设置一个合适的截断长度。

个人经验:

可以让chatgpt帮你写一个脚本计算数据集里面的平均每条的token量从而来设置截断长度。

第四个:per_device_train_batch_size

图片

这个就是批处理大小,意思就是在训练过程中,每个设备(你的GPU)一次处理的样本数量。如果你有一块GPU,batch_size调到16 那么就意味着你一块GPU一次处理16个样本(这里的样本指的就是你一条数据集)

同理,2块GPU batch_size16,每块GPU处理8个样本。

那么这个具体大了小了对模型有什么影响吗?那是必然的。

首先大的batch_sizer让GPU每次需要处理的样本更多,从而需要更多的显存资源。此外,泛化能力可能会略差,因为更新次数减少,模型可能容易过拟合。当然,好处也是有的,就是训练更为的稳定,从而更容易找到全局最优解。可以更快的收敛模型。

总结batch_size大的特点:

1.训练过程更稳定。容易找到全局最优解

2.通常能更快地收敛到一个较好的解。

3.需要更多的GPU内存。

4.泛化能力可能略差,因为更新次数减少,模型容易过拟合

那batch_size小了会怎么样呢?就是上面的反过来的意思,训练过程可能不稳定,容易陷入局部最优解。好处是因为每次GPU处理的样本很少,所以gpu显存占用很低。其次更容易学习到数据集里面的细节特征。其次泛化能力更好,因为噪声更大,有助于跳出局部最优,找到全局最优。

总结batch_size小的特点:

1.训练过程可能更不稳定。

2.可能更容易学习到数据的细节特征。

3.适合显卡显存受限的情况。

4.泛化能力可能更好,因为噪声更大,有助于逃离局部最优。

最后,要说的就是一般来说,调大batch_size的时候,也要相应的调大学习率。调小batch_size的时候,也得相应的调小学习率。至于为什么要这样?因为解释起来相当的麻烦,绝对不是我不会讲。


简单来说,大batch_size搭配上大学习率意味着就像是在大晴天找公交站,很远就能看见。所以可以放心的大步往前走。

小batch_size搭配上小学习率意味着雾霾天找公交站。你很难看清,所以只能用很小的步子慢慢走。

这个比喻我自己都不是很懂,只能说懂的都懂。

反正只要记住大batch_size大,学习率也得调大,反之亦然。

个人经验:

一般来说,小模型,例如10b以下的模型,我建议batch_size调小一些比较好,其次如果你的数据集很少,那batch_size还调的很大的话,特别容易严重过拟合。导致效果很差。小batch_size的拟合效果其实是不错的。这里建议从batch_size调到2开始,甚至可以从1开始。

第五个:gradient_accumulation_steps

图片

梯度累积步数(gradient_accumulation_steps)是啥?

简单来说这是一个小技巧,让你在显存不够的情况下,也能用上大批处理大小(batch size)。

举个例子

你的显存最大只能处理4个样本一次,也就是说 batch size = 4。

你想要的效果是处理8个样本一次,但直接设置 batch size = 8 会爆显存。

怎么办呢?用梯度累积!

梯度累积步数(gradient_accumulation_steps):设置为 2。

它怎么工作?

第一步:处理4个样本,计算梯度,但不更新模型参数。

第二步:再处理4个样本,计算梯度,和第一步的梯度加在一起。

更新参数:现在你有了8个样本的梯度,合并后一次性更新模型参数。

最后的效果

就像你一次处理了8个样本(大批处理大小),但实际上每次只用4个样本的显存。

就像分期付款一样,让你显存不够也能享受大批处理的效果。

第六个:loraplus_lr_ratio

图片

这个是今年出来的一个新的训练算法,旨在传统lora训练方式下。

lora+提高了性能(1% ‑ 2% 的改进)和微调速度(高达 ~ 2 倍加速),而计算成本与 LoRA 相同。

具体的就不展开说了,只知道它可以大幅缩短模型所训练的时间,同样的步数下拟合的会更加的快。我建议可以设置为8或者16。

至于为什么不展开说是因为我还没看完它的论文,所以就不献丑乱说了。只是基于个人经验来推荐一下。

这里我就介绍这6个参数了,基本上这6个是我平时调整的最为频繁的。其实还有很多重要的参数可以讲,但是我感觉每一个都讲的话可能会过于的无聊,不知道这种枯燥的参数讲解会不会有人看。而且我也怕大家睡着了。

实际上不同的参数互相搭配会有很神奇的效果,不同模型下不同的调参也会截然不同。我觉得这也是一个比较有趣的特点。

下期可能会介绍一下如何训练出一个AI客服,目前已经做到下图水平

图片

图片

你可能会问我为什么要打码?因为模型每一次说出的地址和信息都是正确的。我也没有想到换了一种训练方式会对模型产生这么好的影响。目前很少看到有人做AI客服是用训练的方法的。

实际上是可以的,只不过非常难,要对数据集每一个的比例分的特别平均,且关键信息数量要足够。不然会导致训练不充分导致没效果。还有模型的参数搭配也很关键。最后不停的测试训练,找出模型说错的内容然后去修饰、增加\减少数据集,弥补这一部分的错误。最后做到近乎找不出错误的效果。这就是一个完整的AI客服训练了。和传统的模型依靠RAG检索知识库最大的区别就是模型能够模仿带入角色,用训练人的语气性格来和你对话,这种感觉很奇妙。在测试好几次中我都认为它是一个真的人,而不是AI。所以心里话会吐露的比较多。

这个具体的AI客服实现流程我可能会做成视频或者写成文章,具体看时间是否充裕。可能会在下一期或者更久以后。

  • 7
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在R语言中,为了使用网格搜索算法参XGBoost模型,可以使用下面的代码:library(caret)xgbGrid<- expand.grid(nrounds = c(50,100,150),max_depth = c(5,10,15))xgbTune <- train(y ~ .,data = xgbTrain, method = "xgbTree", trControl = trainCtrl, tuneGrid = xgbGrid) ### 回答2: 在使用R语言中对XGBoost模型进行网格搜索算法参,可以使用`caret`包中的`train()`函数和`expand.grid()`函数来实现。 具体代码如下所示: ```R # 加载所需的包 library(xgboost) library(caret) # 设置训练参数空间 param_grid <- expand.grid( nrounds = c(100, 200, 300), # 树的数量 max_depth = c(3, 6, 9), # 树的最大深度 eta = c(0.01, 0.05, 0.1), # 学习率 gamma = c(0, 0.1, 0.2), # 树的叶子节点分裂的最小损失减少量 subsample = c(0.6, 0.8, 1), # 子样本比例 colsample_bytree = c(0.6, 0.8, 1) # 每棵树实例的特征采样比例 ) # 设置交叉验证的控制参数 ctrl <- trainControl( method = "cv", # 使用交叉验证 number = 5 # 设置交叉验证的折数 ) # 定义用于网格搜索的函数 xgboostFit <- function(nrounds, max_depth, eta, gamma, subsample, colsample_bytree) { xgb <- xgboost( data = train_set, # 训练数据集 label = train_label, # 训练标签 nrounds = nrounds, # 树的数量 max_depth = max_depth, # 树的最大深度 eta = eta, # 学习率 gamma = gamma, # 树的叶子节点分裂的最小损失减少量 subsample = subsample, # 子样本比例 colsample_bytree = colsample_bytree, # 每棵树实例的特征采样比例 objective = "reg:linear" # 设置目标函数为线性回归 ) return (xgb) } # 进行网格搜索 xgb_result <- train( x = data, # 训练数据集 y = label, # 训练标签 method = xgboostFit, # 使用自定义函数 tuneGrid = param_grid, # 设置参的参数空间 trControl = ctrl, # 设置交叉验证控制参数 metric = "RMSE" # 使用RMSE作为评估指标 ) # 输出网格搜索的结果 print(xgb_result) ``` 上述代码中,首先需要加载`xgboost`和`caret`包。然后,使用`expand.grid()`函数设置不同参数的网格空间。接下来,使用`trainControl()`函数设置交叉验证的参数。然后,定义了一个自定义函数`xgboostFit()`,用来训练XGBoost模型,并返回模型对象。最后,使用`train()`函数进行网格搜索,其中指定了训练数据、自定义函数、参数空间、交叉验证参数和评估指标。最后,打印网格搜索的结果。 请注意,上述代码中的`data`和`label`是训练数据集和标签,需要根据实际情况进行替换。 ### 回答3: 在R语言中,可以使用xgboost包来建立和参XGBoost模型。使用网格搜索算法参的具体代码如下: 1. 首先,安装和加载xgboost包: ``` install.packages("xgboost") library(xgboost) ``` 2. 准备训练集和测试集的数据。 3. 创建一个参数网格,包含要节的参数及其候选值。例如,可以节的参数包括max_depth(树的最大深度)、nrounds(迭代次数)等。设置可能的参数值组合如下: ``` param_grid <- expand.grid( max_depth = c(3, 5, 7), nrounds = c(50, 100, 150) ) ``` 4. 创建一个空的列表或数据框,用于存储不同参数组合下的模型性能指标结果: ``` result <- data.frame(max_depth = numeric(), nrounds = numeric(), accuracy = numeric(), stringsAsFactors = FALSE) ``` 5. 使用循环遍历参数网格中的每个参数组合,创建并训练XGBoost模型,并评估模型性能: ``` for(i in 1:nrow(param_grid)){ # 设置当前参数组合 params <- list( max_depth = param_grid$max_depth[i], nrounds = param_grid$nrounds[i] ) # 创建XGBoost模型 xgb_model <- xgboost(data = train_data, label = train_label, max.depth = params$max_depth, nrounds = params$nrounds) # 预测测试集 predictions <- predict(xgb_model, newdata = test_data) # 计算模型性能指标(此处仅以准确率为例) accuracy <- sum(predictions == test_label) / length(test_label) # 将参数组合及性能指标保存到结果列表中 result <- rbind(result, c(params$max_depth, params$nrounds, accuracy)) } ``` 6. 最后,可以根据模型性能指标选择最佳的参数组合: ``` # 按准确率降序排序 sorted_result <- result[order(result$accuracy, decreasing = TRUE), ] # 输出最佳参数组合及其对应的性能指标 best_params <- sorted_result[1, c("max_depth", "nrounds")] best_accuracy <- sorted_result[1, "accuracy"] ``` 以上代码展示了在R语言中使用网格搜索算法参XGBoost模型的基本步骤和示例,具体可根据自己的需求进行修和扩展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值