当前位置: 首页 > news >正文

VLM(视觉语言模型)与DeepSeek R1(奖励机制)如何结合

VLM(视觉语言模型)与DeepSeek R1(奖励机制)如何结合

flyfish

VLM的传统训练依赖于监督学习(直接拟合问答对),而规则奖励函数通常用于强化学习(通过试错和奖励反馈优化策略)。这两种方式如何结合?

源码来自
VLM-R1/src/open-r1-multimodal/src/open_r1/grpo_rec.py

# 导入 debugpy 库,用于调试,当前代码中被注释掉,若需要调试可取消注释
# import debugpy
# try:
#     # 5678 是 VS Code 调试配置中的默认附加端口。除非指定主机和端口,否则主机默认为 127.0.0.1
#     debugpy.listen(("localhost", 9501))
#     print("Waiting for debugger attach")
#     debugpy.wait_for_client()
# except Exception as e:
#     pass# 导入操作系统相关功能的库
import os
# 导入正则表达式库,用于字符串匹配和处理
import re
# 导入日期时间处理库
from datetime import datetime
# 导入数据类装饰器和字段定义类,用于定义数据类
from dataclasses import dataclass, field
# 导入可选类型注解,用于表示某个参数可以为 None
from typing import Optional# 导入 Pillow 库中的 Image 类,用于处理图像
from PIL import Image
# 导入 PyTorch 中的数据集基类
from torch.utils.data import Dataset
# 导入 Qwen2VL 条件生成模型
from transformers import Qwen2VLForConditionalGeneration# 导入自定义的数学验证模块中的解析和验证函数
from math_verify import parse, verify
# 导入自定义的 Qwen2VLGRPOTrainer 类
from open_r1.trainer import Qwen2VLGRPOTrainer
# 导入 TRL 库中的 GRPO 配置、训练器、模型配置、脚本参数、解析器和 PEFT 配置获取函数
from trl import GRPOConfig, GRPOTrainer, ModelConfig, ScriptArguments, TrlParser, get_peft_config
# 导入 Transformers 库中的训练参数类
from transformers import TrainingArguments
# 导入 YAML 文件处理库
import yaml
# 导入 JSON 文件处理库
import json
# 导入随机数生成库
import random
# 导入数学计算库
import math# ----------------------- 修复当前版本 transformers 中的 flash attention 错误 -----------------------
# 导入 Qwen2_5_VL 模型中的相关类和函数
from transformers.models.qwen2_5_vl.modeling_qwen2_5_vl import Qwen2_5_VLVisionFlashAttention2, apply_rotary_pos_emb_flashatt, flash_attn_varlen_func
# 导入 PyTorch 库
import torch
# 导入元组类型注解
from typing import Tuple# 自定义 Qwen2_5_VLVisionFlashAttention2 类的前向传播函数
def custom_forward(self,hidden_states: torch.Tensor,cu_seqlens: torch.Tensor,rotary_pos_emb: Optional[torch.Tensor] = None,position_embeddings: Optional[Tuple[torch.Tensor, torch.Tensor]] = None,) -> torch.Tensor:# 获取隐藏状态的序列长度seq_length = hidden_states.shape[0]# 通过 qkv 层得到查询、键、值张量,并进行形状调整和维度置换q, k, v = self.qkv(hidden_states).reshape(seq_length, 3, self.num_heads, -1).permute(1, 0, 2, 3).unbind(0)# 如果没有提供位置嵌入,则根据旋转位置嵌入计算余弦和正弦值if position_embeddings is None:# 打印一次警告信息,提示 RoPE 嵌入计算方式的变化logger.warning_once("The attention layers in this model are transitioning from computing the RoPE embeddings internally ""through `rotary_pos_emb` (2D tensor of RoPE theta values), to using externally computed ""`position_embeddings` (Tuple of tensors, containing cos and sin). In v4.54 `rotary_pos_emb` will be ""removed and `position_embeddings` will be mandatory.")# 拼接旋转位置嵌入emb = torch.cat((rotary_pos_emb, rotary_pos_emb), dim=-1)# 计算余弦值cos = emb.cos().float()# 计算正弦值sin = emb.sin().float()else:# 从位置嵌入中获取余弦和正弦值cos, sin = position_embeddings# 将余弦值转换为浮点类型cos = cos.to(torch.float)# 将正弦值转换为浮点类型sin = sin.to(torch.float)# 应用旋转位置嵌入到查询和键张量q, k = apply_rotary_pos_emb_flashatt(q.unsqueeze(0), k.unsqueeze(0), cos, sin)# 去除查询张量的额外维度q = q.squeeze(0)# 去除键张量的额外维度k = k.squeeze(0)# 计算最大序列长度max_seqlen = (cu_seqlens[1:] - cu_seqlens[:-1]).max().item()# 调用 flash 注意力函数计算注意力输出attn_output = flash_attn_varlen_func(q, k, v, cu_seqlens, cu_seqlens, max_seqlen, max_seqlen).reshape(seq_length, -1)# 通过投影层得到最终的注意力输出attn_output = self.proj(attn_output)return attn_output# 将自定义的前向传播函数赋值给 Qwen2_5_VLVisionFlashAttention2 类的 forward 方法
Qwen2_5_VLVisionFlashAttention2.forward = custom_forward# ----------------------- 主脚本 -----------------------
# 定义 GRPOScriptArguments 数据类,继承自 ScriptArguments
@dataclass
class GRPOScriptArguments(ScriptArguments):"""用于 GRPO 训练脚本的脚本参数。参数:reward_funcs (`list[str]`):奖励函数列表。可能的值: 'accuracy', 'format'。"""# 奖励函数列表,默认包含 'accuracy' 和 'format'reward_funcs: list[str] = field(default_factory=lambda: ["accuracy", "format"],metadata={"help": "List of reward functions. Possible values: 'accuracy', 'format'"})# 图像的最大像素数,默认为 12845056max_pixels: Optional[int] = field(default=12845056,metadata={"help": "Maximum number of pixels for the image"})# 图像的最小像素数,默认为 3136min_pixels: Optional[int] = field(default=3136,metadata={"help": "Minimum number of pixels for the image"})# 图像的根目录,默认为 Noneimage_root: Optional[str] = field(default=None,metadata={"help": "Root directory of the image"})# 定义系统提示信息,用于指导模型的对话生成
SYSTEM_PROMPT = ("A conversation between User and Assistant. The user asks a question, and the Assistant solves it. The assistant ""first thinks about the reasoning process in the mind and then provides the user with the answer. The reasoning ""process and answer are enclosed within <think> </think> and <answer> </answer> tags, respectively, i.e., ""<think> reasoning process here </think><answer> answer here </answer>"
)# 定义 LazySupervisedDataset 类,继承自 Dataset
class LazySupervisedDataset(Dataset):def __init__(self, data_path: str, script_args: GRPOScriptArguments):# 调用父类的构造函数super(LazySupervisedDataset, self).__init__()# 保存脚本参数self.script_args = script_args# 初始化数据字典列表self.list_data_dict = []# 如果数据文件是 YAML 格式if data_path.endswith(".yaml"):# 打开 YAML 文件with open(data_path, "r") as file:# 加载 YAML 数据yaml_data = yaml.safe_load(file)# 获取数据集列表datasets = yaml_data.get("datasets")# 文件格式应为:# datasets:#   - json_path: xxxx1.json#     sampling_strategy: first:1000#   - json_path: xxxx2.json#     sampling_strategy: end:3000#   - json_path: xxxx3.json#     sampling_strategy: random:999# 遍历每个数据集for data in datasets:# 获取 JSON 文件路径json_path = data.get("json_path")# 获取采样策略,默认为 'all'sampling_strategy = data.get("sampling_strategy", "all")# 初始化采样数量为 Nonesampling_number = None# 如果 JSON 文件是 JSONL 格式if json_path.endswith(".jsonl"):# 初始化当前数据字典列表cur_data_dict = []# 打开 JSONL 文件with open(json_path, "r") as json_file:# 逐行读取文件for line in json_file:# 解析每行 JSON 数据并添加到当前数据字典列表cur_data_dict.append(json.loads(line.strip()))# 如果 JSON 文件是 JSON 格式elif json_path.endswith(".json"):# 打开 JSON 文件with open(json_path, "r") as json_file:# 加载 JSON 数据到当前数据字典列表cur_data_dict = json.load(json_file)else:# 如果文件类型不支持,抛出异常raise ValueError(f"Unsupported file type: {json_path}")# 如果采样策略包含冒号if ":" in sampling_strategy:# 分割采样策略和采样数量sampling_strategy, sampling_number = sampling_strategy.split(":")# 如果采样数量包含百分比符号if "%" in sampling_number:# 计算采样数量sampling_number = math.ceil(int(sampling_number.split("%")[0]) * len(cur_data_dict) / 100)else:# 将采样数量转换为整数sampling_number = int(sampling_number)# 应用采样策略if sampling_strategy == "first" and sampling_number is not None:# 取前 sampling_number 个样本cur_data_dict = cur_data_dict[:sampling_number]elif sampling_strategy == "end" and sampling_number is not None:# 取后 sampling_number 个样本cur_data_dict = cur_data_dict[-sampling_number:]elif sampling_strategy == "random" and sampling_number is not None:# 随机打乱样本random.shuffle(cur_data_dict)# 取前 sampling_number 个样本cur_data_dict = cur_data_dict[:sampling_number]# 打印从当前 JSON 文件加载的样本数量print(f"Loaded {len(cur_data_dict)} samples from {json_path}")# 将当前数据字典列表添加到总数据字典列表self.list_data_dict.extend(cur_data_dict)else:# 如果文件类型不支持,抛出异常raise ValueError(f"Unsupported file type: {data_path}")def __len__(self):# 返回数据字典列表的长度return len(self.list_data_dict)def __getitem__(self, i):# 定义将示例转换为对话格式的函数def make_conversation(example):return {"prompt": [{"role": "system", "content": SYSTEM_PROMPT},{"role": "user", "content": example["problem"]}]}# 问题模板,用于包含图像的对话QUESTION_TEMPLATE = "{Question} First output the thinking process in <think> </think> tags and then output the final answer in <answer> </answer> tags. Output the final answer in JSON format."# 定义将包含图像的示例转换为对话格式的函数def make_conversation_image(example):return {"prompt": [# {"role": "system", "content": [{"type": "text", "text": SYSTEM_PROMPT}]},{"role": "user","content": [{"type": "image"},{"type": "text", "text": QUESTION_TEMPLATE.format(Question=example["problem"])}]}]}# 获取指定索引的示例example = self.list_data_dict[i]# 获取图像根目录image_root = self.script_args.image_root# 如果示例中包含图像信息if 'image' in example:# 构建图像路径image_path = os.path.join(image_root, example['image'])# 如果图像文件不存在while not os.path.exists(image_path):# 打印警告信息print(f"Warning: Image {image_path} not found, randomly selecting another image")# 随机选择一个新的索引new_index = random.randint(0, len(self.list_data_dict)-1)# 获取新的示例example = self.list_data_dict[new_index]# 构建新的图像路径image_path = os.path.join(image_root, example['image'])# 打开图像并转换为 RGB 格式image = Image.open(image_path).convert("RGB")else:# 如果示例中不包含图像信息,图像为 Noneimage = Nonereturn {'image': image,'problem': example['problem'],'solution': example['solution'],'prompt': make_conversation_image(example)['prompt'] if 'image' in example else make_conversation(example)['prompt']}'''如果模型预测的边界框与真实边界框的交并比(IoU)大于 0.5,则奖励为 1.0,否则为 0.0。这是一种硬奖励,未来可能使用软奖励会更好。
'''
def iou_reward(completions, solution, **kwargs):# 定义计算交并比的函数def iou(box1, box2):# 计算交集的左上角坐标inter_x1 = max(box1[0], box2[0])inter_y1 = max(box1[1], box2[1])# 计算交集的右下角坐标inter_x2 = min(box1[2]-1, box2[2]-1)inter_y2 = min(box1[3]-1, box2[3]-1)# 如果交集存在if inter_x1 < inter_x2 and inter_y1 < inter_y2:# 计算交集面积inter = (inter_x2-inter_x1+1)*(inter_y2-inter_y1+1)else:# 交集面积为 0inter = 0# 计算并集面积union = (box1[2]-box1[0])*(box1[3]-box1[1]) + (box2[2]-box2[0])*(box2[3]-box2[1]) - inter# 返回交并比return float(inter)/union# 获取完成内容列表contents = [completion[0]["content"] for completion in completions]# 初始化奖励列表rewards = []# 获取当前时间并格式化current_time = datetime.now().strftime("%d-%H-%M-%S-%f")# 定义答案标签的正则表达式模式answer_tag_pattern = r'<answer>(.*?)</answer>'# 定义边界框的正则表达式模式bbox_pattern = r'\[(\s*-?\d*\.?\d+\s*),\s*(\s*-?\d*\.?\d+\s*),\s*(\s*-?\d*\.?\d+\s*),\s*(\s*-?\d*\.?\d+\s*)\]'# 遍历完成内容和真实解决方案for content, sol in zip(contents, solution):# 初始化奖励为 0.0reward = 0.0# 尝试进行符号验证try:# 在完成内容中查找答案标签content_answer_match = re.search(answer_tag_pattern, content)if content_answer_match:# 获取答案内容content_answer = content_answer_match.group(1).strip()# 在答案内容中查找边界框bbox_match = re.search(bbox_pattern, content_answer)if bbox_match:# 获取边界框坐标bbox = [int(bbox_match.group(1)), int(bbox_match.group(2)), int(bbox_match.group(3)), int(bbox_match.group(4))]# 如果交并比大于 0.5if iou(bbox, sol) > 0.5:# 奖励为 1.0reward = 1.0except Exception:# 如果验证失败,继续下一个验证方法pass# 将奖励添加到奖励列表rewards.append(reward)# 如果处于调试模式if os.getenv("DEBUG_MODE") == "true":# 获取日志路径log_path = os.getenv("LOG_PATH")# 打开日志文件并追加记录with open(log_path, "a") as f:# 记录当前时间和奖励信息f.write(f"------------- {current_time} Accuracy reward: {reward} -------------\n")# 记录完成内容f.write(f"Content: {content}\n")# 记录真实解决方案f.write(f"Solution: {sol}\n")return rewardsdef format_reward(completions, **kwargs):"""奖励函数,用于检查完成内容是否符合特定格式。"""# 定义格式的正则表达式模式# pattern = r"<think>.*?</think>\s*<answer>.*?</answer>"pattern = r"<think>.*?</think>\s*<answer>.*?\{.*\[\d+,\s*\d+,\s*\d+,\s*\d+\].*\}.*?</answer>"# 获取完成内容列表completion_contents = [completion[0]["content"] for completion in completions]# 检查每个完成内容是否符合格式matches = [re.fullmatch(pattern, content, re.DOTALL) for content in completion_contents]# 根据匹配结果生成奖励列表return [1.0 if match else 0.0 for match in matches]# 奖励函数注册表,将奖励函数名称映射到对应的函数
reward_funcs_registry = {"accuracy": iou_reward,"format": format_reward,
}def main(script_args, training_args, model_args):# 根据脚本参数中的奖励函数名称,从注册表中获取对应的奖励函数reward_funcs = [reward_funcs_registry[func] for func in script_args.reward_funcs]# 打印奖励函数列表print("reward_funcs:", reward_funcs)# 加载数据集dataset = LazySupervisedDataset(script_args.dataset_name, script_args)# 选择训练器类,这里使用自定义的 Qwen2VLGRPOTrainertrainer_cls = Qwen2VLGRPOTrainer# 初始化 GRPO 训练器trainer = trainer_cls(model=model_args.model_name_or_path,  # 模型名称或路径reward_funcs=reward_funcs,  # 奖励函数列表args=training_args,  # 训练参数train_dataset=dataset,  # 训练数据集eval_dataset=None,  # 评估数据集,这里设为 Nonepeft_config=get_peft_config(model_args),  # PEFT 配置attn_implementation=model_args.attn_implementation,  # 注意力实现方式max_pixels=script_args.max_pixels,  # 图像最大像素数min_pixels=script_args.min_pixels,  # 图像最小像素数torch_dtype=model_args.torch_dtype,  # PyTorch 数据类型)# 开始训练模型trainer.train()# 保存模型到指定的输出目录trainer.save_model(training_args.output_dir)# 如果设置了将模型推送到 Hubif training_args.push_to_hub:# 将模型推送到 Hub,并指定数据集名称trainer.push_to_hub(dataset_name=script_args.dataset_name)if __name__ == "__main__":# 创建 TrlParser 对象,用于解析脚本参数、训练配置和模型配置parser = TrlParser((GRPOScriptArguments, GRPOConfig, ModelConfig))# 解析命令行参数和配置script_args, training_args, model_args = parser.parse_args_and_config()# 调用主函数开始训练main(script_args, training_args, model_args)

代码中的两个关键奖励函数 format_rewardiou_reward

1. 格式奖励函数 format_reward

函数定义和功能
def format_reward(completions, **kwargs):"""Reward function that checks if the completion has a specific format."""pattern = r"<think>.*?</think>\s*<answer>.*?\{.*\[\d+,\s*\d+,\s*\d+,\s*\d+\].*\}.*?</answer>"completion_contents = [completion[0]["content"] for completion in completions]matches = [re.fullmatch(pattern, content, re.DOTALL) for content in completion_contents]return [1.0 if match else 0.0 for match in matches]

此函数的主要功能是检查模型生成的完成内容是否符合特定的格式要求。具体来说,它期望模型的输出满足以下格式:

  • 包含 <think></think> 标签,用于包裹思考过程。
  • 包含 <answer></answer> 标签,用于包裹答案。
  • 答案部分需要是一个 JSON 格式,并且其中包含一个由四个整数组成的列表,通常可以理解为表示边界框的坐标。
实现步骤
  1. 定义正则表达式模式pattern 是一个正则表达式,用于描述期望的输出格式。
  2. 提取完成内容completion_contentscompletions 中提取出每个完成内容的文本部分。
  3. 检查格式匹配matches 使用 re.fullmatch 函数检查每个完成内容是否完全匹配正则表达式模式。
  4. 生成奖励列表:根据匹配结果,为每个完成内容生成一个奖励值,如果匹配则为 1.0,否则为 0.0。
作用

通过这个奖励函数,模型在训练过程中会被激励去生成符合特定格式的输出,有助于规范模型的回答结构,使得输出更易于解析和使用。

2. 交并比(IoU)奖励函数 iou_reward

函数定义和功能
def iou_reward(completions, solution, **kwargs):def iou(box1, box2):inter_x1 = max(box1[0], box2[0])inter_y1 = max(box1[1], box2[1])inter_x2 = min(box1[2]-1, box2[2]-1)inter_y2 = min(box1[3]-1, box2[3]-1)if inter_x1 < inter_x2 and inter_y1 < inter_y2:inter = (inter_x2-inter_x1+1)*(inter_y2-inter_y1+1)else:inter = 0union = (box1[2]-box1[0])*(box1[3]-box1[1]) + (box2[2]-box2[0])*(box2[3]-box2[1]) - interreturn float(inter)/unioncontents = [completion[0]["content"] for completion in completions]rewards = []current_time = datetime.now().strftime("%d-%H-%M-%S-%f")answer_tag_pattern = r'<answer>(.*?)</answer>'bbox_pattern = r'\[(\s*-?\d*\.?\d+\s*),\s*(\s*-?\d*\.?\d+\s*),\s*(\s*-?\d*\.?\d+\s*),\s*(\s*-?\d*\.?\d+\s*)\]'for content, sol in zip(contents, solution):reward = 0.0try:content_answer_match = re.search(answer_tag_pattern, content)if content_answer_match:content_answer = content_answer_match.group(1).strip()bbox_match = re.search(bbox_pattern, content_answer)if bbox_match:bbox = [int(bbox_match.group(1)), int(bbox_match.group(2)), int(bbox_match.group(3)), int(bbox_match.group(4))]if iou(bbox, sol) > 0.5:reward = 1.0except Exception:passrewards.append(reward)if os.getenv("DEBUG_MODE") == "true":log_path = os.getenv("LOG_PATH")with open(log_path, "a") as f:f.write(f"------------- {current_time} Accuracy reward: {reward} -------------\n")f.write(f"Content: {content}\n")f.write(f"Solution: {sol}\n")return rewards

此函数的主要功能是评估模型预测的边界框与真实边界框之间的重叠程度,并根据交并比(IoU)值给予奖励。

实现步骤
  1. 定义 IoU 计算函数iou 函数用于计算两个边界框的交并比。它首先计算两个边界框的交集面积和并集面积,然后将交集面积除以并集面积得到 IoU 值。
  2. 提取完成内容contentscompletions 中提取出每个完成内容的文本部分。
  3. 查找答案和边界框:使用正则表达式 answer_tag_pattern 查找完成内容中的答案部分,再使用 bbox_pattern 查找答案中的边界框坐标。
  4. 计算 IoU 并给予奖励:对于每个完成内容,提取预测的边界框坐标,与真实边界框计算 IoU 值。如果 IoU 值大于 0.5,则给予 1.0 的奖励,否则给予 0.0 的奖励。
  5. 日志记录(可选):如果设置了调试模式(DEBUG_MODEtrue),则将每个完成内容的奖励信息记录到日志文件中。
作用

通过这个奖励函数,模型在训练过程中会被激励去预测更准确的边界框,提高目标检测的精度。同时,结合格式奖励函数,可以让模型不仅准确预测边界框,还能以规定的格式输出结果。

监督学习与规则奖励函数强化学习的结合方式

1. 数据层面的结合
  • 利用监督数据初始化模型:在开始强化学习训练之前,使用监督学习的方式对视觉语言模型(VLM)进行预训练。通过直接拟合问答对数据,让模型学习到基本的语言和视觉特征表示以及问题回答的模式。例如,在代码中使用 LazySupervisedDataset 类加载数据集,这些数据可以作为监督学习阶段的训练数据,让模型初步学习到如何根据问题和图像生成答案。
  • 监督数据作为强化学习的参考:在强化学习的过程中,监督学习的数据可以作为参考来评估模型的输出。例如,在 iou_reward 函数中,通过比较模型预测的边界框与真实边界框的交并比(IoU)来给予奖励,这里的真实边界框就是监督学习中的标签信息。
2. 训练过程的结合
  • 分阶段训练:先进行监督学习训练,让模型收敛到一个较好的初始状态。然后再切换到强化学习阶段,使用规则奖励函数来进一步优化模型的策略。在代码中,虽然没有明确体现分阶段训练的逻辑,但可以在实际应用中先使用监督学习的方法对 Qwen2VLForConditionalGeneration 模型进行训练,然后再使用 Qwen2VLGRPOTrainer 进行强化学习训练。
  • 混合训练:在每个训练步骤中,既使用监督学习的损失函数,又使用强化学习的奖励函数。例如,可以将监督学习的交叉熵损失和强化学习的奖励损失加权求和,作为总的损失函数来更新模型参数。这样可以让模型在学习过程中既考虑到直接拟合标签的准确性,又考虑到长期的奖励优化。
3. 奖励函数设计结合监督信息
  • 准确性奖励:如 iou_reward 函数,将模型输出与监督学习中的标签进行比较,根据比较结果给予奖励。这种奖励函数可以促使模型在强化学习过程中输出更接近真实标签的结果,从而结合了监督学习的信息。
  • 格式奖励format_reward 函数可以确保模型输出的格式符合特定要求,这可以看作是一种规则约束。同时,这种格式要求也可以是在监督学习阶段就定义好的,从而将监督学习中的格式规范融入到强化学习的奖励机制中。

相关文章:

VLM(视觉语言模型)与DeepSeek R1(奖励机制)如何结合

VLM&#xff08;视觉语言模型&#xff09;与DeepSeek R1&#xff08;奖励机制&#xff09;如何结合 flyfish VLM的传统训练依赖于监督学习&#xff08;直接拟合问答对&#xff09;&#xff0c;而规则奖励函数通常用于强化学习&#xff08;通过试错和奖励反馈优化策略&#xf…...

问题:Flask应用中的用户会话(Session)管理失效

我来分享一个常见的PythonWeb开发问题&#xff1a; 问题&#xff1a;Flask应用中的用户会话(Session)管理失效 这是一个在Flask开发中经常遇到的问题。当用户登录后&#xff0c;有时会话会意外失效&#xff0c;导致用户需要重复登录。 解决方案&#xff1a; 1. 首先&#x…...

Qt/C++面试【速通笔记一】

Qt 信号与槽机制 什么是信号&#xff08;Signal&#xff09;和槽&#xff08;Slot&#xff09;&#xff1f; 在Qt中&#xff0c;信号&#xff08;Signal&#xff09;和槽&#xff08;Slot&#xff09;是实现对象之间通信的一种机制。信号是对象在某些事件发生时发出的通知&…...

RoCBert:具有多模态对比预训练的健壮中文BERT

摘要 大规模预训练语言模型在自然语言处理&#xff08;NLP&#xff09;任务上取得了最新的最优结果&#xff08;SOTA&#xff09;。然而&#xff0c;这些模型容易受到对抗攻击的影响&#xff0c;尤其是对于表意文字语言&#xff08;如中文&#xff09;。 在本研究中&#xff0…...

DeepSeek入门到大师 清华大学[1-5版]全集

1、文件概览 1、清华大学《DeepSeek:从入门到精通》 2、清华大学《Deepseek如何赋能职场应用?》 3、清华大学《普通人如何抓住DeepSeek红利》 4、清华大学《DeepSeekDeepResearch让科研像聊天一样简单》 5、清华大学《DeepSeek与AI幻觉》 6、天津大学《深度解读Deepseek:原理…...

Debezium:实时数据捕获与同步的利器

一、什么是 Debezium Debezium 是一个开源的分布式平台&#xff0c;专门用于捕获数据库中的数据变更。它通过读取数据库的事务日志&#xff0c;能够以非侵入性的方式捕获数据库中发生的所有变化&#xff0c;并将这些变化转化为事件流&#xff0c;实时推送到像 Kafka 这样的消息…...

【蓝桥杯】第十五届省赛大学真题组真题解析

【蓝桥杯】第十五届省赛大学真题组真题解析 一、智能停车系统 1、知识点 &#xff08;1&#xff09;flex-wrap 控制子元素的换行方式 属性值有&#xff1a; no-wrap不换行wrap伸缩容器不够则自动往下换行wrap-reverse伸缩容器不够则自动往上换行 &#xff08;2&#xff0…...

AI助力下的PPT革命:DeepSeek 与Kimi的高效创作实践

清华大学出品《DeepSeek&#xff1a;从入门到精通》分享 在忙碌的职场中&#xff0c;制作一份高质量的PPT往往需要投入大量时间和精力&#xff0c;尤其是在临近截止日期时。今天&#xff0c;我们将探索如何借助 AI 工具 —— DeepSeek 和 Kimi —— 让 PPT 制作变得既快捷又高…...

【MySQL篇】持久化和非持久化统计信息的深度剖析(含analyze命令和mysqlcheck工具两种收集方式)

&#x1f4ab;《博主介绍》&#xff1a;✨又是一天没白过&#xff0c;我是奈斯&#xff0c;从事IT领域✨ &#x1f4ab;《擅长领域》&#xff1a;✌️擅长阿里云AnalyticDB for MySQL(分布式数据仓库)、Oracle、MySQL、Linux、prometheus监控&#xff1b;并对SQLserver、NoSQL(…...

C++ 手撕定时器

C 手撕定时器 思路与知识调用场景类声明 参考 思路与知识 1. 为了支持相同时间戳下多个任务&#xff0c;需要考虑到支持重复key的std::mutimap, 以及成员函数equal_range 2. 工具函数Timer::GetTick 返回一个uint64_t毫秒时间戳作为multimap的key&#xff0c;需要会使用chrono…...

邮件安全之发件人伪造

电子邮件工作原理 电子邮件传输过程中主要涉及到SMTP、IMAP、POP3三种协议&#xff0c;具体功能如下&#xff1a; SMTP:全称Simple Mail Transfer Protocol&#xff0c;即简单邮件传输协议&#xff0c;主要用于发送邮件&#xff0c;使用端口号25。 IMAP:全称Internet Mail Acce…...

前端八股——JS+ES6

前端八股&#xff1a;JSES6 说明&#xff1a;个人总结&#xff0c;用于个人复习回顾&#xff0c;将持续改正创作&#xff0c;已在语雀公开&#xff0c;欢迎评论改正。...

Qt QTreeWidget 总结

Qt QTreeWidget 总结 1. 概述 QTreeWidget 是 Qt 中用于显示树形结构的控件&#xff0c;继承自 QTreeView&#xff0c;但提供了更简单的接口。适合展示层级数据&#xff08;如文件目录、组织结构&#xff09;。每个节点是 QTreeWidgetItem 对象&#xff0c;支持文本、图标、复…...

Python常见面试题的详解16

1. 如何强行关闭客户端和服务器之间的连接&#xff1f; 在网络编程中&#xff0c;有时需要强行中断客户端和服务器之间的连接。对于基于 TCP 协议的连接&#xff0c;由于其面向连接的特性&#xff0c;需要采取特定的步骤来确保连接被正确关闭&#xff1b;而 UDP 是无连接协议&a…...

前端设计模式面试题及参考答案

目录 如何用闭包实现单例模式?列举两种实现方式 工厂模式与构造函数创建对象的核心区别是什么? 抽象工厂模式如何解决多平台 UI 组件兼容问题? 原型模式在前端框架中如何优化对象创建性能? 建造者模式如何实现复杂表单配置的链式调用? 单例模式在全局状态管理中的典型…...

Python Django系列—入门实例(二)

数据库配置 现在&#xff0c;打开 mysite/settings.py 。这是个包含了 Django 项目设置的 Python 模块。 默认情况下&#xff0c;​ DATABASES 配置使用 SQLite。如果你是数据库新手&#xff0c;或者只是想尝试 Django&#xff0c;这是最简单的选择。SQLite 包含在 Python 中…...

STM32-智能台灯项目

一、项目需求 1. 红外传感器检测是否有人&#xff0c;有人的话实时检测距离&#xff0c;过近则报警&#xff1b;同时计时&#xff0c;超过固定时间则报警&#xff1b; 2. 按键 1 切换工作模式&#xff1a;智能模式、按键模式、远程模式&#xff1b; 3. 智能模式下&#xff0c;根…...

HTML之JavaScript DOM操作元素(2)

HTML之JavaScript DOM操作元素&#xff08;2&#xff09; 4.增删元素var element document.createElement("元素名") 创建新元素父元素.appendChild(子元素) 在父元素中追加子元素父元素.insertBefore(新元素,参照元素) 在特定元素之前新增元…...

智能优化算法:莲花算法(Lotus flower algorithm,LFA)介绍,提供MATLAB代码

一、 莲花算法 1.1 算法原理 莲花算法&#xff08;Lotus flower algorithm&#xff0c;LFA&#xff09;是一种受自然启发的优化算法&#xff0c;其灵感来源于莲花的自清洁特性和授粉过程。莲花的自清洁特性&#xff0c;即所谓的“莲花效应”&#xff0c;是由其叶片表面的微纳…...

【复习】计算机网络

网络模型 OSI 应用层&#xff1a;给应用程序提供统一的接口表示层&#xff1a;把数据转换成兼容另一个系统能识别的格式会话层&#xff1a;负责建立、管理、终止表示层实体之间的通信会话传输层&#xff1a;负责端到端的数据传输网络层&#xff1a;负责数据的路由、转发、分片…...

【R语言】读取CSV数据时,显示[1] PK...<0 行> (或0-长度的row.names)

一、问题 当我使用以下代码读取CSV数据后&#xff0c;发现使用head(data)显示[1] PK...<0 行> (或0-长度的row.names)&#xff0c;如下截图所示。 # 尝试读取文件 data <- read.csv("C:\\Users\\11300\\Desktop\\test.csv", header TRUE) # 检查数据 hea…...

CentOS环境变量配置+解析

环境变量的作用就是让系统快速通过你的命令找到你的可执行程序&#xff0c;windows系统里也同理&#xff0c;也就是你每次输入个命令&#xff0c;系统就会找环境变量里到底有没有叫这个命令进程的 一、环境变量配置 1.编辑配置文件 vim /etc/profile export PATH$PATH:$JAVA…...

最新版本Exoplayer扩展FFmpeg音频软解码保姆级教程

ExoPlayer 是一个开源的 Android 媒体播放库&#xff0c;由 Google 开发和维护&#xff0c;用于替代 Android 系统自带的 MediaPlayer。它提供了更强大的功能、更好的性能和更高的灵活性&#xff0c;适用于各种复杂的媒体播放场景。所以被广泛用于各种播放器场景。 最近项目中…...

【蓝桥杯集训·每日一题2025】 AcWing 6134. 哞叫时间II python

6134. 哞叫时间II Week 1 2月20日 农夫约翰正在试图向埃尔茜描述他最喜欢的 USACO 竞赛&#xff0c;但她很难理解为什么他这么喜欢它。 他说「竞赛中我最喜欢的部分是贝茜说『现在是哞哞时间』并在整个竞赛中一直哞哞叫」。 埃尔茜仍然不理解&#xff0c;所以农夫约翰将竞赛…...

HTML/CSS中子代选择器

1.作用:选中指定元素中,符合要求的子元素. 子代选择器又称:子元素选择器,子选择器. 2.语法:选择器1>选择器2>选择器3>......选择器n 3.实例 <style>/* div中子代选择器 */div>a{color: red;}</style><div><a href"#">张三</…...

计算机毕业设计SpringBoot+Vue.jst网上购物商城系统(源码+LW文档+PPT+讲解)

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…...

EasyRTC:全平台支持与自研算法驱动的智能音视频通讯解决方案

在智能硬件的浪潮中&#xff0c;设备之间的互联互通已成为提升用户体验的核心需求。无论是智能家居、智能办公&#xff0c;还是工业物联网&#xff0c;高效的音视频通讯和交互能力是实现智能化的关键。然而&#xff0c;传统音视频解决方案往往面临平台兼容性差、交互体验不佳以…...

C#: 日志函数

背景&#xff1a; 1.常见的官方日志模块项目过于复杂&#xff0c;且配置过于繁琐&#xff0c;针对这种现象&#xff0c;实现在大型项目中快速定位错误问题&#xff1b; 实现思路&#xff1a; 1.设置当前日志文件路径&#xff08;获取到当前文件应用程序路径 \ErrorLog) 2.判…...

PyTorch 是如何进行机器学习的

1. 机器学习的核心流程 机器学习的核心是通过数据训练模型&#xff0c;让模型学会从输入数据中提取规律&#xff0c;并对新数据做出预测。整个过程可以分为以下几个步骤&#xff1a; 准备数据&#xff1a;收集并整理数据&#xff0c;分为输入&#xff08;特征&#xff09;和输…...

Java中的Stream API:从入门到实战

引言 在现代Java开发中&#xff0c;Stream API 是处理集合数据的强大工具。它不仅让代码更加简洁易读&#xff0c;还能通过并行处理提升性能。本文将带你从基础概念入手&#xff0c;逐步深入Stream API的使用&#xff0c;并通过实战案例展示其强大功能。 1. 什么是Stream API…...

【蓝桥杯单片机】客观题

一、第十三届省赛&#xff08;一&#xff09; 二、第十三届省赛&#xff08;二&#xff09;...

Spring Boot 中使用 @Transactional 注解配置事务管理

事务管理是应用系统开发中必不可少的一部分。Spring 为事务管理提供了丰富的功能支持。Spring 事务管理分为编程式和声明式的两种方式。编程式事务指的是通过编码方式实现事务&#xff1b;声明式事务基于 AOP,将具体业务逻辑与事务处理解耦。声明式事务管理使业务代码逻辑不受污…...

嵌入式八股文(五)硬件电路篇

一、名词概念 1. 整流和逆变 &#xff08;1&#xff09;整流&#xff1a;整流是将交流电&#xff08;AC&#xff09;转变为直流电&#xff08;DC&#xff09;。常见的整流电路包括单向整流&#xff08;二极管&#xff09;、桥式整流等。 半波整流&#xff1a;只使用交流电的正…...

《论多源数据集成及应用》审题技巧 - 系统架构设计师

论多源数据集成及应用写作框架 一、考点概述 本论题“论多源数据集成及应用”主要考察的是计算机软件测试工程师在数据管理和集成方面的专业知识与实践能力。论题聚焦于信息爆炸时代企业、组织和个人所面临的数据挑战&#xff0c;特别是如何有效地收集、整理和清洗来自不同渠…...

怎么在Github上readme文件里面怎么插入图片?

环境&#xff1a; Github 问题描述&#xff1a; 怎么在Github上readme文件里面怎么插入图片&#xff1f; https://github.com/latiaoge/AI-Sphere-Butler/tree/master 解决方案&#xff1a; 1.相对路径引用 上传图片到仓库 将图片文件&#xff08;如 .png/.jpg&#xff…...

【NLP 31、预训练模型的发展过程】

人的行为&#xff0c;究竟是人所带来的思维方式不同还是与机器一样&#xff0c;刻在脑海里的公式呢&#xff1f; 只是因为不同的人公式不同&#xff0c;所以人的行为才不同&#xff0c;可这又真的是人引以为傲的意识吗&#xff1f; 人脑只是相当于一个大型、驳杂的处理器&#…...

【计算机网络】传输层TCP协议

传输层 - layer4 - TCP协议 传输层&#xff1a;位于ISO模型的第四层 ——>L4 tcp协议意为传输控制协议&#xff08;Transmission Control Protocol&#xff09; 提供端到端的连接 端口号范围&#xff1a;0-65535 &#xff08;2^16次方&#xff09; 一个应用程序(服务)会占用…...

vscode settings(二):文件资源管理器编辑功能主题快捷键

参考资料 Visual Studio Code权威指南 by 韩骏 一. 文件资源管理器 1.1 文件资源管理器隐藏文件夹 默认情况下&#xff0c;Visual Studio Code会在文件资源管理器中隐藏一些文件夹&#xff08;如.git文件夹&#xff09;​。可以通过files.exclude来配置要被隐藏的文件和文件…...

halcon机器视觉深度学习对象检测,物体检测

目录 效果图操作步骤软件版本halcon参考代码本地函数 get_distinct_colors()本地函数 make_neighboring_colors_distinguishable() 效果图 操作步骤 首先要在Deep Learning Tool工具里面把图片打上标注文本&#xff0c; 然后训练模型&#xff0c;导出模型文件 这个是模型 mod…...

go 反射 interface{} 判断类型 获取值 设置值 指针才可以设置值

内容包括 1. 用interface{}接收值 2. 判断interface{}的类型 switch 3. 打印interface{}的类型 4. 通过字符串对结构体&#xff0c;interface{}等进行设置值、获取值处理 示例代码 package mainimport ("fmt""log""reflect" )type Student…...

单臂路由

单臂路由&#xff08;Router on a Stick&#xff09;是一种网络配置方式&#xff0c;主要用于在单个物理接口上实现多个VLAN之间的路由。它通常用于交换机与路由器之间的连接&#xff0c;适用于VLAN间通信需求较小的情况。 工作原理 VLAN划分&#xff1a;交换机上配置多个VLAN…...

SpringBoot【实用篇】- 测试

文章目录 目标&#xff1a; 1.加载测试专用属性3.Web环境模拟测试2.加载测试专用配置4.数据层测试回滚5.测试用例数据设定 目标&#xff1a; 加载测试专用属性加载测试专用配置Web环境模拟测试数据层测试回滚测试用例数据设定 1.加载测试专用属性 我们在前面讲配置高级的…...

NutUI内网离线部署

文章目录 官网拉取源代码到本地仓库修改源代码打包构建nginx反向代理部署访问内网离线地址 在网上找了一圈没有写NutUI内网离线部署的文档&#xff0c;花了1天时间研究下&#xff0c;终于解决了。 对于有在内网离线使用的小伙伴就可以参考使用了 如果还是不会联系UP主:QQ:10927…...

【深度学习】Adam和AdamW优化器有什么区别,以及为什么Adam会被自适应学习率影响

Adam 和 AdamW 的主要区别在于 权重衰减&#xff08;Weight Decay&#xff09; 的实现方式&#xff0c;具体如下&#xff1a; 1. 权重衰减&#xff08;Weight Decay&#xff09;处理方式 Adam&#xff1a;采用 L2 正则化&#xff0c;通过在梯度更新时手动添加 weight_decay 项…...

Pytorch的F.cross_entropy交叉熵函数

参考笔记&#xff1a;pytorch的F.cross_entropy交叉熵函数和标签平滑函数_怎么给crossentropyloss添加标签平滑-CSDN博客 先来讲下基本的交叉熵cross_entropy&#xff0c;官网如下&#xff1a;torch.nn.functional.cross_entropy — PyTorch 1.12 documentation torch.nn.fun…...

一文讲解Redis为什么读写性能高以及I/O复用相关知识点

Redis为什么读写性能高呢&#xff1f; Redis 的速度⾮常快&#xff0c;单机的 Redis 就可以⽀撑每秒十几万的并发&#xff0c;性能是 MySQL 的⼏⼗倍。原因主要有⼏点&#xff1a; ①、基于内存的数据存储&#xff0c;Redis 将数据存储在内存当中&#xff0c;使得数据的读写操…...

[特殊字符] Elasticsearch 双剑合璧:HTTP API 与 Java API 实战整合指南

&#x1f680; Elasticsearch 双剑合璧&#xff1a;HTTP API 与 Java API 实战整合指南 一、HTTP API 定义与用途 Elasticsearch 的 HTTP API 是基于 RESTful 接口设计的核心交互方式&#xff0c;支持通过 URL 和 JSON 数据直接操作索引、文档、集群等资源。适用于快速调试、…...

某手sig3-ios算法 Chomper黑盒调用

Chomper-iOS界的Unidbg 最近在学习中发现一个Chomper框架&#xff0c;Chomper 是一个模拟执行iOS可执行文件的框架&#xff0c;类似于安卓端大名鼎鼎的Unidbg。 这篇文章使用Chomper模拟执行某手的sig3算法&#xff0c;初步熟悉该框架。这里只熟悉模拟执行步骤以及一些常见的…...

蓝桥杯之阶段考核

&#x1f4d6; Day 7&#xff1a;阶段考核 - 蓝桥杯官方模拟赛&#xff08;限时 4 小时&#xff09; &#x1f4d6; 一、如何高效完成模拟赛&#xff1f; 模拟赛是一种接近真实竞赛的训练方式。要高效完成模拟赛&#xff0c;需要掌握以下策略&#xff1a; 1. 赛前准备 ✅ 环…...

DeepSeek掘金——VSCode 接入DeepSeek V3大模型,附使用说明

VSCode 接入DeepSeek V3大模型,附使用说明 由于近期 DeepSeek 使用人数激增,服务器压力较大,官网已 暂停充值入口 ,且接口响应也开始不稳定,建议使用第三方部署的 DeepSeek,如 硅基流动 或者使用其他模型/插件,如 豆包免费AI插件 MarsCode、阿里免费AI插件 TONGYI Lin…...