type
status
date
slug
summary
tags
icon
password
一、 前言
之前一直是在使用大模型直接进行微调优化,之前的微调都是基于参数上的调整。但是有些时候可能也有对于结构的一些改变。所以我的想法就是先对Qwen2.5的结构进行学习。将学习部分的内容与自己的idea相结合看看能不能进行具体的实现过程。
二、 有关transformers的初始化过程
下面几行代码是经常可以在各个教程里面看见的。
其中transformers里面的AutoModelForCausalLM(或者是AutoModel)和Tokenizer是在初始化过程中非常核心功能
(插个题外话AutoModelForCausalLM和AutoModel之间的差别是什么?查了一下说的是AutoModel对于通用类型的任务来说效果会好很多,AutoModelForCasusalLM对因果问答类型的模型会好很多)
这一节先分析AutoModelForCasualLM(或者是AutoModel)是怎么初始化以及是怎么选择深度学习框架的。
首先就是要找到transformers包的位置。使用python下的sys
```
import sys
print(sys.path)
```
就可以看到python包的位置在哪里
进入到transformers里面打开__init__.py文件,这个文件有两个作用:一是告诉python这是一个包而不是普通文件夹;二是这个__init__.py是一个初始化文件,目的是在加载这个包的时候需要执行__init__.py里面的代码。
① 如何选择深度学习框架
在__init__.py下首先第一个注意的就是_import_structure变量就是一个字典,旨在收集模块名和对象关系的字典。(这样写可能会有一点抽象后面结合深度学习框架例子可能会容易理解一点)
Transformers支持不同类型的深度学习框架,例如PyTorch、TensorFlow等。在__init__.py文件中,是通过try raise/except/else的方式进行的选择
(插个题外话:是怎么进行try/except/else的异常处理的?try在正常情况下执行的语句;except是程序异常执行的语句;else是try代码段正常执行之后会执行的语句;raise是抛出一个自定义的错误实例)
那么我们就以选择TensorFlow深度学习框架为例进行分析。在tf框架下需要收集的信息就在TensorFlow-backed objects下。

这样就把tf框架的相关信息添加到里面去了。同理PyTorch、Flax框架等都是这个道理。这样的话就将深度学习框架所需要的信息内容全部的放进去了。
问题也随之而来,放进去之后怎么读取这些信息呢?后面其实有一段读取这些模块和对象的方法。
② 初始化模块并缓存

首先来说:TYPE_CHECKING。他是一个常数,当使用Pycharm等工具进行类型检查的时候,它的值为True;当程序在执行时,它的值为false。在看if TYPE_CHECKING下面的内容,发现都是import导入内容。那么他的导入和_import_structure之间有什么差别呢?_import_structure主要是用来收集字符串信息;而TYPE_CHECKING主要就是来收集导入的包,transformers包非常的大,如果直接导入默认的全部模块和对象,那么会大大的增加启动的时间,TYPE_CHECKING 通过if/else的判断既可以保证工具类的检查正常运行,又可以节省程序在运行的启动时间和提高执行效率。
但是在程序运行过程中TYPE_CHECKING的值为false,就会到另外一块else的执行区

在这个执行区里面可以看到第一个就是有个sys.modules。这个的作用就是使用惰性模块(_LazyModule)将这些模块缓存起来。但是我们可以看到在_LazyModule里面有__name__,也就是说等号前的__name__和等号后的__name__是名称一致的。
③获取对象属性


在上两图中:__init__初始化方法就是将字典进行键值反转,将key值放到_class_to_module[value]中这就实现了键值互换的作用。但是这个的作用是什么呢?目的就是将前面_import_structure字典收集的模块和对象,在_LazyModuel 进行了反转self._class_to_module,在这个字典中,我们可以通过对象名获取到它所在模块名。

上图__getattr__方法属性获取魔法方法,为动态加载提供了机会。
首先,Python 在_LazyModule实例的字典__dict__中查找,很明显没有AutoModelForCausalLM属性
然后,Python 在_LazyModule类本身中查找,很明显也没有
最终,若对象实现了__getattr__魔法方法,Python 会调用这个魔法方法获取属性(如果还找不到则会抛出AttributeError异常)
④ 动态加载模块
在__getattr__魔法方法中,通过刚才键值反转的字典_class_to_module获取到模块路径,然后调用self._get_module私有方法动态加载模块。在这个私有方法中,通过importlib.import_module动态导入模块。
最后一步,也是非常重要的一步:setattr(self, name, value)把对象放入了transformers模块属性列表中(在下图中),它把本不是transformers模块中的对象,与自己建立了关联!

- 作者:JucanaYu
- 链接:https://jucanayu.top/article/1a37ab71-7095-80d1-9ed7-c7c0646e94ba
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。