lc:98、51 熬夜看小说起晚了。晚上看了一下claudecode在国内怎么配置的问题,不得不说还真是八仙过海各显神通,什么法子都来了。CC官方防大陆也和防火一样生怕 claudecode在大陆能用。 配了一个小时差不多弄完了,然后把平时写日记的typora换成了obsidian并加上了claudecode插件。 开始做第一个项目:
Fine-tuning Qwen-1.5B with LoRA for Chinese Sentiment Analysis
用Qwen是因为它的中文能力较强,虽然说事实上它支持超过29种语言的多语言。符合我们用lora锦上添花的过程,而且它显存友好,部署起来并不会特别吃力。
| 特性 | Qwen | BERT |
|---|---|---|
| 架构 | Decoder-Only | Encoder-Only |
| 注意力 | Causal (单向) | Bidirectional (双向) |
| 预训练目标 | 自回归生成 | 掩码语言建模 |
| 分类时使用 | 最后一个 token | [CLS] token |
在GPT之前分类任务主流就是用bert,由谷歌2018年提出。 Decoder-Only 模型做分类时,通常取序列最后一个位置的隐藏状态,通过一个线性分类头输出类别概率。和生成式的区别仅仅是最后过的头不同,lora_config = LoraConfig( task_type=TaskType.SEQ_CLS, # 序列分类任务 … ) 不看视频,自己动起手来才发现github的autoxxx还是有点花样的,能够自己帮你处理很多结构。 比如说Qwen2.5-1.5B本来是文本生成的模型,如果用AutoModelForSequenceClassification去下载它,模型结构会自动调整:
AutoModelForSequenceClassification (分类任务)
| 层级 | 组件名称 | 状态 |
|---|---|---|
| 1 | Qwen Transformer | 预训练好的(和上面一样) |
| 2 | Score Head (2) | 随机初始化的(num_labels) |
AutoModelForCausalLM (生成任务)
| 层级 | 组件名称 | 状态 |
|---|---|---|
| 1 | Qwen Transformer | 预训练好的 |
| 2 | LM Head (151936) | 预训练好的(词表大小) |
关键区别:
- 分类任务:最后一层是 Score Head,只输出 2 个分数(对应"好"/“坏”)
- 生成任务:最后一层是 LM Head,输出 151936 个分数(词表中的每个词)
分类任务就不是从超大词表里取出预测的下一个结果了,而是像从两个词的词表中抽一个,也就是"好"或者"坏"。
当然,tokenizer还是要的,虽然最后不用根据它把数据映射回真实词,直接用0、1二分类就行,但是Embedding还是要用tokenizer把数据变成词向量。 今天最后一个工作,理解一下数据预处理。
原始文本
{“text”: “这家酒店环境非常好,服务态度也很棒!”, “label”: 1} {“text”: “服务态度太差了,再也不会来了。”, “label”: 0} 考虑到我们需要的是连贯的文字和可理解的内容。乱码、多余空格、重复标点,都是"脏"的数据,需要去除,但是内容量过于巨大,不可能一个一个看。所以采用下面的操作
| |
第一个传参位置寻找要匹配的字符,第二个位置是替换的结果,第三个位置传入的是文本变量,除此之外还可以传入count,表示最多替换次数,不传则替换所有。flags,正则表达式标志,比如忽略大小写之类的操作可以由它指定。
分词处理
模型不能直接理解文字,需要转换成数字
| |
以 “这家酒店很好” 为例:
词汇切分: “这家酒店很好” → [“这家”, “酒店”, “很”, “好”] 转换ID: [“这家”, “酒店”, “很”, “好”] → [1234, 5678, 9012, 3456] 添加特殊token: [101, 1234, 5678, 9012, 3456, 102] (101=开始,102=结束),4个转换的token,加俩特殊token 填充: 如果不足256长度,用0填充到256 结果包含:
input_ids:[101, 1234, 5678, 9012, 3456, 102, 0, 0, ...](256个数字)attention_mask:[1, 1, 1, 1, 1, 1, 0, 0, ...](1=真实内容,0=填充)- labels:
1(情感标签) 接着用一个函数
| |
批量调用刚刚的预处理过程即可,dataset.map封装好了最后的组装环节,直接输入各个参数即可。
完整流程
| |
Why 这么处理
- 统一格式: 所有句子都变成256长度的数字数组
- 批量处理: 可以一次性处理多个样本,提高效率
- 模型理解: 模型只能处理数字,不能直接理解文字
- 内存对齐: 固定长度便于GPU并行计算 今天先到这吧,等着晚点看cs2的2026年的森载大战了。