不用再找,这是大模型 LLM 微调经验最全总结

大家好,今天对大模型微调项目代码进行了重构,支持ChatGLM和ChatGLM2模型微调的切换,增加了代码的可读性,并且支持Freeze方法、Lora方法、P-Tuning方法、「全量参数方法」 微调。

PS:在对Chat类模型进行SFT时,一定要遵循模型原始的系统指令,否则会出现严重的遗忘或微调效果不明显现象。

https://github.com/Hello-MLClub/ChatGLM-Finetuning

在这里插入图片描述

更新说明

为什么要更新?

其实一开始这个项目是ChatGLM刚刚出来,笔者进行单卡微调的代码(写的会比较随意),主要是为了帮助大家跑通整个SFT的流程,更加理解代码。没想到获得了这么多关注,并且ChatGLM2也出了,很多网友都提问是否支持,因此做了项目的更新,代码的重构。(后面可能会支持更多模型吧)

相比于V0.1版本,目前版本做了如下更新:

  • 项目仍然采用非Trainer的写法,虽然Trainer代码简单,但不易修改,大模型时代算法工程师本就成为了数据工程师,因此更需了解训练流程及步骤

  • 不仅支持单卡训练,也支持多卡训练。

  • 代码中关键内容增加了中文注释。

  • 数据格式已经更新为广泛使用的{“instruction”: instruction, “input”: input, “output”: output}格式。

  • 不仅支持微量参数训练,也支持全量参数训练(至少两块A40)

  • 由于ChatGLM官方代码和模型之前一直在更新,目前代码和模型使用的是最新版本(20230806)。

  • 训练数据构建过程,与ChatGLM、ChatGLM2推理一致,见utils.py文件内容,并且在采用单指令集方式,使得模型并没有出现严重的灾难性遗忘

  • 统计了不同方法显存占用情况

技术交流

建了技术交流群!想要进交流群、获取如下原版资料的同学,可以直接加微信号:dkl88194。加的时候备注一下:研究方向 +学校/公司+CSDN,即可。然后就可以拉你进群了。

方式①、添加微信号:dkl88194,备注:来自CSDN + 技术交流
方式②、微信搜索公众号:Python学习与数据挖掘,后台回复:加群

微调方法

模型微调时,如果遇到显存不够的情况,可以开启gradient_checkpointing、zero3、offload等参数来节省显存。

本文章对gradient_checkpointing、zero3、offload暂时不做过多介绍,后面会进行专项介绍,或者大家可以自行搜索其原理。

Freeze方法

Freeze方法,即参数冻结,对原始模型部分参数进行冻结操作,仅训练部分参数,以达到在单卡或多卡,不进行TP或PP操作就可以对大模型进行训练。

微调代码,见train.py,核心部分如下:

freeze_module_name = args.freeze_module_name.split(",")
for name, param in model.named_parameters():if not any(nd in name for nd in freeze_module_name):param.requires_grad = False

针对模型不同层进行修改,可以自行修改freeze_module_name参数配置,例如"layers.27.,layers.26.,layers.25.,layers.24."。训练代码均采用DeepSpeed进行训练,可设置参数包含train_path、model_name_or_path、mode、train_type、freeze_module_name、ds_file、num_train_epochs、per_device_train_batch_size、gradient_accumulation_steps、output_dir等, 可根据自己的任务配置。

ChatGLM单卡训练

CUDA_VISIBLE_DEVICES=0 deepspeed --master_port 520 train.py \--train_path data/spo_0.json \--model_name_or_path ChatGLM-6B/ \--per_device_train_batch_size 1 \--max_len 1560 \--max_src_len 1024 \--learning_rate 1e-4 \--weight_decay 0.1 \--num_train_epochs 2 \--gradient_accumulation_steps 4 \--warmup_ratio 0.1 \--mode glm \--train_type freeze \--freeze_module_name "layers.27.,layers.26.,layers.25.,layers.24." \--seed 1234 \--ds_file ds_zero2_no_offload.json \--gradient_checkpointing \--show_loss_step 10 \--output_dir ./output-glm

ChatGLM四卡训练,通过CUDA_VISIBLE_DEVICES控制具体哪几块卡进行训练,如果不加该参数,表示使用运行机器上所有卡进行训练

CUDA_VISIBLE_DEVICES=0,1,2,3 deepspeed --master_port 520 train.py \--train_path data/spo_0.json \--model_name_or_path ChatGLM-6B/ \--per_device_train_batch_size 1 \--max_len 1560 \--max_src_len 1024 \--learning_rate 1e-4 \--weight_decay 0.1 \--num_train_epochs 2 \--gradient_accumulation_steps 4 \--warmup_ratio 0.1 \--mode glm \--train_type freeze \--freeze_module_name "layers.27.,layers.26.,layers.25.,layers.24." \--seed 1234 \--ds_file ds_zero2_no_offload.json \--gradient_checkpointing \--show_loss_step 10 \--output_dir ./output-glm

ChatGLM2单卡训练

CUDA_VISIBLE_DEVICES=0 deepspeed --master_port 520 train.py \--train_path data/spo_0.json \--model_name_or_path ChatGLM2-6B/ \--per_device_train_batch_size 1 \--max_len 1560 \--max_src_len 1024 \--learning_rate 1e-4 \--weight_decay 0.1 \--num_train_epochs 2 \--gradient_accumulation_steps 4 \--warmup_ratio 0.1 \--mode glm2 \--train_type freeze \--freeze_module_name "layers.27.,layers.26.,layers.25.,layers.24." \--seed 1234 \--ds_file ds_zero2_no_offload.json \--gradient_checkpointing \--show_loss_step 10 \--output_dir ./output-glm2

ChatGLM2四卡训练,通过CUDA_VISIBLE_DEVICES控制具体哪几块卡进行训练,如果不加该参数,表示使用运行机器上所有卡进行训练

CUDA_VISIBLE_DEVICES=0,1,2,3 deepspeed --master_port 520 train.py \--train_path data/spo_0.json \--model_name_or_path ChatGLM2-6B/ \--per_device_train_batch_size 1 \--max_len 1560 \--max_src_len 1024 \--learning_rate 1e-4 \--weight_decay 0.1 \--num_train_epochs 2 \--gradient_accumulation_steps 4 \--warmup_ratio 0.1 \--mode glm2 \--train_type freeze \--freeze_module_name "layers.27.,layers.26.,layers.25.,layers.24." \--seed 1234 \--ds_file ds_zero2_no_offload.json \--gradient_checkpointing \--show_loss_step 10 \--output_dir ./output-glm2

PS:ChatGLM微调时所用显存要比ChatGLM2多,详细显存占比如下:在这里插入图片描述

PT方法

PT方法,即P-Tuning方法,参考ChatGLM官方代码 ,是一种针对于大模型的soft-prompt方法。

  • P-Tuning仅对大模型的Embedding加入新的参数。

  • P-Tuning-V2,将大模型的Embedding和每一层前都加上新的参数。

P-Tuning: https://arxiv.org/abs/2103.10385
P-Tuning-V2: https://arxiv.org/abs/2110.07602

微调代码,见train.py,核心部分如下:

config = MODE[args.mode]["config"].from_pretrained(args.model_name_or_path)
config.pre_seq_len = args.pre_seq_len
config.prefix_projection = args.prefix_projection
model = MODE[args.mode]["model"].from_pretrained(args.model_name_or_path, config=config)
for name, param in model.named_parameters():if not any(nd in name for nd in ["prefix_encoder"]):param.requires_grad = False

当prefix_projection为True时,为P-Tuning-V2方法,在大模型的Embedding和每一层前都加上新的参数;为False时,为P-Tuning方法,仅在大模型的Embedding上新的参数。

训练代码均采用DeepSpeed进行训练,可设置参数包含train_path、model_name_or_path、mode、train_type、pre_seq_len、prefix_projection、ds_file、num_train_epochs、per_device_train_batch_size、gradient_accumulation_steps、output_dir等, 可根据自己的任务配置。

ChatGLM单卡训练

CUDA_VISIBLE_DEVICES=0 deepspeed --master_port 520 train.py \--train_path data/spo_0.json \--model_name_or_path ChatGLM-6B \--per_device_train_batch_size 1 \--max_len 768 \--max_src_len 512 \--learning_rate 1e-4 \--weight_decay 0.1 \--num_train_epochs 2 \--gradient_accumulation_steps 4 \--warmup_ratio 0.1 \--mode glm \--train_type ptuning \--seed 1234 \--ds_file ds_zero2_no_offload.json \--gradient_checkpointing \--show_loss_step 10 \--pre_seq_len 16 \--prefix_projection True \--output_dir ./output-glm

ChatGLM四卡训练,通过CUDA_VISIBLE_DEVICES控制具体哪几块卡进行训练,如果不加该参数,表示使用运行机器上所有卡进行训练

CUDA_VISIBLE_DEVICES=0,1,2,3 deepspeed --master_port 520 train.py \--train_path data/spo_0.json \--model_name_or_path ChatGLM-6B \--per_device_train_batch_size 1 \--max_len 1560 \--max_src_len 1024 \--learning_rate 1e-4 \--weight_decay 0.1 \--num_train_epochs 2 \--gradient_accumulation_steps 4 \--warmup_ratio 0.1 \--mode glm \--train_type ptuning \--seed 1234 \--ds_file ds_zero2_no_offload.json \--gradient_checkpointing \--show_loss_step 10 \--pre_seq_len 16 \--prefix_projection True \--output_dir ./output-glm

ChatGLM2单卡训练

CUDA_VISIBLE_DEVICES=0 deepspeed --master_port 520 train.py \--train_path data/spo_0.json \--model_name_or_path ChatGLM2-6B \--per_device_train_batch_size 1 \--max_len 1560 \--max_src_len 1024 \--learning_rate 1e-4 \--weight_decay 0.1 \--num_train_epochs 2 \--gradient_accumulation_steps 4 \--warmup_ratio 0.1 \--mode glm2 \--train_type ptuning \--seed 1234 \--ds_file ds_zero2_no_offload.json \--gradient_checkpointing \--show_loss_step 10 \--pre_seq_len 16 \--prefix_projection True \--output_dir ./output-glm2

ChatGLM2四卡训练,通过CUDA_VISIBLE_DEVICES控制具体哪几块卡进行训练,如果不加该参数,表示使用运行机器上所有卡进行训练

CUDA_VISIBLE_DEVICES=0,1,2,3 deepspeed --master_port 520 train.py \--train_path data/spo_0.json \--model_name_or_path ChatGLM2-6B \--per_device_train_batch_size 1 \--max_len 1560 \--max_src_len 1024 \--learning_rate 1e-4 \--weight_decay 0.1 \--num_train_epochs 2 \--gradient_accumulation_steps 4 \--warmup_ratio 0.1 \--mode glm2 \--train_type ptuning \--seed 1234 \--ds_file ds_zero2_no_offload.json \--gradient_checkpointing \--show_loss_step 10 \--pre_seq_len 16 \--prefix_projection True \--output_dir ./output-glm2

PS:ChatGLM微调时所用显存要比ChatGLM2多,详细显存占比如下:在这里插入图片描述

Lora方法

Lora方法,即在大型语言模型上对指定参数(权重矩阵)并行增加额外的低秩矩阵,并在模型训练过程中,仅训练额外增加的并行低秩矩阵的参数。当“秩值”远小于原始参数维度时,新增的低秩矩阵参数量也就很小。在下游任务tuning时,仅须训练很小的参数,但能获取较好的表现结果。

请添加图片描述

Paper: https://arxiv.org/abs/2106.09685
Github: https://github.com/microsoft/LoRA
HuggingFace封装的peft库: https://github.com/huggingface/peft

微调代码,见train.py,核心部分如下:

model = MODE[args.mode]["model"].from_pretrained(args.model_name_or_path)
lora_module_name = args.lora_module_name.split(",")
config = LoraConfig(r=args.lora_dim,lora_alpha=args.lora_alpha,target_modules=lora_module_name,lora_dropout=args.lora_dropout,bias="none",task_type="CAUSAL_LM",inference_mode=False,)
model = get_peft_model(model, config)
model.config.torch_dtype = torch.float32

训练代码均采用DeepSpeed进行训练,可设置参数包含train_path、model_name_or_path、mode、train_type、lora_dim、lora_alpha、lora_dropout、lora_module_name、ds_file、num_train_epochs、per_device_train_batch_size、gradient_accumulation_steps、output_dir等, 可根据自己的任务配置。

ChatGLM单卡训练

CUDA_VISIBLE_DEVICES=0 deepspeed --master_port 520 train.py \--train_path data/spo_0.json \--model_name_or_path ChatGLM-6B \--per_device_train_batch_size 1 \--max_len 1560 \--max_src_len 1024 \--learning_rate 1e-4 \--weight_decay 0.1 \--num_train_epochs 2 \--gradient_accumulation_steps 4 \--warmup_ratio 0.1 \--mode glm \--train_type lora \--lora_dim 16 \--lora_alpha 64 \--lora_dropout 0.1 \--lora_module_name "query_key_value" \--seed 1234 \--ds_file ds_zero2_no_offload.json \--gradient_checkpointing \--show_loss_step 10 \--output_dir ./output-glm

ChatGLM四卡训练,通过CUDA_VISIBLE_DEVICES控制具体哪几块卡进行训练,如果不加该参数,表示使用运行机器上所有卡进行训练

CUDA_VISIBLE_DEVICES=0,1,2,3 deepspeed --master_port 520 train.py \--train_path data/spo_0.json \--model_name_or_path ChatGLM-6B \--per_device_train_batch_size 1 \--max_len 1560 \--max_src_len 1024 \--learning_rate 1e-4 \--weight_decay 0.1 \--num_train_epochs 2 \--gradient_accumulation_steps 4 \--warmup_ratio 0.1 \--mode glm \--train_type lora \--lora_dim 16 \--lora_alpha 64 \--lora_dropout 0.1 \--lora_module_name "query_key_value" \--seed 1234 \--ds_file ds_zero2_no_offload.json \--gradient_checkpointing \--show_loss_step 10 \--output_dir ./output-glm

ChatGLM2单卡训练

CUDA_VISIBLE_DEVICES=0 deepspeed --master_port 520 train.py \--train_path data/spo_0.json \--model_name_or_path ChatGLM2-6B \--per_device_train_batch_size 1 \--max_len 1560 \--max_src_len 1024 \--learning_rate 1e-4 \--weight_decay 0.1 \--num_train_epochs 2 \--gradient_accumulation_steps 4 \--warmup_ratio 0.1 \--mode glm2 \--train_type lora \--lora_dim 16 \--lora_alpha 64 \--lora_dropout 0.1 \--lora_module_name "query_key_value,dense_h_to_4h,dense_4h_to_h,dense" \--seed 1234 \--ds_file ds_zero2_no_offload.json \--gradient_checkpointing \--show_loss_step 10 \--output_dir ./output-glm2

ChatGLM2四卡训练,通过CUDA_VISIBLE_DEVICES控制具体哪几块卡进行训练,如果不加该参数,表示使用运行机器上所有卡进行训练

CUDA_VISIBLE_DEVICES=0,1,2,3 deepspeed --master_port 520 train.py \--train_path data/spo_0.json \--model_name_or_path ChatGLM2-6B \--per_device_train_batch_size 1 \--max_len 1560 \--max_src_len 1024 \--learning_rate 1e-4 \--weight_decay 0.1 \--num_train_epochs 2 \--gradient_accumulation_steps 4 \--warmup_ratio 0.1 \--mode glm2 \--train_type lora \--lora_dim 16 \--lora_alpha 64 \--lora_dropout 0.1 \--lora_module_name "query_key_value,dense_h_to_4h,dense_4h_to_h,dense" \--seed 1234 \--ds_file ds_zero2_no_offload.json \--gradient_checkpointing \--show_loss_step 10 \--output_dir ./output-glm2

PS:ChatGLM微调时所用显存要比ChatGLM2多,详细显存占比如下:

在这里插入图片描述

注意:Lora方法在模型保存时仅保存了Lora训练参数,因此在模型预测时需要将模型参数进行合并,具体参考merge_lora.py。

全参方法

全参方法,对大模型进行全量参数训练,主要借助DeepSpeed-Zero3方法,对模型参数进行多卡分割,并借助Offload方法,将优化器参数卸载到CPU上以解决显卡不足问题。

微调代码,见train.py,核心部分如下:

model = MODE[args.mode]["model"].from_pretrained(args.model_name_or_path)

训练代码均采用DeepSpeed进行训练,可设置参数包含train_path、model_name_or_path、mode、train_type、ds_file、num_train_epochs、per_device_train_batch_size、gradient_accumulation_steps、output_dir等, 可根据自己的任务配置。

ChatGLM四卡训练,通过CUDA_VISIBLE_DEVICES控制具体哪几块卡进行训练,如果不加该参数,表示使用运行机器上所有卡进行训练

CUDA_VISIBLE_DEVICES=0,1,2,3 deepspeed --master_port 520 train.py \--train_path data/spo_0.json \--model_name_or_path ChatGLM-6B \--per_device_train_batch_size 1 \--max_len 1560 \--max_src_len 1024 \--learning_rate 1e-4 \--weight_decay 0.1 \--num_train_epochs 2 \--gradient_accumulation_steps 4 \--warmup_ratio 0.1 \--mode glm \--train_type all \--seed 1234 \--ds_file ds_zero3_offload.json \--gradient_checkpointing \--show_loss_step 10 \--output_dir ./output-glm

ChatGLM2四卡训练,通过CUDA_VISIBLE_DEVICES控制具体哪几块卡进行训练,如果不加该参数,表示使用运行机器上所有卡进行训练

CUDA_VISIBLE_DEVICES=0,1,2,3 deepspeed --master_port 520 train.py \--train_path data/spo_0.json \--model_name_or_path ChatGLM2-6B \--per_device_train_batch_size 1 \--max_len 1560 \--max_src_len 1024 \--learning_rate 1e-4 \--weight_decay 0.1 \--num_train_epochs 2 \--gradient_accumulation_steps 4 \--warmup_ratio 0.1 \--mode glm2 \--train_type all \--seed 1234 \--ds_file ds_zero3_no_offload.json \--gradient_checkpointing \--show_loss_step 10 \--output_dir ./output-glm2

PS:ChatGLM微调时所用显存要比ChatGLM2多,后面补充DeepSpeed的Zero-Stage的相关内容说明。

运行环境

cpm_kernels==1.0.11
deepspeed==0.9.0
numpy==1.24.2
peft==0.3.0
sentencepiece==0.1.96
tensorboard==2.11.0
tensorflow==2.13.0
torch==1.13.1+cu116
tqdm==4.64.1
transformers==4.27.1

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/221912.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

binkw32.dll丢失怎么办?这5个方法都可以解决binkw32.dll丢失问题

binkw32.dll文件是什么? binkw32.dll是一个动态链接库文件,它是Windows操作系统中的一个重要组件。它包含了许多用于处理多媒体文件的函数和资源,如视频、音频等。当我们在电脑上打开或播放某些多媒体文件时,系统会调用binkw32.d…

显示器件是什么

显示器件 电子元器件百科 文章目录 显示器件前言一、显示器件是什么二、显示器件的类别三、显示器件的应用实例四、显示器件的作用原理总结前言 显示器件根据不同的技术原理和应用领域,具有不同的特点和优势,可适用于电子产品、电视、计算机显示器、手持设备、汽车仪表盘等…

绿盟 SAS堡垒机 local_user.php 权限绕过漏洞复现

绿盟 SAS堡垒机 local_user.php 权限绕过漏洞复现 一、 产品简介二、漏洞概述三、 复现环境四、漏洞复现五、小龙检测 免责声明:请勿利用文章内的相关技术从事非法测试,由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失&…

全维度构建核心竞争优势,极智嘉(Geek+)连获六项大奖

近日,全球仓储机器人引领者极智嘉(Geek)一举斩获国内外六大重磅奖项,在技术实力、出海成绩到人才战略等多个维度,再度向大众展示了行业标杆的强劲实力。 首先在技术实力上,此前极智嘉与罗马尼亚医药电商Dr.MAX达成合作&#xff0…

测试用例设计方法六脉神剑——第四剑:石破天惊,功能图法攻阵

1 引言 前面几篇文章为我们讲述了因果图、判定表、正交试验等几种方法,主要是针对于不同条件输入输出的组合进行测试,但在实际需求中,我们也常会遇到需要对被测对象的状态流转进行验证的情况,此时前面几种方法将不再适用&#xf…

美国访问学者陪读签证怎么申请?

美国访问学者陪读签证是许多前往美国深造的学者及其家属关注的重要问题。如何申请这一签证,一直以来都是备受关注的话题。下面知识人网小编将为您介绍一下美国访问学者陪读签证的申请流程。 首先,申请人需要了解访问学者陪读签证的基本要求。通常情况下&…

马尔科夫预测模型(超详细,案例代码)

概述 马尔科夫预测模型是一种基于马尔科夫过程的预测方法。马尔科夫过程是一类具有马尔科夫性质的随机过程,即未来的状态只依赖于当前状态,而与过去状态无关。这种过程通常用状态空间和状态转移概率矩阵来描述。 在马尔科夫预测模型中,系统被…

Disruptor详解,Java高性能内存队列最优解

文章目录 一、Disruptor介绍1、为什么要有Disruptor2、Disruptor介绍3、Disruptor的高性能设计4、RingBuffer数据结构5、等待策略6、Disruptor在日志框架中的应用7、术语 二、Disruptor实战1、引入依赖2、Disruptor构造器3、入门实例(1)Hello World&…

浮动的魅力与挑战:如何在前端设计中巧妙运用浮动(下)

🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云…

SpringBoot的Starter自动化配置,自己编写配置maven依赖且使用及短信发送案例

目录 一、Starter机制 1. 是什么 2. 有什么用 3. 应用场景 二、短信发送案例 1. 创建 2. 配置 3. 编写 4. 形成依赖 6. 其他项目的使用 每篇一获 一、Starter机制 1. 是什么 SpringBoot中的starter是一种非常重要的机制(自动化配置),能够抛弃以前繁杂…

SD-WAN解决外贸企业网络问题

为了获取全球客户,占领更多的市场,越来越多的外贸企业出现。外贸企业在发展业务的过程中会遇到很多困难,海外网络访问问题就是其中之一。目前该问题主要有三种解决方案:VPN、MPLS专线以及SD-WAN专线。 VPN通过在公网上面建立专用网…

WPF-UI HandyControl 简单介绍

文章目录 前言我的网易云专栏和Gitee仓库HandyControlHandyControl示例相关资源地址 我的运行环境快速开始和Material Design功能对比手风琴右键菜单自动补充滚动条轮播图消息通知步骤条托盘按钮 结尾 前言 最近我在研究如何使用WPF做一个比较完整的项目,然后我就先…

SLAM学习——相机模型(针孔+鱼眼)

针孔相机模型 针孔相机模型是很常用,而且有效的模型,它描述了一束光线通过针孔之后,在针孔背面投影成像的关系,基于针孔的投影过程可以通过针孔和畸变两个模型来描述。 模型中有四个坐标系,分别为world,c…

初识GroovyShell

文章目录 前言一、GroovyShell二、maven三、解决方案四、关键代码4.1 数据库配置表(pg)4.2 入参4.3 分页查询 总结 前言 项目背景:查询多个表的数据列表和详情,但不想创建过多的po、dao、resp等项目文件。 一、GroovyShell Apache Groovy是一种强大的…

Windows下使用CMake编译lua

Lua 是一个功能强大、高效、轻量级、可嵌入的脚本语言。它支持程序编程、面向对象程序设计、函数式编程、数据驱动编程和数据描述。 Lua的官方网站上只提供了源码,需要使用Make进行编译,具体的编译方法为 curl -R -O http://www.lua.org/ftp/lua-5.4.6.…

中兴 H108NS 路由器 tools_admin.asp权限绕过漏洞复现

0x01 产品简介 中兴H108NS路由器是一款集WiFi管理、路由分配、动态获取上网连接等功能于一体的路由器产品。 0x02 漏洞概述 中兴H108NS路由器tools_admin.asp接口处存在身份认证绕过漏洞,攻击者可利用该漏洞绕过身份认证允许访问路由器的管理面板修改管理员密码,获取用户的…

虾皮选品网:如何使用虾皮选品数据软件提升您的选品策略

在虾皮(Shopee)平台上进行选品时,了解市场趋势、竞争程度和产品潜力是非常重要的。为了帮助卖家更好地分析虾皮市场,并为选品和运营策略提供有力支持,有一些数据软件和工具可以派上用场。本文将介绍一些建议使用的虾皮…

HPM5300系列--第二篇 Visual Studio Code开发环境以及多种调试器调试模式

一、目的 在博文《HPM5300系列--第一篇 命令行开发调试环境搭建》、《HPM6750系列--第四篇 搭建Visual Studio Code开发调试环境》中我们介绍了命令行方式开发环境,也介绍了HPM6750evkmini开发板如何使用Visual Studio Code进行开发调试(其中调试方式使用…

Power BI - 5分钟学习增加条件列

每天5分钟,今天介绍Power BI增加条件列。 什么是增加条件列? 简单理解,可以根据表中某列设置一个或者多个条件,判定的结果会生成一个新列。 举例: 首先,导入一张【Sales】样例表(Excel数据源导入请参考每…

深入理解C语言的函数参数

1、一个简单的函数 int Add(int x, int y) {return x y; }int main() {printf("%d", Add(2, 3, 4, 5, 6));return 0; } 这一段足够简单的代码,闭眼都能知道运行结果会在屏幕上打印 5 。那编译器是怎么处理后面的 4、5、6 ? 我们再看看这个函…