基于 AWS SageMaker 对 DeepSeek-R1-Distilled-Llama-8B 模型的精调与实践

news2025/1/31 1:54:13

在当今人工智能蓬勃发展的时代,语言模型的性能优化和定制化成为研究与应用的关键方向。本文聚焦于 AWS SageMaker 平台上对 DeepSeek-R1-Distilled-Llama-8B 模型的精调实践,详细探讨这一过程中的技术细节、操作步骤以及实践价值。

一、实验背景与目标

(一)语言模型发展趋势

随着自然语言处理技术的不断演进,语言模型从基础架构的创新逐渐转向在特定场景下的性能优化和功能拓展。开发者们期望通过对预训练模型的精细调整,使其在特定领域、任务中表现更为出色,以满足多样化的应用需求。

(二)DeepSeek-R1-Distilled-Llama-8B 模型优势

DeepSeek-R1-Distilled-Llama-8B 模型融合了 DeepSeek-R1 的先进知识蒸馏技术与 Llama-8B 模型的架构优势。知识蒸馏使得小模型能够学习到大型模型的优秀特征,在保持较小参数规模的同时,具备强大的语言理解和生成能力。8B 的参数规模在性能与计算资源消耗之间达到了较好的平衡,适合在多种场景下进行部署和应用。

(三)实验目标

本次实验旨在利用 AWS SageMaker 平台的强大计算资源和丰富工具,对 DeepSeek-R1-Distilled-Llama-8B 模型进行精细调整,提升其在特定任务(如问答、文本生成等)上的性能表现。通过实验,探索如何优化模型训练过程,提高模型的泛化能力和准确性,为实际应用提供有力支持。

二、AWS SageMaker 平台概述

(一)SageMaker 核心功能

AWS SageMaker 是一个全托管的机器学习平台,为开发者提供了从数据预处理、模型训练、模型部署到模型监控的一站式解决方案。它集成了多种主流的机器学习框架,如 TensorFlow、PyTorch 等,支持在不同规模的计算实例上进行训练和推理。在本次实验中,我们将借助 SageMaker 的分布式训练功能,加速 DeepSeek-R1-Distilled-Llama-8B 模型的精调过程。

(二)SageMaker 在模型开发中的优势

  1. 高效资源管理:SageMaker 能够自动配置和管理计算资源,根据模型训练的需求动态调整实例类型和数量。这不仅提高了资源利用率,还降低了开发者的运维成本,使他们能够专注于模型开发和优化。
  2. 分布式训练支持:对于大规模的语言模型训练,分布式训练是关键。SageMaker 支持数据并行和模型并行等多种分布式训练策略,能够充分利用多个计算节点的计算能力,显著缩短训练时间。在精调 DeepSeek-R1-Distilled-Llama-8B 模型时,分布式训练可以加快模型收敛速度,提高训练效率。
  3. 内置算法与工具:SageMaker 提供了一系列内置的算法和工具,如超参数调优、模型评估等。这些工具简化了模型开发流程,帮助开发者快速找到最优的模型配置,提升模型性能。

三、实验步骤详解

 在这个演示中,我们展示了如何使用 PyTorch FSDP、QLoRA、Hugging Face PEFT 和 bitsandbytes 对 DeepSeek-R1-Distill-Llama-8B 模型进行微调。

(一)我们正在使用 SageMaker 远程装饰器在 Amazon SageMaker 训练作业上运行微调任务

JupyterLab 实例类型:ml.t3.medium

Python 版本:3.11

微调:

  • 实例类型:ml.g5.12xlarge
  • 安装所需的库,包括 Hugging Face 库,并重启内核。
    %pip install -r requirements.txt --upgrade
    %pip install -q -U python-dotenv

(二)设置配置文件路径

我们正在设置 config.yaml 文件所在的目录,以便远程装饰器可以通过 SageMaker Defaults 使用这些设置。

本次实验使用 Hugging Face 容器用于 us-east-1 区域。确保您使用的是适合您 AWS 区域的正确镜像,否则请编辑 config.yaml。容器镜像可在此处获取。

from dotenv import load_dotenv
import os

# Use .env in case of hidden variables
load_dotenv()

# Set path to config file
os.environ["SAGEMAKER_USER_CONFIG_OVERRIDE"] = os.getcwd()

 (三)可视化并上传数据集

我们将加载 rajpurkar/squad 数据集

import sagemaker

sagemaker_session = sagemaker.Session()
bucket_name = sagemaker_session.default_bucket()
default_prefix = sagemaker_session.default_bucket_prefix

from datasets import load_dataset
import pandas as pd

dataset = load_dataset("rajpurkar/squad")
df = pd.DataFrame(dataset['train'])
df = df.iloc[0:1000]
df['answer'] = [answer['text'][0] for answer in df['answers']]
df = df[['context', 'question', 'answer']]

df.head()

from sklearn.model_selection import train_test_split

train, test = train_test_split(df, test_size=0.1, random_state=42)

print("Number of train elements: ", len(train))
print("Number of test elements: ", len(test))

创建一个提示模板,并加载一个随机样本的数据集以尝试摘要。

from random import randint

# custom instruct prompt start
prompt_template = f"""<|begin_of_text|><|start_header_id|>user<|end_header_id|>\nContext:\n{
  
  {context}}\n\n{
  
  {question}}<|eot_id|><|start_header_id|>assistant<|end_header_id|>{
  
  {answer}}<|end_of_text|><|eot_id|>"""

# template dataset to add prompt to each sample
def template_dataset(sample):
    sample["text"] = prompt_template.format(context=sample["context"],
                                            question=sample["question"],
                                            answer=sample["answer"])
    return sample

使用 Hugging Face Trainer 类对模型进行微调。定义我们想要使用的超参数。我们还创建一个 DataCollator,它将负责填充我们的输入和标签。 

from datasets import Dataset, DatasetDict

train_dataset = Dataset.from_pandas(train)
test_dataset = Dataset.from_pandas(test)

dataset = DatasetDict({"train": train_dataset, "test": test_dataset})

train_dataset = dataset["train"].map(template_dataset, remove_columns=list(dataset["train"].features))

print(train_dataset[randint(0, len(dataset))]["text"])

test_dataset = dataset["test"].map(template_dataset, remove_columns=list(dataset["test"].features))

 为了训练我们的模型,我们需要将输入(文本)转换为标记 ID。这是通过 Hugging Face Transformers Tokenizer 完成的。除了 QLoRA,我们还将使用 bitsandbytes 4 位精度将冻结的 LLM 量化为 4 位,并在其上附加 LoRA 适配器。

定义训练函数

model_id = "deepseek-ai/DeepSeek-R1-Distill-Llama-8B"

from accelerate import Accelerator
import datetime
from huggingface_hub import snapshot_download
import os
from peft import AutoPeftModelForCausalLM, LoraConfig, get_peft_model, prepare_model_for_kbit_training
from sagemaker.remote_function import remote
import torch
from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig, set_seed
import transformers
import traceback

# Start training
@remote(
    keep_alive_period_in_seconds=0,
    volume_size=100,
    job_name_prefix=f"train-{model_id.split('/')[-1].replace('.', '-')}",
    use_torchrun=True,
    nproc_per_node=4
)
def train_fn(
        model_name,
        train_ds,
        test_ds=None,
        lora_r=8,
        lora_alpha=16,
        lora_dropout=0.1,
        per_device_train_batch_size=8,
        per_device_eval_batch_size=8,
        gradient_accumulation_steps=1,
        learning_rate=2e-4,
        num_train_epochs=1,
        fsdp="",
        fsdp_config=None,
        gradient_checkpointing=False,
        merge_weights=False,
        seed=42,
        token=None
):
    def init_distributed():
        # Initialize the process group
        torch.distributed.init_process_group(
            backend="nccl", # Use "gloo" backend for CPU
            timeout=datetime.timedelta(seconds=5400)
        )
        local_rank = int(os.environ["LOCAL_RANK"])
        torch.cuda.set_device(local_rank)

        return local_rank

    if torch.cuda.is_available() and (torch.cuda.device_count() > 1 or int(os.environ.get("SM_HOST_COUNT", 1)) > 1):
        # Call this function at the beginning of your script
        local_rank = init_distributed()

        # Now you can use distributed functionalities
        torch.distributed.barrier(device_ids=[local_rank])

    os.environ.update({"HF_HUB_ENABLE_HF_TRANSFER": "1"})

    set_seed(seed)

    accelerator = Accelerator()

    if token is not None:
        os.environ.update({"HF_TOKEN": token})
        accelerator.wait_for_everyone()

    print("Downloading model ", model_name)

    os.makedirs("/tmp/tmp_folder", exist_ok=True)

    snapshot_download(repo_id=model_name, local_dir="/tmp/tmp_folder")

    print(f"Downloading model {model_name} under /tmp/tmp_folder")

    model_name = "/tmp/tmp_folder"

    tokenizer = AutoTokenizer.from_pretrained(model_name)

    # Set Tokenizer pad Token
    tokenizer.pad_token = tokenizer.eos_token

    with accelerator.main_process_first():
        # tokenize and chunk dataset
        lm_train_dataset = train_ds.map(
            lambda sample: tokenizer(sample["text"]), remove_columns=list(train_ds.features)
        )

        print(f"Total number of train samples: {len(lm_train_dataset)}")

        if test_ds is not None:
            lm_test_dataset = test_ds.map(
                lambda sample: tokenizer(sample["text"]), remove_columns=list(test_ds.features)
            )

            print(f"Total number of test samples: {len(lm_test_dataset)}")
        else:
            lm_test_dataset = None

    torch_dtype = torch.bfloat16

    # Defining additional configs for FSDP
    if fsdp != "" and fsdp_config is not None:
        bnb_config_params = {
            "bnb_4bit_quant_storage": torch_dtype
        }

        model_configs = {
            "torch_dtype": torch_dtype
        }

        fsdp_configurations = {
            "fsdp": fsdp,
            "fsdp_config": fsdp_config,
            "gradient_checkpointing_kwargs": {
                "use_reentrant": False
            },
            "tf32": True
        }
    else:
        bnb_config_params = dict()
        model_configs = dict()
        fsdp_configurations = dict()

    bnb_config = BitsAndBytesConfig(
        load_in_4bit=True,
        bnb_4bit_use_double_quant=True,
        bnb_4bit_quant_type="nf4",
        bnb_4bit_compute_dtype=torch_dtype,
        **bnb_config_params
    )

    model = AutoModelForCausalLM.from_pretrained(
        model_name,
        trust_remote_code=True,
        quantization_config=bnb_config,
        attn_implementation="flash_attention_2",
        use_cache=not gradient_checkpointing,
        cache_dir="/tmp/.cache",
        **model_configs
    )

    if fsdp == "" and fsdp_config is None:
        model = prepare_model_for_kbit_training(model, use_gradient_checkpointing=gradient_checkpointing)

    if gradient_checkpointing:
        model.gradient_checkpointing_enable()

    config = LoraConfig(
        r=lora_r,
        lora_alpha=lora_alpha,
        target_modules="all-linear",
        lora_dropout=lora_dropout,
        bias="none",
        task_type="CAUSAL_LM"
    )

    model = get_peft_model(model, config)

    trainer = transformers.Trainer(
        model=model,
        train_dataset=lm_train_dataset,
        eval_dataset=lm_test_dataset if lm_test_dataset is not None else None,
        args=transformers.TrainingArguments(
            per_device_train_batch_size=per_device_train_batch_size,
            per_device_eval_batch_size=per_device_eval_batch_size,
            gradient_accumulation_steps=gradient_accumulation_steps,
            gradient_checkpointing=gradient_checkpointing,
            logging_strategy="steps",
            logging_steps=1,
            log_on_each_node=False,
            num_train_epochs=num_train_epochs,
            learning_rate=learning_rate,
            bf16=True,
            ddp_find_unused_parameters=False,
            save_strategy="no",
            output_dir="outputs",
            **fsdp_configurations
        ),
        data_collator=transformers.DataCollatorForLanguageModeling(tokenizer, mlm=False),
    )

    trainer.train()

    if trainer.accelerator.is_main_process:
        trainer.model.print_trainable_parameters()

    if trainer.is_fsdp_enabled:
        trainer.accelerator.state.fsdp_plugin.set_state_dict_type("FULL_STATE_DICT")

    if merge_weights:
        output_dir = "/tmp/model"

        # merge adapter weights with base model and save
        # save int 4 model
        trainer.model.save_pretrained(output_dir, safe_serialization=False)

        if accelerator.is_main_process:
            # clear memory
            del model
            del trainer

            torch.cuda.empty_cache()

            # load PEFT model
            model = AutoPeftModelForCausalLM.from_pretrained(
                output_dir,
                torch_dtype=torch.float16,
                low_cpu_mem_usage=True,
                trust_remote_code=True,
            )

            # Merge LoRA and base model and save
            model = model.merge_and_unload()
            model.save_pretrained(
                "/opt/ml/model", safe_serialization=True, max_shard_size="2GB"
            )
    else:
        trainer.model.save_pretrained("/opt/ml/model", safe_serialization=True)

    if accelerator.is_main_process:
        tokenizer.save_pretrained("/opt/ml/model")

    accelerator.wait_for_everyone()

train_fn(
    model_id,
    train_ds=train_dataset,
    test_ds=test_dataset,
    per_device_train_batch_size=2,
    per_device_eval_batch_size=1,
    gradient_accumulation_steps=2,
    gradient_checkpointing=True,
    num_train_epochs=1,
    fsdp="full_shard auto_wrap offload",
    fsdp_config={
        'backward_prefetch': 'backward_pre',
        'cpu_ram_efficient_loading': True,
        'offload_params': True,
        'forward_prefetch': False,
        'use_orig_params': False
    },
    merge_weights=True
)

(四)加载微调模型

注意:使用 merge_weights=True 运行 train_fn 以合并训练好的适配器

下载模型

import boto3
import sagemaker

sagemaker_session = sagemaker.Session()

model_id = "deepseek-ai/DeepSeek-R1-Distill-Llama-8B"

bucket_name = sagemaker_session.default_bucket()
default_prefix = sagemaker_session.default_bucket_prefix
job_prefix = f"train-{model_id.split('/')[-1].replace('.', '-')}"

def get_last_job_name(job_name_prefix):
    sagemaker_client = boto3.client('sagemaker')

    search_response = sagemaker_client.search(
        Resource='TrainingJob',
        SearchExpression={
            'Filters': [
                {
                    'Name': 'TrainingJobName',
                    'Operator': 'Contains',
                    'Value': job_name_prefix
                },
                {
                    'Name': 'TrainingJobStatus',
                    'Operator': 'Equals',
                    'Value': "Completed"
                }
            ]
        },
        SortBy='CreationTime',
        SortOrder='Descending',
        MaxResults=1)

    return search_response['Results'][0]['TrainingJob']['TrainingJobName']

job_name = get_last_job_name(job_prefix)

job_name

推理配置 

import sagemaker
from sagemaker import get_execution_role
from sagemaker import Model
instance_count = 1
instance_type = "ml.g5.4xlarge"
health_check_timeout = 700
image_uri = sagemaker.image_uris.retrieve(
    framework="djl-lmi",
    region=sagemaker_session.boto_session.region_name,
    version="latest"
)

image_uri
if default_prefix:
    model_data = f"s3://{bucket_name}/{default_prefix}/{job_name}/{job_name}/output/model.tar.gz"
else:
    model_data = f"s3://{bucket_name}/{job_name}/{job_name}/output/model.tar.gz"

model = Model(
    image_uri=image_uri,
    model_data=model_data,
    role=get_execution_role(),
    env={
        'HF_MODEL_ID': "/opt/ml/model", # path to where sagemaker stores the model
        'OPTION_TRUST_REMOTE_CODE': 'true',
        'OPTION_ROLLING_BATCH': "vllm",
        'OPTION_DTYPE': 'bf16',
        'OPTION_TENSOR_PARALLEL_DEGREE': 'max',
        'OPTION_MAX_ROLLING_BATCH_SIZE': '1',
        'OPTION_MODEL_LOADING_TIMEOUT': '3600',
        'OPTION_MAX_MODEL_LEN': '4096'
    }
)
model_id = "deepseek-ai/DeepSeek-R1-Distill-Llama-8B"

endpoint_name = f"{model_id.split('/')[-1].replace('.', '-')}-djl"
predictor = model.deploy(
    endpoint_name=endpoint_name,
    initial_instance_count=instance_count,
    instance_type=instance_type,
    container_startup_health_check_timeout=health_check_timeout,
    model_data_download_timeout=3600
)

 预测

import sagemaker
sagemaker_session = sagemaker.Session()
model_id = "deepseek-ai/DeepSeek-R1-Distill-Llama-8B"

endpoint_name = f"{model_id.split('/')[-1].replace('.', '-')}-djl"
predictor = sagemaker.Predictor(
    endpoint_name=endpoint_name,
    sagemaker_session=sagemaker_session,
    serializer=sagemaker.serializers.JSONSerializer(),
    deserializer=sagemaker.deserializers.JSONDeserializer(),
)
base_prompt = f"""<|begin_of_text|><|start_header_id|>user<|end_header_id|>{
  
  {question}}<|eot_id|><|start_header_id|>assistant<|end_header_id|>"""
prompt = base_prompt.format(question="What statue is in front of the Notre Dame building?")

response = predictor.predict({
	"inputs": prompt,
    "parameters": {
        "temperature": 0.2,
        "top_p": 0.9,
        "return_full_text": False,
        "stop": ['<|eot_id|>', '<|end_of_text|>']
    }
})

response = response["generated_text"].split("<|end_of_text|>")[0]

response

 删除端点

predictor.delete_model()
predictor.delete_endpoint(delete_endpoint_config=True)

四、实验结果与分析

(一)性能指标对比

将精调后的 DeepSeek-R1-Distilled-Llama-8B 模型与预训练模型在相同任务上进行性能对比。结果显示,精调后的模型在准确率、F1 值等指标上有显著提升,表明精调过程有效地提高了模型在特定任务上的性能表现。

(二)结果分析

  1. 优势分析:精调后的模型能够更好地理解和处理特定任务的数据,生成更准确、更符合需求的回答。这得益于在精调过程中,模型学习了目标任务的特定模式和知识,增强了对任务的适应性。
  2. 局限性分析:尽管精调后的模型性能有所提升,但仍然存在一些局限性。例如,在处理一些复杂的、语义模糊的问题时,模型的回答可能不够准确或完整。这可能是由于数据集的覆盖范围有限,或者模型的架构在处理复杂语义时存在一定的困难。

五、总结与展望

(一)实验总结

本次实验在 AWS SageMaker 平台上成功对 DeepSeek-R1-Distilled-Llama-8B 模型进行了精调,通过合理配置实验环境、选择合适的精调算法和优化策略,提升了模型在特定任务上的性能。实验结果表明,SageMaker 平台为语言模型的精调提供了强大的支持,QLoRA 算法在减少计算成本的同时有效地提高了模型性能。

(二)未来展望

  1. 模型改进方向:进一步探索更先进的精调算法和技术,如基于注意力机制的优化方法,以提高模型对复杂语义的理解和处理能力。同时,尝试增加数据集的规模和多样性,提高模型的泛化能力。
  2. 应用拓展:将精调后的模型应用到更多的实际场景中,如智能客服、智能写作等领域,验证模型的实用性和有效性。通过实际应用的反馈,不断优化模型,提升用户体验。

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

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

相关文章

【Rust自学】15.1. 使用Box<T>智能指针来指向堆内存上的数据

喜欢的话别忘了点赞、收藏加关注哦&#xff0c;对接下来的教程有兴趣的可以关注专栏。谢谢喵&#xff01;(&#xff65;ω&#xff65;) 15.1.1. Box<T> box<T>可以被简单地理解为装箱&#xff0c;它是最简单的智能指针&#xff0c;允许你在堆内存上存储数据&am…

Hive:复杂数据类型之Map函数

Map函数 是Hive里面的一种复杂数据类型, 用于存储键值对集合。Map中的键和值可以是基础类型或复合类型&#xff0c;这使得Map在处理需要关联存储信息的数据时非常有用。 定义map时,需声明2个属性: key 和 value , map中是 key value 组成一个元素 key-value, key必须为原始类…

Matlab实现TCN-BiLSTM时间卷积神经网络结合双向长短期记忆神经网络多特征分类预测(附模型研究报告)

Matlab实现TCN-BiLSTM时间卷积神经网络结合双向长短期记忆神经网络多特征分类预测&#xff08;附模型研究报告&#xff09; 目录 Matlab实现TCN-BiLSTM时间卷积神经网络结合双向长短期记忆神经网络多特征分类预测&#xff08;附模型研究报告&#xff09;分类效果基本描述程序设…

Midjourney中的强变化、弱变化、局部重绘的本质区别以及其有多逆天的功能

开篇 Midjourney中有3个图片“微调”&#xff0c;它们分别为&#xff1a; 强变化&#xff1b;弱变化&#xff1b;局部重绘&#xff1b; 在Discord里分别都是用命令唤出的&#xff0c;但如今随着AI技术的发达在类似AI可人一类的纯图形化界面中&#xff0c;我们发觉这样的逆天…

NLP深度学习 DAY4:Word2Vec详解:两种模式(CBOW与Skip-gram)

用稀疏向量表示文本&#xff0c;即所谓的词袋模型在 NLP 有着悠久的历史。正如上文中介绍的&#xff0c;早在 2001年就开始使用密集向量表示词或词嵌入。Mikolov等人在2013年提出的创新技术是通过去除隐藏层&#xff0c;逼近目标&#xff0c;进而使这些单词嵌入的训练更加高效。…

【Linux】 冯诺依曼体系与计算机系统架构全解

Linux相关知识点可以通过点击以下链接进行学习一起加油&#xff01;初识指令指令进阶权限管理yum包管理与vim编辑器GCC/G编译器make与Makefile自动化构建GDB调试器与Git版本控制工具Linux下进度条 冯诺依曼体系是现代计算机设计的基石&#xff0c;其统一存储和顺序执行理念推动…

【最后203篇系列】005 -QTV200 Online

说明 借着春节休假&#xff0c;把这部分完工&#xff0c;然后2025年将正式的把量化研究的成果进行产品化输出。 首先&#xff0c;我会将策略的执行从脚本挪到服务。做法是将策略的逻辑放在微服务里&#xff0c;作为一个接口&#xff0c;而由sniffer来触发策略执行。我想这样策…

Midjourney基础-常用修饰词+权重的用法大全

用好修饰词很关键 Midjourney要用除了掌握好提示词的写法&#xff0c;按照上一篇《做Midjourney最好图文教程-提示词公式以及高级参数讲解》画面主体 场景氛围 主体行为 构图方式 艺术风格 图像质量。 要画出有质感的内容我们必须要掌握好“修饰词”&#xff0c;这些修饰…

Deepseek的RL算法GRPO解读

在本文中&#xff0c;我们将深入探讨Deepseek采用的策略优化方法GRPO&#xff0c;并顺带介绍一些强化学习&#xff08;Reinforcement Learning, RL&#xff09;的基础知识&#xff0c;包括PPO等关键概念。 策略函数&#xff08;policy&#xff09; 在强化学习中&#xff0c; a…

神经网络和深度学习

应用 类型 为什么近几年飞速发展 数据增长&#xff0c;算力增长&#xff0c;算法革新 逻辑回归 向量化 浅层神经网络(Shallow neural network) 单条训练数据前向传播计算表达式 batch训练数据前向传播计算表达式 反向传播计算表达式 参数随机初始化 不能全部设为0 原因是同一…

python学opencv|读取图像(四十八)使用cv2.bitwise_xor()函数实现图像按位异或运算

【0】基础定义 按位与运算&#xff1a;两个等长度二进制数上下对齐&#xff0c;全1取1&#xff0c;其余取0。 按位或运算&#xff1a;两个等长度二进制数上下对齐&#xff0c;有1取1&#xff0c;其余取0。 按位取反运算&#xff1a;一个二进制数&#xff0c;0变1,1变0。 按…

关联传播和 Python 和 Scikit-learn 实现

文章目录 一、说明二、什么是 Affinity Propagation。2.1 先说Affinity 传播的工作原理2.2 更多细节2.3 传播两种类型的消息2.4 计算责任和可用性的分数2.4.1 责任2.4.2 可用性分解2.4.3 更新分数&#xff1a;集群是如何形成的2.4.4 估计集群本身的数量。 三、亲和力传播的一些…

【etcd】二进制安装etcd

由于生产服务器不能使用yum 安装 etcd ,或者 安装的etcd 版本比较老&#xff0c;这里介绍一个使用二进制安装的方式。 根据安装文档编写一个下载脚本即可 &#xff1a; 指定 etcd 的版本 提供了两个下载地址 一个 Google 一个 Github&#xff0c; 不过都需要外网 注释掉删除保…

企业知识管理平台助力企业创新与竞争力提升的有效策略探讨

内容概要 在当今快速发展的商业环境中&#xff0c;企业知识管理平台的构建显得至关重要。它不仅为企业的知识资源提供了一个整合与分享的空间&#xff0c;还为企业的创新与竞争力提升提供了策略支持。本文将深入探讨企业知识管理平台的关键要素&#xff0c;包括知识获取、存储…

Java多线程——线程安全性

线程安全性 当多个线程访问某个类时&#xff0c;这个类始终都能表现出正确的行为&#xff0c;那么就称这个类是线程安全的 public class A {public void test(){//....} }无状态对象是线程安全的&#xff0c;其不包含任何域&#xff0c;也不包含任何对其他类中域的引用&#…

Windows安装Miniconda和PySide6以及配置PyCharm

目录 1. 选择Miniconda 2. 下载Miniconda 3. 安装Miniconda 4. 在base环境下创建pyside6环境 5. 安装pyside6环境 6. 配置PyCharm环境 7. 运行第一个程序效果 1. 选择Miniconda 选择Miniconda而没有选择Anaconda&#xff0c;是因为它是一个更小的Anaconda发行版&#x…

C++传送锚点的内存寻址:内存管理

文章目录 1.C/C内存分布回顾2.C内存管理2.1 内存申请2.2 operator new与operator delete函数2.3 定位new表达式 3.关于内存管理的常见知识点3.1 malloc/free和new/delete的区别3.2 内存泄漏 希望读者们多多三连支持小编会继续更新你们的鼓励就是我前进的动力&#xff01; 继C语…

循序渐进kubernetes-RBAC(Role-Based Access Control)

文章目录 概要Kubernetes API了解 Kubernetes 中的 RBACRoles and Role Bindings:ClusterRoles and ClusterRoleBindings检查访问权限&#xff1a;外部用户结论 概要 Kubernetes 是容器化应用的强大引擎&#xff0c;但仅仅关注部署和扩展远远不够&#xff0c;集群的安全同样至…

《从因果关系的角度学习失真不变表示以用于图像恢复》学习笔记

paper&#xff1a;2303.06859 GitHub&#xff1a;lixinustc/Causal-IR-DIL: Distortion invariant feature learning for image restoration from a causality perspective 2023 CVPR 目录 摘要 1、介绍 1.1 图像修复任务 1.2 失真不变表示学习 1.3 因果效应估计的挑战…

亚博microros小车-原生ubuntu支持系列:16 机器人状态估计

本来想测试下gmapping建图&#xff0c;但是底层依赖了yahboomcar_bringup做底层的数据处理&#xff0c;所以先把依赖的工程导入。 程序启动后&#xff0c;会订阅imu和odom数据&#xff0c;过滤掉一部分的imu数据后&#xff0c;然后与odom数据进行融合&#xff0c;最后输出一个…