模型微调

监督微调(SFT)

SFT是把x=[BOS, s, u, c, a, EOS]作为训练数据,微调模型以更好地适应特定任务或领域。

序列起始的特殊token,用于稳定起始状态。

给AI的元指令/角色设定,训练时通常和user一同作为条件,但不计损失,推理时必须与训练时采用相同模板,以避免风格或格式不一。

user的输入内容。

使用RAG检索到的上下文片段+多轮回复的历史信息(可只用总结作为输入)(或去重按权重处理)。

高质量assistant给出的回答,用于模仿这种规范化回复。我们只在a的token上计损失,其余位置打mask(label=-100)。

序列结束的特殊token,训练时通常只放在assistant段末尾,推理时遇到EOS作为停止条件之一,但注意别把EOS泄露到user/system中,会导致模型提前停止或学到错误的停用习惯。

SFT采用条件自回归(decoder-only)或条件序到序(encoder-decoder)的极大似然估计,依靠高质量、风格一致的答案将预训练分布旋转到格式合规的子分布。
SFT的目标是让模型在给定输入时生成更准确和相关的输出。但容易导致话多或过度自信,常用DPO/ORPO收敛风格与拒答策略。

使用RAG结果输入的方法:

学习一串可训练的牵入向量,只加在输入头上,用于确定风格和格式,可与LoRA叠加。

采用Encoder-Decoder架构,将检索到的数据交给Encoder作为记忆,Decoder生成时用Cross-Attention随取随用。可一次编码多次读,对长上下文场景更稳定。

对当前上下文信息计算查询向量q,并找到k个最近邻$(k_i, v_i)$,将距离通过温度T转为权重,即$P_{kNN}(\omega) \propto \sum_{i:v_i=\omega} exp \big(-\frac{\lVert q - k_i \rVert ^2}{T} \big)$,通过$P(\omega) = (1 - \lambda) P_{LM}(\omega) + \lambda P_{kNN}(\omega)$,其中$\lambda \in [0, 1]$可固定也可自适应。

低秩适应(LoRA)

标准线性层输出为$y = \tilde{W}x$,但LoRA并不直接更新$\tilde{W}$,而是在训练时学习一个低秩增量$\triangle{W} = s \cdot AB$,而$\tilde{W} = W + \triangle W$,秩$r \ll \min(d_{in}, d_{out})$,缩放$s = \frac{\alpha}{r}$。
通常将A初始化为全零,B初始化为小随机值,这样使得$\triangle W=0$不会破坏预训练能力,即初始函数等价于原始基座,再用$s = \frac{\alpha}{r}$控制学习幅度,训练时只更新A和B,冻结W。
新增浮点运算次数$FLOPs \approx O(r \cdot (d_{in} + d_{out}))$,相比原层$O(d_{in}, d_{out})$很小,几乎不影响推理吞吐。

LoRA优先插在注意力机制上(重语义),适度加在MLP(重风格/格式)。
基座是指预训练好的原始模型权重$W$,在LoRA训练时被完全冻结。

LoRA可采用两种推理形态:

先加载基座权重,再加载LoRA适配器,前向时实时加$\triangle Wx$。可一份基座+多个LoRA头,以便随时切换,更灵活,基座可4/8bit量化,直接推理,代价是每层多做两次小矩阵乘。可在资源吃紧时采用量化基座,但在合并前需要反量化到FP16再合并,同时也会影响精度。

在非量化的模型副本上把$\triangle W$加回$W$,可以部署成单一权重文件,无LoRA依赖,便于再做整模型量化或裁剪。需要注意的是,量化基座上不能直接合并,需先把量化权重反量化到FP16/FP32副本再合并,要切换到另一套LoRA时需回滚到原基座再合并,相对来说较麻烦。

Pandas

读写

pd.read_csv(): 读取CSV文件

pd.to_csv(): 写入CSV文件

df.loc[]: 基于标签选择数据

df.iloc[]: 基于位置选择数据

pd.concat(): 将多个数据按照行或列合并

pd.merge(): 按照某列将两个数据合并

df.head(): 查看前几行数据

df.sample(): 随机抽样数据

df.tail(): 查看后几行数据

df.info(): 查看数据基本信息

df.describe(): 查看数据的基本统计信息,包括均值、中位数、标准差、最小值、最大值等

多级索引

pd.MultiIndex: 创建多级索引,其中

从元组创建多级索引。

从列表的交叉积创建多级索引。

pd.set_index(): 将df的某列转换为多重索引

pd.reset_index(): 将多重索引转换为普通列

df.loc[]: 按顺序选择多级索引数据

df.xs(): 按级别选择多级索引数据

df.sort_index(): 按多重索引排序

df.groupby(): 按多重索引分组

df.fillna(): 填充多重索引的缺失值

df.dropna(): 删除多重索引的缺失值

性能优化

df.astype(): 将某列转换为指定数据类型;
Pandas默认的数据类型是int64float64,但在某些情况下,使用更小的数据类型可以节省内存空间和提高计算速度。例如,可以将整数类型转换为int8int16int32,将浮点数类型转换为float32
对具有重复值的字符串列使用category数据类型,可以显著减少内存使用。因为category类型只存储唯一值的索引,而不是每个值的完整字符串;
df.downcast(): 将某列转换为更小的数据类型。

尽量采用向量化操作,避免使用for循环遍历DataFrame的行或列。Pandas提供了许多内置函数和方法,可以对整个列或行进行操作,而不需要显式地循环;
使用df.apply()df.applymap()df.map()等方法对列或行进行操作更高效;
使用df.eval()df.query()方法,可以在DataFrame中执行复杂的表达式和查询,而不需要显式地编写循环或条件语句。

使用索引切片分块操作,可以快速访问和修改DataFrame中的数据,而不需要遍历整个DataFrame。
当需要将多个DataFrame合并时(如pd.merge()pd.concat,特别是在处理大数据集时需要注意优化合并操作。可以使用on和how参数明确指定合并方式,避免不必要的计算。

通过numba库,可以将Python代码编译为机器码,从而提高代码的执行速度。Pandas与numba集成,可以使用@numba.jit装饰器来加速自定义函数。

避免链式赋值(如df['A'][df['A'] > 2] = 0),因为它可能导致意外的结果和性能问题。应使用单明确的赋值语句(如df.loc[df['A'] > 2, 'A'] = 0)。

数据清洗

df.set_index(): 将某列设置为索引

df.reset_index(): 把索引重置为普通列

df.isna(): 检测缺失值

df.fillna(): 填充缺失值

df.dropna(): 删除缺失值

df.duplicated(): 检测重复值

df.drop_duplicates(): 删除重复值

df.replace(): 替换值

pd.to_numeric(): 将某列转换为数值类型

pd.to_datetime(): 将某列转换为日期时间类型

pd.get_dummies(): 将某列转换为独热编码

df.sort_values(): 按某列排序

df.groupby(): 按某列分组

df.agg(): 对分组数据进行聚合计算

df.eval(): 使用字符串表达式计算新列

df.query(): 使用字符串表达式过滤数据

df.apply(): 对某列或行应用函数

df.applymap(): 对整个DataFrame应用函数

df.map(): 对某列应用函数

pd.date_range(): 生成指定频率的日期范围

pd.Timedelta(): 计算时间差

df.rolling(): 计算滚动窗口统计量(固定窗口大小)

df.expanding(): 计算扩展窗口统计量(只有最小预测数)

数据分析

df.mean(): 计算均值

df.median(): 计算中位数

df.mode(): 计算众数

df.count(): 计算非缺失值的数量

df.corr(): 计算相关系数,其中

皮尔逊相关系数,衡量线性关系,其中-1表示完全负相关,1表示完全正相关,0表示无相关性。

斯皮尔曼相关系数,衡量线性关系,其中-1表示完全负相关,1表示完全正相关,0表示无相关性。

肯德尔相关系数,衡量线性关系,其中-1表示完全负相关,1表示完全正相关,0表示无相关性。

只用df.corr()可计算相关性矩阵
可用import seaborn as snssns.heatmap()可视化相关性矩阵

df.plot(): 绘制数据图表,其中
kind='line': 折线图;
kind='bar': 条形图;
kind='barh': 横向条形图;
kind='hist': 直方图;
kind='scatter': 散点图;
kind='box': 箱线图;
kind='kde': 密度分布图;
kind='pie': 饼状图;
kind='area': 面积图

pd.pivot_table(): 创建数据透视表,对一个或多个数值指标按行/列维度做聚合(mean、sum、std、count、quantile等)

pd.crosstab(): 计算两个或多个分类变量计算频次/比例的列联表

装饰器

@:装饰器

*args:可变位置参数

**kwargs:可变关键字参数

@wraps:保留被装饰函数的元信息

@lru_cache:缓存函数结果

@repeat:重复执行函数

@sleep_and_retry:睡眠并重试

@limits:限制函数调用频率

@dataclass:数据类

@register:如果程序意外停止,可以执行一些操作

@property:将方法转换为属性

@x.setter:为属性添加写入能力

@x.deleter:为属性添加删除能力

@cached_property:让方法第一次调用时计算,之后读取缓存

@staticmethod:定义静态方法

@classmethod:定义类方法

@singledispatch:允许函数根据第一个参数的类型进行不同的处理

0%