ChatGLM 6B 部署及微调 【干货】

news2024/11/27 0:23:21

代码地址模型地址、安装环境:Ubuntu20.04,RTX3060 12G

一、部署

1.1 下载代码

cd /opt
git clone https://github.com/THUDM/ChatGLM2-6B

1.2 下载模型

将模型下载后放到项目文件夹内

git lfs install # 确认安装了lfs,或者直接到项目地址点击下载
git clone https://huggingface.co/THUDM/chatglm2-6b

1.3 拉取依赖

pip3 install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
pip3 install tensorboard gradio mdtex2html -i https://pypi.tuna.tsinghua.edu.cn/simple

1.4 NVIDIA显卡驱动安装

找不到驱动
nvidia-smi # 输入指令>>>
NVIDIA-SMI has failed because it couldn't communicate with the NVIDIA driver. Make sure that the latest NVIDIA driver is installed and running.
查看内核版本
uname -r
下载新的内核
sudo apt-get install linux-generic-hwe-20.04 #这个是下载新的内核版本
删掉旧NVIDIA驱动
$ sudo apt-get purge libnvidia*
$ sudo apt-get purge nvidia*
下载驱动
$ sudo dpkg --list | grep nvidia      #找版本
$ ubuntu-drivers devices #这样也行。
安装驱动
$ sudo add-apt-repository ppa:graphics-drivers/ppa
$ sudo apt-get update
$ sudo apt-get install nvidia-driver-535
$ sudo prime-select nvidia
# ------------- 如果上面有报错的话 -----------------------
$ sudo apt-get install --reinstall nvidia-driver-535
# -------------------------------------------------------
$ reboot # 重启
查看驱动
$ nvidia-smi

1.5 修改测试文件

1.5.1 修改模型地址

web_demo.py中的"THUDM/chatglm2-6b"模型地址指向保存的模型地址"/opt/ChatGlm6B2/model"

1.5.2 按性能选择模型载入
# 全精度全加载
model = AutoModel.from_pretrained("/opt/ChatGlm6B2/model", trust_remote_code=True).cuda()
# 半精度全加载
model = AutoModel.from_pretrained("/opt/ChatGlm6B2/model", trust_remote_code=True).half().cuda()
# 半精度8bit量化
model = AutoModel.from_pretrained("/opt/ChatGlm6B2/model", trust_remote_code=True).quantize(8).half().cuda()
# 半精度4bit量化
model = AutoModel.from_pretrained("/opt/ChatGlm6B2/model", trust_remote_code=True).quantize(4).half().cuda()
1.5.3 修改启动端口
# demo.queue().launch(share=False, inbrowser=True)
demo.queue().launch(share=True, inbrowser=True, server_name='127.0.0.1', server_port=8080)
1.5.4 gradio无法构建可访问链接
下载文件:
wget https://cdn-media.huggingface.co/frpc-gradio-0.2/frpc_linux_amd64
重命名下载的文件:
mv frpc_linux_amd64 frpc_linux_amd64_v0.2
将文件移动到指定位置:
mv frpc_linux_amd64_v0.2 /root/.virtualenvs/glm/lib/python3.8/site-packages/gradio
找到文件
cd /root/.virtualenvs/glm/lib/python3.8/site-packages/gradio
授予权限
chmod 777 frpc_linux_amd64_v0.2

1.6 测试运行

# Gradio 启动
workon glm
cd /opt/ChatGlm6B2
python3 web_demo.py
# --------------------------------------------------------------------
python3 /opt/ChatGlm6B2/web_demo.py

# 或者 Streamlit 启动
workon glm
cd /opt/ChatGlm6B2
streamlit run web_demo2.py --server.port 8080
# --------------------------------------------------------------------
streamlit run /opt/ChatGlm6B2/web_demo2.py --server.port 8080

二、P-Tuning v2 微调

2.1 安装依赖

# 除了部署需要的依赖之外,还需要安装以下依赖
pip install rouge_chinese nltk jieba datasets transformers[torch] -i https://pypi.douban.com/simple/

2.2 下载数据集

2.2.1 编写数据

参考 answers.xlsxdev.xlsx 编写自己的数据

2.2.2 生成json数据

使用 GetPrompts.py、或者使用打包好的 GetPrompts.exe 将数据转化为json,其中history默认按,分隔

2.2.3 移入文件夹

将整理好的数据集移入文件夹,参考执行脚本中即将配置的路径../answers.json../dev.json,将文件放到以下位置

/opt/ChatGlm6B2/answers.json
/opt/ChatGlm6B2/dev.json

完整文件结构

/opt/ChatGlm6B2
	/model
	/output
	answers.json
	dev.json
	/ptuning
		main.py
		train_chat.sh
		…
	…

2.3 修改微调脚本

# /opt/ChatGlm6B2/ptuning/train_chat.sh

# torchrun命令运行PyTorch训练脚本:
# torchrun: 运行PyTorch --standalone以独立模式运行(即在单个节点上运行,而不是在分布式环境中运行) --nnodes=1 指定节点的数量为1(即单节点运行) --nproc-per-node=$NUM_GPUS 指定每个节点上的进程数(GPU的数量) main.py 运行的PyTorch训练脚本
# do_train: 指定进行训练。
# train_file $CHAT_TRAIN_DATA: 指定训练数据文件的路径。
# validation_file $CHAT_VAL_DATA: 指定验证数据文件的路径。
# preprocessing_num_workers 10: 指定预处理数据时使用的工作进程数。
# prompt_column prompt: 指定数据中包含提示的列名。
# response_column response: 指定数据中包含响应的列名。
# history_column history: 指定数据中包含历史对话的列名。
# overwrite_cache: 指定是否覆盖缓存的预处理数据。
# model_name_or_path THUDM/chatglm2-6b: 指定模型的名称或路径,这里使用了一个预训练的聊天生成模型。
# output_dir $CHECKPOINT_NAME: 指定输出目录的路径。
# overwrite_output_dir: 指定是否覆盖输出目录。
# max_source_length 256: 指定输入序列的最大长度。
# max_target_length 256: 指定目标序列的最大长度。
# per_device_train_batch_size 1: 指定每个设备的训练批次大小。
# per_device_eval_batch_size 1: 指定每个设备的评估批次大小。
# gradient_accumulation_steps 16: 指定梯度累积的步数。
# predict_with_generate: 指定在生成模式下进行预测。
# max_steps 3000: 指定训练的最大步数。
# logging_steps 10: 指定每隔多少步打印一次日志。
# save_steps 1000: 指定每隔多少步保存一次模型。
# learning_rate $LR: 指定学习率,其中`$LR`是一个环境变量,用于指定学习率的值。
# pre_seq_len $PRE_SEQ_LEN: 指定预处理序列的长度,用于指定预处理序列的长度。
# quantization_bit 4: 指定量化的位数。

PRE_SEQ_LEN=128
LR=1e-2
NUM_GPUS=1
# 对话数据
CHAT_TRAIN_DATA=../answers.json
# 验证数据
CHAT_VAL_DATA=../dev.json
# 保存路径
CHECKPOINT_NAME=../output
# 模型路径
MODEL_PATH=../model
# 训练最大步数 3000默认
MAX_STEP=500
# 一个巨坑:为了加快速度,减小了MAX_STEP,但是保存步长还是1000,未达到保存条件没保存模型文件,重头来过
# 保存步长
SAVE_STEP=100

torchrun --standalone --nnodes=1 --nproc-per-node=$NUM_GPUS main.py \
    --do_train \
    --train_file $CHAT_TRAIN_DATA \
    --validation_file $CHAT_VAL_DATA \
    --preprocessing_num_workers 10 \
    --prompt_column prompt \
    --response_column response \
    --history_column history \
    --overwrite_cache \
    --model_name_or_path $MODEL_PATH \
    --output_dir $CHECKPOINT_NAME/chatglm-6b-pt-$PRE_SEQ_LEN-$LR \
    --overwrite_output_dir \
    --max_source_length 512 \
    --max_target_length 512 \
    --per_device_train_batch_size 1 \
    --per_device_eval_batch_size 1 \
    --gradient_accumulation_steps 16 \
    --predict_with_generate \
    --max_steps $MAX_STEP \
    --logging_steps 10 \
    --save_steps $SAVE_STEP \
    --learning_rate $LR \
    --pre_seq_len $PRE_SEQ_LEN \
    --quantization_bit 4

2.4 执行微调脚本

workon glm
cd /opt/ChatGlm6B2/ptuning
sh train_chat.sh                      # bash train_chat.sh
---------------------------------------------------------------
nohup sh train_chat.sh > output.log   # 后台执行 | 不生效

2.5 修改评估脚本

评估模型质量,可跳过

# /opt/ChatGlm6B2/ptuning/evaluate.sh
# model_name_or_path:原始ChatGLM-6B模型文件路径
# ptuning_checkpoint:训练完成后,生成的文件目录

LR=1e-2
PRE_SEQ_LEN=128
NUM_GPUS=1
# 验证数据
CHAT_VAL_DATA=../dev.json
# 保存路径
CHECKPOINT_NAME=../output
# 模型路径
MODEL_PATH=../model
# 最大步数
MAX_STEP=500

torchrun --standalone --nnodes=1 --nproc-per-node=$NUM_GPUS main.py \
    --do_predict \
    --validation_file $CHAT_VAL_DATA \
    --test_file $CHAT_VAL_DATA \
    --overwrite_cache \
    --prompt_column prompt \
    --response_column response \
    --history_column history \
    --model_name_or_path $MODEL_PATH \
    --ptuning_checkpoint $CHECKPOINT_NAME/chatglm-6b-pt-$PRE_SEQ_LEN-$LR/checkpoint-$MAX_STEP \
    --output_dir $CHECKPOINT_NAME/chatglm-6b-pt-$PRE_SEQ_LEN-$LR \
    --overwrite_output_dir \
    --max_source_length 64 \
    --max_target_length 64 \
    --per_device_eval_batch_size 1 \
    --predict_with_generate \
    --pre_seq_len $PRE_SEQ_LEN \
    --quantization_bit 4

2.6 执行评估脚本

workon glm
cd /opt/ChatGlm6B2/ptuning
sh evaluate.sh                      # bash evaluate.sh

2.7 测试模型效果

修改web_demo.pyweb_demo2.py中的模型引入

原模型引入
tokenizer = AutoTokenizer.from_pretrained("/opt/ChatGlm6B2/model", trust_remote_code=True)                             # 载入Tokenizer
model = AutoModel.from_pretrained("/opt/ChatGlm6B2/model", trust_remote_code=True).quantize(8).cuda()                  # 全精度8bit量化
# model = AutoModel.from_pretrained("/opt/ChatGlm6B2/model", trust_remote_code=True).cuda()                            # 全精度全加载
# model = AutoModel.from_pretrained("/opt/ChatGlm6B2/model", trust_remote_code=True).half().cuda()                     # 半精度全加载
# model = AutoModel.from_pretrained("/opt/ChatGlm6B2/model", trust_remote_code=True).quantize(8).half().cuda()         # 半精度8bit量化
# model = AutoModel.from_pretrained("/opt/ChatGlm6B2/model", trust_remote_code=True).quantize(4).half().cuda()         # 半精度4bit量化
## 多显卡支持,使用下面两行代替上面一行,将num_gpus改为你实际的显卡数量
## from utils import load_model_on_gpus
## model = load_model_on_gpus("/opt/ChatGlm6B2/model", num_gpus=2)
model = model.eval()
修改后模型引入
tokenizer = AutoTokenizer.from_pretrained("/opt/ChatGlm6B2/model", trust_remote_code=True)                             # 载入Tokenizer

# 加载的 P-Tuning 的 checkpoint:
# 注意: 将 pre_seq_len 改成训练时的实际值。
# /opt/ChatGlm6B2/model 指向本地的模型路径(注意不是checkpoint路径)
# /opt/ChatGlm6B2/output/chatglm-6b-pt-128-1e-2/checkpoint-500 指向生成的微调模型文件路径
config = AutoConfig.from_pretrained("/opt/ChatGlm6B2/model", trust_remote_code=True, pre_seq_len=128)
model = AutoModel.from_pretrained("/opt/ChatGlm6B2/model", config=config, trust_remote_code=True)
prefix_state_dict = torch.load(os.path.join("/opt/ChatGlm6B2/output/chatglm-6b-pt-128-1e-2/checkpoint-500", "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)

## 如果需要加载的是全参数微调的 checkpoint,则直接加载整个 checkpoint:
## model = AutoModel.from_pretrained("/opt/ChatGlm6B2/output/chatglm-6b-pt-128-1e-2/checkpoint-500", trust_remote_code=True)

## 之后根据需求可以进行量化,也可以直接使用:
model = model.quantize(8)
model = model.cuda()
model = model.eval()
执行
workon glm
python3 /opt/ChatGlm6B2/web_demo.py                           # Gradio 启动
streamlit run /opt/ChatGlm6B2/web_demo2.py --server.port 8080 # 或者 Streamlit 启动

三、接口调用

3.1 接口脚本

from fastapi import FastAPI, Request
from transformers import AutoConfig, AutoModel, AutoTokenizer
import uvicorn, json, datetime
import torch
import os

DEVICE = "cuda"
DEVICE_ID = "0"
CUDA_DEVICE = f"{DEVICE}:{DEVICE_ID}" if DEVICE_ID else DEVICE

def torch_gc():
    if torch.cuda.is_available():
        with torch.cuda.device(CUDA_DEVICE):
            torch.cuda.empty_cache()
            torch.cuda.ipc_collect()

app = FastAPI()

@app.post("/")
async def create_item(request: Request):
    global model, tokenizer
    json_post_raw = await request.json()
    json_post = json.dumps(json_post_raw)
    json_post_list = json.loads(json_post)
    prompt = json_post_list.get('prompt')
    history = json_post_list.get('history')
    max_length = json_post_list.get('max_length')
    top_p = json_post_list.get('top_p')
    temperature = json_post_list.get('temperature')
    response, history = model.chat(tokenizer,
                                   prompt,
                                   history=history,
                                   max_length=max_length if max_length else 2048,
                                   top_p=top_p if top_p else 0.7,
                                   temperature=temperature if temperature else 0.95)
    now = datetime.datetime.now()
    time = now.strftime("%Y-%m-%d %H:%M:%S")
    answer = {
        "response": response,
        "history": history,
        "status": 200,
        "time": time
    }
    log = "[" + time + "] " + '", prompt:"' + prompt + '", response:"' + repr(response) + '"'
    print(log)
    torch_gc()
    return answer


if __name__ == '__main__':
    # ------------------------------------------------------------------------------------------------------------------------------------------
    # 使用原模型参数
    # tokenizer = AutoTokenizer.from_pretrained("/opt/ChatGlm6B2/model", trust_remote_code=True)
    # # model = AutoModel.from_pretrained("/opt/ChatGlm6B2/model", trust_remote_code=True).cuda()                            # 全精度全加载
    # model = AutoModel.from_pretrained("/opt/ChatGlm6B2/model", trust_remote_code=True).quantize(8).cuda()                  # 全精度全加载
    # # model = AutoModel.from_pretrained("/opt/ChatGlm6B2/model", trust_remote_code=True).half().cuda()                     # 半精度全加载
    # # model = AutoModel.from_pretrained("/opt/ChatGlm6B2/model", trust_remote_code=True).quantize(8).half().cuda()         # 半精度8bit量化
    # # model = AutoModel.from_pretrained("/opt/ChatGlm6B2/model", trust_remote_code=True).quantize(4).half().cuda()         # 半精度4bit量化
    # # 多显卡支持,使用下面两行代替上面一行,将num_gpus改为你实际的显卡数量
    # # from utils import load_model_on_gpus
    # # model = load_model_on_gpus("/opt/ChatGlm6B2/model", num_gpus=2)
    # ------------------------------------------------------------------------------------------------------------------------------------------
    # 使用微调后参数
    tokenizer = AutoTokenizer.from_pretrained("/opt/ChatGlm6B2/model", trust_remote_code=True)                             # 载入Tokenizer
    # 加载的 P-Tuning 的 checkpoint:
    # 注意: 将 pre_seq_len 改成训练时的实际值。
    # /opt/ChatGlm6B2/model 指向本地的模型路径(注意不是checkpoint路径)
    # /opt/ChatGlm6B2/output/chatglm-6b-pt-128-1e-2/checkpoint-500 指向生成的微调模型文件路径
    config = AutoConfig.from_pretrained("/opt/ChatGlm6B2/model", trust_remote_code=True, pre_seq_len=128)
    model = AutoModel.from_pretrained("/opt/ChatGlm6B2/model", config=config, trust_remote_code=True)
    prefix_state_dict = torch.load(os.path.join("/opt/ChatGlm6B2/output/chatglm-6b-pt-128-1e-2/checkpoint-500", "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)
    ## 如果需要加载的是全参数微调的 checkpoint,则直接加载整个 checkpoint:
    ## model = AutoModel.from_pretrained("/opt/ChatGlm6B2/output/chatglm-6b-pt-128-1e-2/checkpoint-500", trust_remote_code=True)
    # 之后根据需求可以进行量化,也可以直接使用:
    model = model.quantize(8)
    model = model.cuda()
    # ------------------------------------------------------------------------------------------------------------------------------------------
    model.eval()
    uvicorn.run(app, host='0.0.0.0', port=8080, workers=1)

3.2 执行脚本

workon glm
python /opt/ChatGlm6B2/web_demo.py
# 挂载后台执行
nohup /root/.virtualenvs/glm/bin/python /opt/ChatGlm6B2/api.py > /opt/ChatGlm6B2/output.log 2>&1 &
nohup /root/.virtualenvs/glm/bin/python /opt/ChatGlm6B2/openai_api.py > /opt/ChatGlm6B2/apilog.log 2>&1 &
# 终止
ps aux | grep api.py
kill PID

3.3 调用接口


3.4 Vue调用

代理转发
const path = require('path')
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
  devServer: {
    proxy: {
      '/chatglm': { // 部署前 取消注释
        target: 'http://127.0.0.1:8080/', // API服务器的地址
        // ws: true, // 如果要代理 websockets,配置这个参数
        changeOrigin: true, // 是否跨域
        pathRewrite: {
          '^/chatglm': ''
        }
      },
    }
  }
})

部署后使用Nginx代理

# vi /etc/nginx/nginx.conf

server {
    listen 8080;                                # 前端项目开放监听端口
    server_name 127.0.0.1;                    # 前端项目开放ip/域名
    location / {                                # 默认根路径
        root   /var/www/chat/;                  # build文件的位置
        try_files $uri $uri/ /index.html;       # 内部文件重定向
    }
	location / chatglm {                                # 默认根路径
        proxy_redirect off;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade"; 
        proxy_connect_timeout 1800s;
        proxy_send_timeout 1800s;
        proxy_read_timeout 1800s; 
        proxy_pass http://127.0.0.1:8080/;
    }
}
封装函数
import axios from 'axios'
import { message } from 'element-ui'

export async function postChat(prompt, history=[], max_length=1000, top_p=0.8, temperature=0.9) {
    const { data: res } = await axios.post( '/chatglm',
        {
            "prompt": prompt,
            "history": history,
            "max_length": max_length,
            "top_p": top_p,
            "temperature": temperature
        }
    )
    console.log(res)
    if (res.status !== 200) {
        return message.error('接口异常,请重新尝试或联系管理员!')
    }
}
调用函数
<script>
import { postChat } from '@/api/ChatApi.js'
export default {
    data() {
        return {}
    },
    created(){
        postChat("你好")
    },
}
</script>

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

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

相关文章

基于ssm的网上订餐系统

一、系统架构 前端&#xff1a;jsp | js | css | jquery 后端&#xff1a;spring | springmvc | mybatis 环境&#xff1a;jdk1.7 | mysql | maven | tomcat 二、代码与数据库 三、功能介绍 01. web端-首页 02. web端-我的餐车 03. web端-我的订单 04. web端-用户中心 05. web…

西门子PLC与组态王无线通讯中如何设置从站

本方案主要详述了在多台西门子300PLC与组态王之间Modbus无线通讯中如何设置从站。方案中所用到的无线通讯终端是DTD434MC——欧美系PLC专用无线通讯终端。 一、方案概述 无线Modbus网络组成如下&#xff1a; 二、测试背景 ● PC端组态软件版本&#xff1a;组态王6.55 ● 默…

tomcat-pass-getshell 弱口令 漏洞复现

tomcat-pass-getshell 弱口令 漏洞复现 名称: tomcat-pass-getshell 弱口令 描述: Tomcat是Apache 软件基金会&#xff08;Apache Software Foundation&#xff09;的Jakarta 项目中的一个核心项目&#xff0c;由Apache、Sun 和其他一些公司及个人共同开发而成。 通过弱口令登…

2024 IEEE Fellow名单公布,上百位华人学者入选!

就在近日&#xff0c;美国电子电气工程师学会&#xff08;Institute of Electrical and Electronic Engineers&#xff0c;IEEE&#xff09;公布了新一届Fellow名单。 IEEE Fellow为学会最高等级会员&#xff0c;是IEEE授予成员的最高荣誉&#xff0c;旨在表彰那些在电气、电子…

内网隧道学习

默认密码&#xff1a;hongrisec2019 一.环境搭建 网卡学习 一个网卡一个分段&#xff0c;想象成一个管道 192.168.52一段 192.168.150一段 仅主机模式保证不予外界连通&#xff0c;保证恶意操作不会跑到真实机之上 52段是内部通信&#xff0c;150段属于服务器&#xff08;…

23款奔驰E300L升级23P驾驶辅助 智驾出行 缓解开车疲劳

辅助驾驶越来越多的被大家所青睐&#xff01;为了提升驾驶安全性和舒适便捷性奔驰改装原厂半自动驾驶23P辅助系统 23P智能辅助驾驶系统还是很有必要的&#xff0c;因为在跑高速的时候可以使用23P智能驾驶的自动保持车速&#xff0c;保持车距&#xff0c;车道自动居中行驶以及自…

小型内衣洗衣机什么牌子好?口碑最好的小型洗衣机

很多人会觉得内衣洗衣机是智商税&#xff0c;洗个内衣只需要两分钟的事情&#xff0c;需要花个几百块钱去入手一个洗衣机吗&#xff1f;然而清洗贴身衣物的并不是一件简单的事情&#xff0c;如果只是简单的搓洗&#xff0c;内裤上看不见的细菌也无法消除&#xff0c;而且对来生…

英特尔工作站:助力专业用户实现高效创作

原创 | 文 BFT机器人 英特尔工作站是由全球知名的英特尔公司设计和开发的一款计算平台。英特尔在工作站处理器领域将其产品分为性能型和移动型两类&#xff0c;它的诞生旨在满足专业用户在科学、工程、设计等领域对高性能计算的需求。英特尔工作站配备了最新的英特尔处理器、大…

关于卸载亚信安全防火墙软件

电脑根据需求上安装亚信安全防火墙,不需要时,要卸载需要密码 关于卸载亚信安全防火墙客户端-适用于win10和win11的方法(系统64位). 亲测有效: 1.电脑上winR,运行输入msconfig 2.勾选引导中的安全引导,然后重新启动,进入安全模式. 3.winR输入regedit,打开注册表编辑器进入/Mis…

苹果用户如何恢复手机数据?盘点3个实用方法!

随着手机功能的不断增强和应用程序的不断丰富&#xff0c;人们越来越依赖手机&#xff0c;离不开手机。然而&#xff0c;有时因为误操作、系统故障或者数据丢失等原因&#xff0c;我们需要找回手机上丢失的数据。那么&#xff0c;苹果用户如何恢复手机数据呢&#xff1f;本文将…

java开发必备的Vue知识点和技能

vue介绍 什么是Vue&#xff1f;vue就是一款用于构建用户界面的渐进式的JavaScript框架。&#xff08;官方&#xff1a;https://cn.vuejs.org/&#xff09; 框架&#xff1a;就是一套完整的项目解决方案&#xff0c;用于快速构建项目。 优点&#xff1a;大大提升前端项目的开…

Java基础之集合类

Java基础之集合类 一、集合的框架1.1、集合概述1.2、集合与数组区别1.3、数组的缺点&#xff1a;1.4、常用集合分类1.5、Collection常用方法 二、List集合2.1、ArrayList2.2、LinkedList2.3、Vector2.4、区别 三、Set集合3.1、HashSet集合3.2、LinkedHashSet集合3.3、TreeSet集…

终于等到你!常用的组织架构图模板,高清图片一键导出

组织架构图是一种用来展示一个组织内部人员和职责关系的图表。通过组织架构图&#xff0c;我们可以清晰地了解一个组织的层级架构和各个部门之间的关系。在本文中&#xff0c;我们将向大家推荐8个常用的组织架构图模板&#xff0c;帮助你快速制作出专业的组织架构图。 1. 市场营…

数据结构——动态规划

动态规划&#xff1a;有很多重叠子问题&#xff0c;每一个状态一定是由上一个状态推导出来的 贪心&#xff1a;没有状态推导&#xff0c;而是从局部直接选最优的 动规五步曲&#xff1a; 确定dp数组&#xff08;dp table&#xff09;以及下标的含义 确定递推公式&#xff08;容…

招投标信息可以用CRM系统来查看吗?

对于B2B企业来说获客难、获客成本高是共识。做大客户的企业通过招投标获取商机是一个重要获客途径&#xff0c;然而传统方式管理招投标信息问题很多&#xff0c;例如资料丢失、手工录入出错、信息分散、信息查找费时费力。为了解决这些难题小编推荐CRM系统&#xff0c;CRM系统需…

非参数估计与参数估计的区别,以及详细列举了常用的非参数估计方法和参数估计方法,一网打尽非参数估计与参数估计!!!

文章目录 前言一、非参数估计与参数估计的区别二、常用的非参数估计方法三、常用的参数估计方法总结 前言 非参数估计和参数估计是统计学中的两种不同的估计方法。 一、非参数估计与参数估计的区别 参数估计是指&#xff0c;对于已知分布形式的数据&#xff0c;根据样本数据…

WinEdt打开.tex文件显示error reading错误

原因&#xff1a; 是因为.tex文件中包含了utf-8字符&#xff0c;而在打开的时候并没有指明utf-8打开方式 解决方法 在WinEdt中&#xff0c;【File】-【Open】&#xff08;或使用快捷键CtrlO&#xff09;&#xff0c;在弹出的打开对话框中&#xff0c;右下角【文件名】右侧有…

全面探讨HTTP协议从0.9到3.0版本的发展和特点

前言&#xff1a; 最近的几场面试都问到了http的相关知识点&#xff0c;博主在此结合书籍和网上资料做下总结。本篇文章讲收录到秋招专题&#xff0c;该专栏比较适合刚入坑Java的小白以及准备秋招的大佬阅读。 如果文章有什么需要改进的地方欢迎大佬提出&#xff0c;对大佬有帮…

EI期刊论文复现:考虑电动汽车可调度潜力的充电站两阶段市场投标策略程序代码!

本程序代码参考EI期刊论文《考虑电动汽车可调度潜力的充电站两阶段市场投标策略》&#xff0c;程序中基于历史数据评估可调度潜力&#xff0c;由联合报价模型确定节点边际电价&#xff0c;作为报价的参考&#xff0c;包含个体竞价模式&#xff0c;纳什博弈竞价&#xff0c;算例…

PC8231(CC/CV)5V/2.4A同步降压芯片 频率可调 限流欠压补偿

一&#xff0e;概述 PC8231 是一款同步降压转换器&#xff0c; 该转换器可驱动输出 2.4A 负载电流。 设计允许 PC8231 在 9V 到40V 宽输入电压范围内工作。通过将 COMP/EN 引脚逻辑电平拉低来实现外部关断功能&#xff0c;并进入待机模式。外部补偿使反馈控制环路具有良好的线…