模型训练二三事:参数个数、小批量、学习率衰减、输入形状

目录

获取torch参数总数

方法一:使用torch.nn.Module的parameters()方法

方法二:使用state_dict()方法

迷你batch

什么是Mini-Batch?

如何在PyTorch中使用Mini-Batch?

不指定batchsize

没有标签ytrain

即使没有标签(y_train),

与epoch兼容

学习率的衰减

1. 使用torch.optim.lr_scheduler模块

StepLR

ExponentialLR

StepLR

ExponentialLR

对比

ReduceLROnPlateau

2. 自定义学习率衰减

输入形状


获取torch参数总数

在PyTorch中,要获取一个模型的参数总数,可以使用以下命令:

total_params = sum(p.numel() for p in model.parameters())

这里,model 是你的模型实例。model.parameters() 返回模型中所有参数的迭代器,p.numel() 返回单个参数的元素总数。sum 函数用来将这些数目加起来得到总的参数个数。

如果你还想要区分可训练参数和固定参数(比如批量归一化的统计量),可以分别计算:

trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
non_trainable_params = sum(p.numel() for p in model.parameters() if not p.requires_grad)

这样你就能得到模型中可训练参数和不可训练参数的数量。

第二个答案

在PyTorch中,计算一个模型的参数数量可以通过以下几种方式:

方法一:使用torch.nn.Moduleparameters()方法

import torch
import torch.nn as nn# 定义一个简单的模型
class SimpleModel(nn.Module):def __init__(self):super(SimpleModel, self).__init__()self.conv1 = nn.Conv2d(1, 10, kernel_size=5)self.conv2 = nn.Conv2d(10, 20, kernel_size=5)self.fc1 = nn.Linear(320, 50)self.fc2 = nn.Linear(50, 10)def forward(self, x):x = torch.relu(torch.max_pool2d(self.conv1(x), 2))x = torch.relu(torch.max_pool2d(self.conv2(x), 2))x = x.view(-1, 320)x = torch.relu(self.fc1(x))x = self.fc2(x)return x# 实例化模型
model = SimpleModel()# 计算参数数量
num_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
print(f"模型参数数量: {num_params}")

方法二:使用state_dict()方法

# 计算参数数量
num_params = sum(p.numel() for p in model.state_dict().values() if p.requires_grad)
print(f"模型参数数量: {num_params}")

以上两种方法都可以正确计算出模型中可训练参数的数量。requires_grad参数用于判断是否为可训练的参数。如果你想要计算所有的参数(包括不可训练的参数),可以去掉if p.requires_grad这部分条件判断。

迷你batch

在深度学习中,mini-batch是一种常用的数据处理方法,它涉及将整个数据集分成多个较小的批次(batches),然后逐个批次地训练模型。PyTorch是一个流行的开源深度学习框架,它支持mini-batch的实现。

什么是Mini-Batch?

  • 定义:Mini-batch是指将数据集分割成较小的子集,每个子集包含一定数量的样本。这些子集通常远小于整个数据集的大小。
  • 目的:使用mini-batch的主要目的是为了内存效率和计算效率。如果一次性处理整个数据集,可能会因为内存不足而无法进行训练。同时,使用mini-batch可以利用矩阵运算的并行化,加速训练过程。

如何在PyTorch中使用Mini-Batch?

以下是使用PyTorch进行mini-batch训练的基本步骤:

  1. 准备数据集:首先,你需要一个数据集。PyTorch提供了torch.utils.data.Dataset类,你可以通过继承这个类来创建自己的数据集。

  2. 数据加载器:使用torch.utils.data.DataLoader类来创建一个数据加载器。这个类负责将数据集分割成mini-batches,并提供一个迭代器,可以用来在训练循环中遍历这些批次。

下面是一个使用PyTorch进行mini-batch训练的简单例子:

import torch
from torch.utils.data import DataLoader, TensorDataset# 假设我们有一些数据和标签
X_train = torch.randn(100, 3, 32, 32)  # 100个样本,每个样本3x32x32
y_train = torch.randint(0, 10, (100,))  # 100个样本的标签# 创建一个TensorDataset对象
train_dataset = TensorDataset(X_train, y_train)# 创建DataLoader。这里设置batch_size为10,意味着每个mini-batch将包含10个样本
train_loader = DataLoader(dataset=train_dataset, batch_size=10, shuffle=True)# 训练模型
for epoch in range(num_epochs):for batch_idx, (data, target) in enumerate(train_loader):# 在这里进行模型的训练,例如:# output = model(data)# loss = loss_function(output, target)# optimizer.zero_grad()# loss.backward()# optimizer.step()pass  # 替换为实际的训练代码

在上面的代码中,DataLoaderbatch_size参数决定了每个mini-batch的大小。shuffle=True表示在每个epoch开始时,数据会被重新打乱,以确保模型不会在训练过程中记住数据的顺序。

通过这种方式,你可以有效地利用PyTorch进行基于mini-batch的深度学习模型训练。

不指定batchsize

在PyTorch中,如果你不指定DataLoaderbatch_size参数,它的默认值是1。这意味着如果没有指定batch_sizeDataLoader将默认每次迭代返回一个样本的数据和标签,而不是一次处理整个数据集或随机选取一个样本。

以下是DataLoader的默认参数:

  • batch_size: 默认为1
  • shuffle: 默认为False,即不会在每个epoch开始时打乱数据
  • sampler: 默认为None,但如果指定了sampler,那么shuffle必须为False
  • batch_sampler: 默认为None,如果指定了batch_sampler,则batch_sizeshufflesampler, 和 drop_last都不会起作用

因此,如果你不指定batch_size,你的训练循环将一次处理一个样本,这通常是不高效的,因为深度学习模型通常从并行处理多个样本中获益。以下是一个例子,展示了如果不指定batch_sizeDataLoader的行为:

import torch
from torch.utils.data import DataLoader, TensorDataset# 假设我们有一些数据和标签
X_train = torch.randn(100, 3, 32, 32)  # 100个样本,每个样本3x32x32
y_train = torch.randint(0, 10, (100,))  # 100个样本的标签# 创建一个TensorDataset对象
train_dataset = TensorDataset(X_train, y_train)# 创建DataLoader,没有指定batch_size
train_loader = DataLoader(dataset=train_dataset)# 训练模型
for epoch in range(num_epochs):for batch_idx, (data, target) in enumerate(train_loader):# 在这里,data和target将只包含一个样本# ...pass  # 替换为实际的训练代码

在上面的例子中,datatarget在每个迭代中都会包含一个样本。如果你希望一次处理多个样本,你应该显式地设置batch_size参数。

没有标签ytrain

在PyTorch中,如果你想要构造一个没有标签的TensorDataset,你可以只传入数据(x_train)而不需要标签。以下是如何操作的步骤:

  1. 首先,确保你的数据x_train是一个torch.Tensor

  2. 使用torch.utils.data.TensorDataset来创建一个数据集。由于你不需要标签,你可以传入x_train和一个与x_train相同形状的全零张量作为占位符。

下面是一个示例代码:

import torch
from torch.utils.data import TensorDataset, DataLoader# 假设 x_train 是你的数据,它是一个形状为 [num_samples, num_features] 的张量
x_train = torch.randn(100, 10)  # 示例数据# 创建一个与 x_train 相同形状的全零张量作为占位符
no_labels = torch.zeros(100, 10)  # 假设你不需要标签,这里只是占位# 创建 TensorDataset,这里 no_labels 不会被使用
dataset = TensorDataset(x_train, no_labels)# 创建 DataLoader
dataloader = DataLoader(dataset, batch_size=10, shuffle=True)# 使用 DataLoader
for data in dataloader:# data 是一个元组,包含数据和标签,但由于没有标签,你可以忽略第二个元素inputs = data[0]  # 这就是你的 x_train 数据# 进行你的模型训练或其他操作

在这个例子中,no_labels张量不会被实际使用,它仅仅是为了构造TensorDataset实例。在迭代DataLoader时,你可以直接使用data[0]来获取你的输入数据。如果你确定不需要标签,也可以通过切片操作来只获取数据部分:

for inputs in dataloader:# inputs 直接是你的 x_train 数据# 进行你的模型训练或其他操作

这样,你就可以在不使用标签的情况下使用TensorDatasetDataLoader了。

即使没有标签(y_train),

你也可以在PyTorch中实现迷你批次(mini-batch)训练。以下是如何使用DataLoader来创建一个只有输入数据(x_train)的迷你批次的过程:

  1. 首先,确保你的输入数据x_train是一个torch.Tensor

  2. 使用torch.utils.data.TensorDataset来创建一个数据集,传入x_train和一个与x_train相同形状的全零张量作为占位符(如果你不想使用标签)。

  3. 使用DataLoader来包装你的TensorDataset,并通过设置batch_size参数来定义每个批次的大小。

下面是一个示例代码:

import torch
from torch.utils.data import TensorDataset, DataLoader# 假设 x_train 是你的输入数据,它是一个形状为 [num_samples, num_features] 的张量
x_train = torch.randn(100, 10)  # 示例数据# 创建一个与 x_train 相同形状的全零张量作为占位符
# 如果你不需要标签,这个张量实际上不会被使用
no_labels = torch.zeros(100, 10)# 创建 TensorDataset,这里 no_labels 不会被使用
dataset = TensorDataset(x_train, no_labels)# 创建 DataLoader,设置 batch_size 来定义每个批次的大小
batch_size = 32  # 你可以根据需要调整批次大小
dataloader = DataLoader(dataset, batch_size=batch_size, shuffle=True)# 使用 DataLoader 来进行迷你批次训练
for inputs in dataloader:# 由于没有标签,inputs 将只包含输入数据# inputs 的形状将是 [batch_size, num_features]# 这里是模型训练的伪代码# outputs = model(inputs)  # 前向传播# loss = loss_function(outputs)  # 计算损失(这里没有标签,所以损失函数需要自行定义)# loss.backward()  # 反向传播# optimizer.step()  # 更新权重

在这个例子中,DataLoader会自动将x_train分成指定大小的迷你批次,并且每个批次都会在训练循环中被迭代。由于没有标签,你可能需要定义一个不需要标签的损失函数,例如自编码器(autoencoder)中的重构误差,或者使用无监督学习的方法。

注意,如果你不打算使用标签,并且不需要第二个元素,你可以简化for循环中的代码,直接从DataLoader中获取输入数据:

 input,占位符_

for inputs, _ in dataloader:# 这里只使用 inputs,忽略 _# 进行模型训练或其他操作

在这个简化的版本中,下划线(_)是一个常见的Python约定,用于表示一个不需要的变量。

与epoch兼容

要在训练过程中同时实现多个epoch和mini-batch,你可以使用PyTorch的DataLoader来处理mini-batch,并在一个外部循环中迭代多个epoch。以下是一个示例代码,展示了如何实现这个过程:

import torch
from torch.utils.data import TensorDataset, DataLoader# 假设 x_train 和 y_train 是你的输入数据和标签
# x_train = torch.randn(batch_size, num_features)
# y_train = torch.randn(batch_size, num_targets)# 创建 TensorDataset
dataset = TensorDataset(x_train, y_train)# 创建 DataLoader
batch_size = 32  # 你可以根据需要设置batch_size
dataloader = DataLoader(dataset, batch_size=batch_size, shuffle=True)# 初始化你的模型
# model = YourModel()# 选择一个优化器
# optimizer = torch.optim.Adam(model.parameters(), lr=0.001)# 选择一个损失函数
# loss_function = torch.nn.MSELoss()  # 例如,对于回归问题# 训练模型
for epoch in range(1000):for inputs, targets in dataloader:# 前向传播outputs = model(inputs)# 计算损失loss = loss_function(outputs, targets)# 反向传播和优化optimizer.zero_grad()  # 清空过往梯度loss.backward()        # 反向传播,计算当前梯度optimizer.step()       # 根据梯度更新网络参数# 在每个epoch后可以打印损失,进行验证等print(f'Epoch {epoch+1}/{1000}, Loss: {loss.item()}')

在这个例子中,外层循环 for epoch in range(1000): 负责迭代1000个epochs。内层循环 for inputs, targets in dataloader: 负责在每个epoch内进行mini-batch的训练。

注意,这里假设你已经有了 x_train 和 y_train 数据,并且已经定义了模型、优化器和损失函数。你需要根据你的具体任务来调整这些组件。此外,shuffle=True 参数确保在每个epoch开始时数据会被重新打乱,这有助于模型的泛化能力。

学习率的衰减

可以自己写模块,也可以掉包

在训练深度学习模型时,学习率的衰减是一种常用的策略,可以帮助模型在训练过程中更好地收敛。学习率衰减意味着随着训练的进行,学习率会逐渐减小,这有助于模型在训练初期快速学习,并在训练后期精细调整参数以避免过拟合。

在PyTorch中,可以使用以下几种方法来实现学习率的衰减:

1. 使用torch.optim.lr_scheduler模块

lr_scheduler模块旗下有指数衰减、等策略

PyTorch提供了lr_scheduler模块,其中包含了几种预定义的学习率衰减策略。以下是一些常用的学习率衰减方法:

StepLR

v

import torch.optim as optim# 初始化优化器
optimizer = optim.Adam(model.parameters(), lr=0.001)# 初始化学习率调度器
scheduler = optim.lr_scheduler.StepLR(optimizer, step_size=30, gamma=0.1)# 训练循环
for epoch in range(num_epochs):# 训练代码...scheduler.step()  # 更新学习率

StepLR中,step_size是学习率衰减的周期,gamma是衰减率。

ExponentialLR

scheduler = optim.lr_scheduler.ExponentialLR(optimizer, gamma=0.98)

ExponentialLR会以指数方式衰减学习率,gamma是衰减率。

就是是否要等待多少步的区别

ExponentialLRStepLR是PyTorch中两种不同的学习率衰减策略,它们的主要区别在于学习率衰减的方式:

StepLR

  • 衰减方式StepLR按照固定的间隔(步长)来减少学习率。在每个指定的步长结束后,学习率会乘以一个固定的衰减因子(gamma)。
  • 参数
    • step_size:学习率更新的周期,即每过多少个epoch后学习率乘以gamma
    • gamma:学习率衰减的乘数因子。
  • 特点:学习率的衰减是离散的,即在特定的epoch数之后学习率会突然减少。

ExponentialLR

  • 衰减方式ExponentialLR则是连续地按照指数衰减的方式减少学习率。在每个epoch结束后,学习率都会乘以一个固定的衰减因子(gamma)。
  • 参数
    • gamma:每个epoch结束后学习率乘以的衰减因子。
  • 特点:学习率的衰减是连续的,每次更新都会按照指数规律减少,而不是在特定的epoch数之后突然减少。

对比

  • 更新频率StepLR在每隔step_size个epoch后更新一次学习率,而ExponentialLR在每个epoch后都会更新学习率。
  • 衰减模式StepLR的衰减是阶梯式的,而ExponentialLR的衰减是平滑的,逐渐减小。
  • 使用场景StepLR适用于那些需要在不同阶段使用不同学习率的情况,而ExponentialLR适用于需要平滑过渡到更小学习率的情况。

以下是一个简单的例子来说明两者的区别:

import torch.optim as optim# 假设有一个简单的模型和优化器
model = ...
optimizer = optim.SGD(model.parameters(), lr=0.1)# StepLR 示例
scheduler_step = optim.lr_scheduler.StepLR(optimizer, step_size=30, gamma=0.1)# ExponentialLR 示例
scheduler_exp = optim.lr_scheduler.ExponentialLR(optimizer, gamma=0.99)# 假设训练100个epoch
for epoch in range(1, 101):# 训练代码...# StepLR 更新if epoch % 30 == 0:scheduler_step.step()# ExponentialLR 更新scheduler_exp.step()

在这个例子中,StepLR每30个epoch将学习率乘以0.1,而ExponentialLR每个epoch都将学习率乘以0.99。随着时间的推移,ExponentialLR的学习率会逐渐减小,而StepLR的学习率会在每个指定的epoch突然减小。

ReduceLROnPlateau

scheduler = optim.lr_scheduler.ReduceLROnPlateau(optimizer, 'min', factor=0.1, patience=10)# 训练循环
for epoch in range(num_epochs):# 训练代码...val_loss = ...  # 验证集损失scheduler.step(val_loss)  # 根据验证集损失更新学习率

ReduceLROnPlateau会在指标停止改进时减少学习率,factor是衰减率,patience是在更新学习率之前等待的epoch数。

2. 自定义学习率衰减

如果你想要自定义学习率衰减策略,可以直接在训练循环中更新优化器的学习率:

initial_lr = 0.001
decay_rate = 0.1
decay_steps = 30for epoch in range(num_epochs):# 训练代码...if epoch % decay_steps == 0 and epoch != 0:for param_group in optimizer.param_groups:param_group['lr'] *= decay_rate

在这个例子中,每30个epoch,学习率就会乘以衰减率decay_rate

使用这些方法之一,你可以在训练过程中实现学习率的衰减,帮助模型更好地收敛。记得在选择学习率衰减策略时,需要根据你的具体问题和模型调整参数。

输入形状

在监督学习中,x_train(输入数据)和 y_train(标签或目标数据)的形状关系取决于具体的学习任务和数据组织方式。以下是一些常见的情况:

  1. 回归任务

    • x_train 的形状通常是 [num_samples, num_features],其中 num_samples 是样本数量,num_features 是每个样本的特征数量。
    • y_train 的形状通常是 [num_samples, 1](如果目标是单个连续值)或者 [num_samples, num_targets](如果有多个连续目标值)。

    例如,对于单个目标值的回归问题:

    • x_train[100, 10](100个样本,每个样本10个特征)
    • y_train[100, 1](100个样本的单一目标值)
  2. 分类任务

    • x_train 的形状同样是 [num_samples, num_features]
    • y_train 的形状可以是 [num_samples](如果任务是二分类或多分类的单标签问题,并且标签是整数编码的)或者 [num_samples, num_classes](如果任务是多标签问题或者使用one-hot编码的多分类问题)。

    例如,对于一个多分类问题:

    • x_train[100, 10](100个样本,每个样本10个特征)
    • y_train[100](100个样本的类别标签,如果使用整数编码)
    • 或者 y_train[100, num_classes](100个样本的one-hot编码类别标签)
  3. 序列模型

    • 对于序列模型(如RNN、LSTM),x_train 的形状通常是 [num_samples, sequence_length, num_features]
    • y_train 的形状可以是 [num_samples, sequence_length](如果每个时间步都有预测目标)或者 [num_samples, 1](如果整个序列有一个预测目标)。

    例如,对于时间序列预测:

    • x_train[100, 50, 10](100个样本,每个样本序列长度为50,每个时间步10个特征)
    • y_train[100, 1](100个样本的未来时间步预测值)

总之,x_train 和 y_train 的形状必须兼容,以便在训练过程中正确地进行批量处理和矩阵运算。具体的关系取决于模型的输入和输出要求。

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

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

相关文章

gitlab高级功能之 CICD Steps

CICD Steps 1. 介绍2. 定义 Steps2.1 Inputs2.2 Outputs 3. Using steps3.1 Set environment variables3.2 Running steps locally 4. Scripts5. Actions5.1 已知的问题 6. 表达式7. 实操7.1 单个step7.2 多个step7.3 复用steps7.4 添加output到step7.5 使用远程step 1. 介绍 …

开源数据集成平台白皮书重磅发布《Apache SeaTunnel 2024用户案例合集》!

2025年新年临近,Apache SeaTunnel 社区用户案例精选📘也跟大家见面啦!在过去的时间里,SeaTunnel 社区持续成长,吸引了众多开发者的关注与支持。 为了致谢一路同行的伙伴,也为了激励更多人加入技术共创&…

第六十四章 假脱机设备 - 使用 %SPOOL 打印

文章目录 第六十四章 假脱机设备 - 使用 %SPOOL 打印使用 %SPOOL 打印使用 Print 函数 第六十四章 假脱机设备 - 使用 %SPOOL 打印 使用 %SPOOL 打印 %SPOOL 实用程序菜单的选项 1 Print(打印)允许您在任何设备上打印 ^SPOOL 全局中的一个或多个文档&a…

Python:交互式物质三态知识讲解小工具

学着物理写着Python 以下是一个使用Python的Tkinter库实现的简单示例程序,通过图形界面展示并讲解固态、液态、气态的一些特点,代码中有详细的注释来帮助你理解各部分功能: 完整代码 import tkinter as tk from tkinter import ttk import …

选择IT驻场外包公司,要找有哪些资质的公司

在当今数字化快速发展的时代,IT驻场外包服务成为众多企业优化运营、提升竞争力的关键选择。无论是初创企业寻求技术起步支持,还是大型企业为降低成本、专注核心业务而将部分 IT 职能外包,IT 外包公司都扮演着至关重要的角色。然而&#xff0c…

多模态论文笔记——CogVLM和CogVLM2(副)

大家好,这里是好评笔记,公主号:Goodnote,专栏文章私信限时Free。本文详细介绍多模态模型的LoRA版本——CogVLM和CogVLM2。在SD 3中使用其作为captioner基准模型的原因和优势。 文章目录 CogVLM论文背景VLMs 的任务与挑战现有方法及…

Scala 访问修饰符

Scala 访问修饰符 在编程语言中,访问修饰符是一种重要的语法元素,它用于控制类、对象、特质、接口、方法和变量的访问级别。Scala作为一种多范式编程语言,也提供了丰富的访问修饰符,以实现封装和隐藏内部实现细节。本文将详细介绍…

网络安全抓包

#知识点: 1、抓包技术应用意义 //有些应用或者目标是看不到的,这时候就要进行抓包 2、抓包技术应用对象 //app,小程序 3、抓包技术应用协议 //http,socket 4、抓包技术应用支持 5、封包技术应用意义 总结点:学会不同对象采用…

Innodisk iSMART V6使用说明_SSD还能用多久?已经读写了多少次数?……

Innodisk iSMART是一款SSD健康数据读取软件。它能轻松获取大部分SSD内部寄存器中的健康数据,并以简洁的图形界面展示给用户。在程序界面的顶部,是页面标签,点击页面标签就能切换到相应的页面。页面标签的下面是磁盘选择栏。点击磁盘编号&…

网络编程原理:回显服务器与客户端通信交互功能

文章目录 路由器及网络概念网络通信基础TCP/IP 五层协议封装和分用封装分用 网络编程(网络协议)UDP类 API使用实现回显通信程序回显服务器(UDP代码)回显客户端(UDP代码) TCP API使用回显服务器(TCP代码)回显客户端(TCP代码) 路由器及网络概念 网络发展是…

设计模式 创建型 建造者模式(Builder Pattern)与 常见技术框架应用 解析

单例模式(Singleton Pattern),又称生成器模式,是一种对象构建模式。它主要用于构建复杂对象,通过将复杂对象的构建过程与其表示分离,使得同样的构建过程可以创建出具有不同表示的对象。该模式的核心思想是将…

【C++】P1428 小鱼比可爱

博客主页: [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C 文章目录 💯前言💯题目说明题目输入格式题目输出格式样例**输入样例****输出样例** 题目解析 💯解法分析我的做法代码解法说明时间复杂度 老师的做法代码解法说明总结时间复杂度 …

[coredump] 生成管理

在 Linux 系统中,core dump 文件的生成路径和文件名可以通过几个方面来控制: 系统默认路径: 默认情况下,core dump 文件通常生成在程序的工作目录,即程序运行时的当前目录。文件名通常为 core,或者在某些系…

maven之插件调试

当使用maven进行项目管理的时候,可能会碰到一些疑难问题。网上资料很少,可能会想着直接调试定位问题。这里以maven-compiler-plugin为例: (1)准备maven-compiler-plugin源码 进入maven 官网-》Maven Plugins-》找到对…

CentOS 8 上搭建SFTP服务

安装 在CentOS 8上搭建SFTP服务,可以通过OpenSSH来实现。以下是具体步骤: 1. 安装OpenSSH服务器 在CentOS 8中,通常已经安装了OpenSSH服务器。如果没有,可以通过以下命令安装: sudo dnf install -y openssh-server…

【系统分析师】- 案例 -数据库特训

目录 1、规范化与逆规范化 2、数据库视图 3、数据库索引 4、SQL优化 5、数据库分区 6、分布式数据库 7、NoSql 8、读写分离(主从复制) 9、缓存一致性 10、云数据库 11、主题数据库 12、数据同步 1、规范化与逆规范化 规范化: 优点…

Redis(基础篇 + 实践篇 )

01 | 基本架构:一个键值数据库包含什么? Redis 作为一个内存数据存储系统,它的架构设计非常简洁,但功能非常强大。理解其核心架构对高效使用 Redis 至关重要。 客户端与服务器架构: 客户端通过 TCP 协议连接到 Redis …

蓝桥杯(Java)(ing)

Java前置知识 输入流: (在Java面向对象编程-CSDN博客里面有提过相关知识------IO流) // 快读快写 static BufferedReader in new BufferedReader(new InputStreamReader(System.in)); static BufferedWriter out new BufferedWriter(new…

GaussDB逻辑解码技术原理深度解析

GaussDB逻辑解码技术原理深度解析 一、背景介绍 在数字化转型的大潮中,异构数据库之间的数据同步需求日益增长。异构数据库同步指的是将不同类型、不同结构的数据库之间的数据进行同步处理,以确保数据在不同数据库之间的一致性。华为云提供的DRS服务&a…

【C++】深入理解C语言中的特殊字符处理与问题分析优化

博客主页: [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: C 文章目录 💯前言💯题目:B2090 年龄与疾病输入格式输出格式输入输出样例 💯初始代码分析与问题排查问题点分析 💯修正后的代码与优化修正与优化要点 &#…