fine-tuning的作用

本文探讨了深度学习中Fine-tuning的技术细节及其应用。介绍了如何利用预训练模型加速训练过程,并讨论了不同任务间模型调整的最佳实践。此外,文章还分析了在不同规模数据集上训练模型的影响。

查找的一些关于fine-tuning的解释

在网络训练中,第一层特征并不特化到任务上,特征是如何注册那个从一般到特殊的,详细参考NIPS2014上Bengio大神的文章:How transferable are features in deep neural networks?

(1)fine tuning的过程其实就是用训练好的参数(可以从已训练好的模型中获得)初始化自己的网络,然后用自己的数据接着训练,参数的调整方法与from scratch训练过程一样(梯度下降)。对于初始化过程,我们可以称自己的网络为目标网络,训练好的模型对应网络为源网络,要求目标网络待初始化的层要与源网络的层相同(层的名字、类型以及层的设置参数等等均相同)。

 (2)Fine-tuning已经成为了使用DL网络的一个常用技巧(trick)。个人认为在使用深度网络做图像处理任务时,使用一个在大的数据集上预训练好的模型(ex:caffe在imagenet上训练的caffeNet, VGG16...)在自己数据上微调往往可以得到比直接用自己数据训练更好的效果,这是因为在imagenet上预训练的模型参数从微调一开始就处于一个较好的位置,这样微调能够更快的使网络收敛。对于相同类别的任务我们可以默认这样去做比较好,比如我们可以直接利用caffe在imageNet classification task 预训练的模型做一些其他的分类任务。然而当我们要做一个不同的任务,比如在imageNet上做Detection,那么可能直接拿在imagenet分类任务上预训练的模型进行微调就不是最好的了。分类考虑的是图像的一个语义信息,无论目标出现在哪里判定出类别就算正确,而检测不一样,还需要知道目标的确切位置,所以对于检测任务,我们也可以使用微调这个trick,但使用的预训练网络是在目标级别数据库上训练的(图像就是一个完整目标或者图像中所有目标都有标记—Bounding Boxes Infomation)。

(3)一般我们在训练from scratch的时候往往要在一些超大型的数据集上训练,一个目的是为了让训练得到的特征(尤其是底层特征)更加多样。而从genertive pre-training到discriminative fine-tuning的过程是一个对泛化特征进行面向task的特化的过程。首先,如果你将底层特征可视化出来,会发现底层特征多是一些边、角之类的基础几何形状,高层特征可能会发生一些有趣的变化,直接反映出你的task。 在大数据集上进行 pretrain 的目的之一是为了获得丰富、一般化的底层特征,换言之就是学到丰富的“基础几何形状”。有了这些丰富的基础几何形状,等过渡到小数据集上 finetune 的时候,就可以通过它们组合出上层具有强判别力的特征。此时,如果你再将组合出来的上层特征可视化,就会发现它们已经有模有样了,见上面辛博的配图。反之,如果你直接在小数据集上训练,那么就难以获得丰富的、一般化的基础几何形状,也就难以“描绘出”栩栩如生的上层特征。底层特征非常重要,如果底层特征不够好,特征类型不够充分,很可能训练不出来好的高层抽象。这就是为什么需要在大规模数据集上进行genertive training的原因之一。


(3)从我们的实验经验上来看,网络越深,底层的参数越难得到有效训练,这也是为什么经常有人用 vggNet  finetune 的原因之一.
使用 backpropagation 进行训练的时候残差逐层传递,有可能到底层的时候残差就很小了(gradient vanishing),导致底层的参数train 不动.   这也是楼上辛同学的图里底层 feature map 没有什么改变的原因之一,因为底层参数本身就很难得到训练.
(4)finetune 就是直接从别人已经训练好的网络上拷贝参数,然后针对自己的数据训练新的模型。

这时候需要比较小的 learning_rate, 因为要在不破坏原有模型的情况下 fit 自己的数据,finetune 的好处就是可以直接获得我们难以或者无法训练的底层参数。

(5)在目标检测中,会使用VGG、Resnet、zf、Alexnet等基础网络作为特征提取器。然后调用预训练好的网络(输出pool5的feature map,详情参考这篇博客),根据特定任务进行fine-tuning(有实验证明:如果不进行fine-tuning,也就是你直接把预训练模型当做万金油使用,类似于HOG、SIFT一样做特征提取,不针对特定的任务。然后把提取的特征用于分类,结果发现p5的精度竟然跟f6、f7差不多,而且f6提取到的特征还比f7的精度略高;如果你进行fine-tuning了,那么在rcnn中f7、f6的提取到的特征最后训练的svm分类器的精度就会飙涨),据此我们明白了一个道理,如果不针对特定任务进行fine-tuning,而是把CNN当做特征提取器,卷积层所学到的特征其实就是基础的共享特征提取层,就类似于SIFT算法一样,可以用于提取各种图片的特征,而f6、f7所学习到的特征是用于针对特定任务的特征。打个比方:对于人脸性别识别来说,一个CNN模型前面的卷积层所学习到的特征就类似于学习人脸共性特征,然后全连接层所学习的特征就是针对性别分类的特征了。

题外话:在RCNN中还有另外一个疑问:CNN训练的时候,本来就是对bounding box的物体进行识别分类训练,是一个端到端的任务,在训练的时候最后一层softmax就是分类层,那么为什么作者闲着没事干要先用CNN做特征提取(提取fc7层数据),然后再把提取的特征用于训练svm分类器?这个是因为svm训练和cnn训练过程的正负样本定义方式各有不同,导致最后采用CNN softmax输出比采用svm精度还低。

    事情是这样的,cnn在训练的时候,对训练数据做了比较宽松的标注,比如一个bounding box可能只包含物体的一部分,那么我也把它标注为正样本,用于训练cnn;采用这个方法的主要原因在于因为CNN容易过拟合,所以需要大量的训练数据,所以在CNN训练阶段我们是对Bounding box的位置限制条件限制的比较松(IOU只要大于0.5都被标注为正样本了);

  然而svm训练的时候,因为svm适用于少样本训练,所以对于训练样本数据的IOU要求比较严格:IOU<0.7的都当成负样本(rcnn训练的是svm二分类这里会存在正负样本不均衡情况,要对负样本下采样或者对正样本上采样)。我们只有当bounding box把整个物体都包含进去了,我们才把它标注为物体类别,然后训练svm。


在机器学习和深度学习领域中,**Fine-Tuning** 和 **Tuning** 是两个常被提及的概念。虽然它们都涉及对模型的调整过程,但在具体含义、应用场景及技术实现上存在显著区别。 ### Fine-Tuning(微调) Fine-Tuning 通常指的是在一个已经预训练好的模型基础上,针对特定任务或数据集进行进一步的参数调整。这一过程通常保留了原始模型的大部分结构和参数,并在此基础上使用新的数据对模型进行再训练,以适应新任务的需求。根据是否调整全部参数,可以分为全参数微调(Full Fine-tuning)和部分/参数高效微调(Parameter-Efficient Fine-tuning, PEFT),例如 LoRA(Low-Rank Adaptation)[^3]。 Fine-Tuning 的主要优势在于它能够利用预训练模型所学到的通用特征表示,并将其迁移到特定任务中,从而减少从头开始训练所需的数据量和计算资源。这种方式非常适合需要高精度或领域特定知识的任务,如医学图像分析、法律文本理解等[^1]。 ### Tuning(调优) Tuning 是一个更广泛的概念,涵盖了所有类型的模型参数调整过程,包括但不限于 Fine-Tuning。它通常指代的是在模型开发过程中,为了提升模型性能而对超参数(如学习率、批处理大小、网络层数、激活函数类型等)进行调整的过程。这些调整可能发生在模型训练的不同阶段,目的是找到最优的模型配置,使得模型在验证集或测试集上的表现达到最佳[^2]。 此外,Tuning 还可能涉及模型架构的选择与优化,比如通过神经网络架构搜索(Neural Architecture Search, NAS)来自动寻找最适合当前任务的网络结构。 ### 区别与应用场景 - **Fine-Tuning** 更侧重于基于已有预训练模型,在目标任务上进行快速适配。适用于有少量目标域数据但希望获得较好性能的情况。 - **Tuning** 则更多关注于整个模型训练过程中的参数和超参数优化,适用于模型开发初期或没有现成预训练模型可用的情形。 两者在实际应用中常常结合使用,例如先对模型进行 Fine-Tuning 以快速适应新任务,然后通过 Tuning 调整超参数以进一步提升模型性能。 ```python # 示例:使用 Hugging Face Transformers 库进行简单的 Fine-Tuning from transformers import AutoTokenizer, AutoModelForSequenceClassification, Trainer, TrainingArguments model_name = "bert-base-uncased" tokenizer = AutoTokenizer.from_pretrained(model_name) model = AutoModelForSequenceClassification.from_pretrained(model_name, num_labels=2) training_args = TrainingArguments( output_dir="./results", num_train_epochs=3, per_device_train_batch_size=16, evaluation_strategy="epoch" ) trainer = Trainer( model=model, args=training_args, train_dataset=train_dataset, eval_dataset=eval_dataset, tokenizer=tokenizer ) trainer.train() ```
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值