最近在参加:2023AIWIN——中文网页自动导航挑战赛 DataWhale的大佬们提供了baseline的讲解:如何手把手打一场世界人工智能大赛 下面就来记录一下使用Kaggle上提供的30小时15G免费GPU算力的运行情况。
数据集预处理
数据下载及配置
首先从比赛官网上下载A榜的数据集:获取数据 在本地解压缩后,进入到路径:\2023S-T1-A-Data[供选手] 0513\指令数据&标签
,找到我们的训练集测试集数据和标签,共有3个 .json
文件。 将这3个文件打包上传至Kaggle上。 进入到 jupyter notebook
环境中,配置好数据集,效果如下:
数据处理
import json
import pandas as pd
import re
from collections import defaultdict, Counter
from bs4 import BeautifulSoup
LABEL_PATH = '/kaggle/input/web-auto-navigation-dataset/'
label_trainset = json. load( open ( LABEL_PATH + 'label_trainset.json' , encoding= "utf-8" ) )
instruction_trainset = json. load( open ( LABEL_PATH + 'instruction_trainset.json' , encoding= "utf-8" ) )
instruction_testA = json. load( open ( LABEL_PATH + 'instruction_testA.json' , encoding= "utf-8" ) ) import randomchat_data = [ ]
for idx in range ( 20 ) : for instructions in instruction_trainset[ idx] [ 'instruction_detail' ] : chat_data. append( { 'prompt' : instructions[ 'instruction' ] , 'response' : ';' . join( [ f' { key} ' for key, value in instructions[ 'key-value' ] . items( ) ] ) , "history" : [ ] } )
random. shuffle( chat_data) with open ( 'train.json' , 'w' ) as up: for line in chat_data[ : - 400 ] : up. write( json. dumps( line) + '\n' ) with open ( 'dev.json' , 'w' ) as up: for line in chat_data[ - 400 : ] : up. write( json. dumps( line) + '\n' )
生成的文件可以在 /kaggle/working/
目录下找到:
配置环境
!git clone https: // github. com/ THUDM/ ChatGLM- 6B. git
配置 requirements.txt
中的必要工具包。
!pip install - r / kaggle/ working/ ChatGLM- 6B/ requirements. txt
配置 train_chat.sh
文件
cd / kaggle/ working/ ChatGLM- 6B/ ptuning
写入相关配置 其中 --model_name_or_path
我们训练4-bit量化版本 THUDM/chatglm-6b-int4
。 普通的 THUDM/chatglm-6b
版本会爆显存,因为会先将模型下载下来再进行量化。 通过修改以下超参数来调整模型训练。 下述参数中 PRE_SEQ_LEN
、max_source_length
、max_target_length
过大导致模型训练较慢,可以适当修改。
with open ( "/kaggle/working/ChatGLM-6B/ptuning/train_chat.sh" , mode= 'w' ) as f: f. write( 'CHAT_TRAIN_DATA=/kaggle/working/train.json' + '\n' ) f. write( 'CHAT_VAL_DATA=/kaggle/working/dev.json' + '\n' ) f. write( 'CHECKPOINT_NAME=/kaggle/working' + '\n' ) f. write( 'PRE_SEQ_LEN=128' + '\n' ) f. write( 'LR=1e-3' + '\n' ) f. write( 'CUDA_VISIBLE_DEVICES=0 python3 main.py \\' + '\n' ) f. write( ' --do_train \\' + '\n' ) f. write( ' --train_file $CHAT_TRAIN_DATA \\' + '\n' ) f. write( ' --validation_file $CHAT_VAL_DATA \\' + '\n' ) f. write( ' --prompt_column prompt \\' + '\n' ) f. write( ' --response_column response \\' + '\n' ) f. write( ' --history_column history \\' + '\n' ) f. write( ' --overwrite_cache \\' + '\n' ) f. write( ' --model_name_or_path THUDM/chatglm-6b-int4 \\' + '\n' ) f. write( ' --output_dir $CHECKPOINT_NAME \\' + '\n' ) f. write( ' --overwrite_output_dir \\' + '\n' ) f. write( ' --max_source_length 256 \\' + '\n' ) f. write( ' --max_target_length 256 \\' + '\n' ) f. write( ' --per_device_train_batch_size 1 \\' + '\n' ) f. write( ' --per_device_eval_batch_size 1 \\' + '\n' ) f. write( ' --gradient_accumulation_steps 16 \\' + '\n' ) f. write( ' --predict_with_generate \\' + '\n' ) f. write( ' --max_steps 3000 \\' + '\n' ) f. write( ' --logging_steps 100 \\' + '\n' ) f. write( ' --save_steps 1000 \\' + '\n' ) f. write( ' --learning_rate $LR \\' + '\n' ) f. write( ' --pre_seq_len $PRE_SEQ_LEN \\' + '\n' ) f. write( ' --quantization_bit 4' + '\n' )
注:由于Kaggle上目前不支持 Linux
的 vim
命令修改文件,尝试了如下两种写入方法都会报错: 1、这种方式只能在文件末尾补充内容,报错原因大概是在调用后声明导致。 !echo CHAT_TRAIN_DATA= / kaggle/ working/ train. json >> train_chat. sh
!echo CHAT_VAL_DATA= / kaggle/ working/ dev. json >> train_chat. sh
!echo CHECKPOINT_NAME= / kaggle/ working >> train_chat. sh
2、这种方式修改的文件不是 Linux
支持的格式。 % % writefile / kaggle/ working/ ChatGLM- 6B/ ptuning/ train_chat. sh
微调 ChatGLM
!pip install rouge_chinese - i https: // pypi. tuna. tsinghua. edu. cn/ simple
微调模型,由于Kaggle上无法支持代码运行过程中的输入,因此要关闭 wandb
,执行默认操作,等待模型运行完毕即可。
!wandb off
!bash train_chat. sh
使用微调权重部署ChatGLM
import torch
from transformers import AutoTokenizer, AutoModel, AutoConfig
config = AutoConfig. from_pretrained( "THUDM/chatglm-6b-int4" , trust_remote_code= True )
config. pre_seq_len = 128 tokenizer = AutoTokenizer. from_pretrained( "THUDM/chatglm-6b-int4" , trust_remote_code= True )
model = AutoModel. from_pretrained( "THUDM/chatglm-6b-int4" , trust_remote_code= True , config= config) . half( )
prefix_state_dict = torch. load( './ChatGLM-6B/ptuning/checkpoint-100/pytorch_model.bin' )
new_prefix_state_dict = { }
for k, v in prefix_state_dict. items( ) : if k. startswith( "transformer.prefix_encoder." ) : new_prefix_state_dict[ k[ len ( "transformer.prefix_encoder." ) : ] ] = v
model. transformer. prefix_encoder. load_state_dict( new_prefix_state_dict)
model = model. quantize( 4 )
model = model. half( ) . cuda( )
model. transformer. prefix_encoder. float ( )
model = model. eval ( )
response, history = model. chat( tokenizer, '''请搜索:吉林批发和零售业的主板B股的首创环保的信息。''' , history= [ ] )
print ( response)
结果提交
对模型的输出格式进行调整,符合提交要求,保存为 .json
文件。 将得到的 .json
文件压缩提交 参赛提交
结果分析
ChatGLM-6B-int4模型的精度稍低,需要更多的训练步数。 由于GPU显存有限,每个batch只能处理1个样本,训练过程波动较大,因此需要调整 gradient_accumulation_steps
参数,在多个样本后更新参数。 缺点是速度较慢,设置为16的话总时长要10小时以上。 模型调优过程经验见下一篇文章。