Python60日基础学习打卡D35

news2025/5/27 12:11:29
import torch
import torch.nn as nn
import torch.optim as optim
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import MinMaxScaler
import time
import matplotlib.pyplot as plt

# 设置GPU设备
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
print(f"使用设备: {device}")

# 加载鸢尾花数据集
iris = load_iris()
X = iris.data  # 特征数据
y = iris.target  # 标签数据

# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 归一化数据
scaler = MinMaxScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)

# 将数据转换为PyTorch张量并移至GPU
X_train = torch.FloatTensor(X_train).to(device)
y_train = torch.LongTensor(y_train).to(device)
X_test = torch.FloatTensor(X_test).to(device)
y_test = torch.LongTensor(y_test).to(device)

class MLP(nn.Module):
    def __init__(self):
        super(MLP, self).__init__()
        self.fc1 = nn.Linear(4, 10)  # 输入层到隐藏层
        self.relu = nn.ReLU()
        self.fc2 = nn.Linear(10, 3)  # 隐藏层到输出层

    def forward(self, x):
        out = self.fc1(x)
        out = self.relu(out)
        out = self.fc2(out)
        return out

# 实例化模型并移至GPU
model = MLP().to(device)

# 分类问题使用交叉熵损失函数
criterion = nn.CrossEntropyLoss()

# 使用随机梯度下降优化器
optimizer = optim.SGD(model.parameters(), lr=0.01)

# 训练模型
num_epochs = 20000  # 训练的轮数

# 用于存储每100个epoch的损失值和对应的epoch数
losses = []

start_time = time.time()  # 记录开始时间

for epoch in range(num_epochs):
    # 前向传播
    outputs = model(X_train)  # 隐式调用forward函数
    loss = criterion(outputs, y_train)

    # 反向传播和优化
    optimizer.zero_grad() #梯度清零,因为PyTorch会累积梯度,所以每次迭代需要清零,梯度累计是那种小的bitchsize模拟大的bitchsize
    loss.backward() #  反向传播计算梯度
    optimizer.step() # 更新参数

    # 记录损失值
    if (epoch + 1) % 200 == 0:
        losses.append(loss.item()) # item()方法返回一个Python数值,loss是一个标量张量
        print(f'Epoch [{epoch+1}/{num_epochs}], Loss: {loss.item():.4f}')
    
    # 打印训练信息
    if (epoch + 1) % 100 == 0: # range是从0开始,所以epoch+1是从当前epoch开始,每100个epoch打印一次
        print(f'Epoch [{epoch+1}/{num_epochs}], Loss: {loss.item():.4f}')

time_all = time.time() - start_time  # 计算训练时间
print(f'Training time: {time_all:.2f} seconds')


# 可视化损失曲线
plt.plot(range(len(losses)), losses)
plt.xlabel('Epoch')
plt.ylabel('Loss')
plt.title('Training Loss over Epochs')
plt.show()

一、模型结构可视化

理解一个深度学习网络最重要的2点:

  1. 了解损失如何定义的,知道损失从何而来----把抽象的任务通过损失函数量化出来
  2. 了解参数总量,即知道每一层的设计才能退出---层设计决定参数总量

为了了解参数总量,我们需要知道层设计,以及每一层参数的数量。下面介绍1几个层可视化工具:

1.1 nn.model自带的方法(直接print)

#  nn.Module 的内置功能,直接输出模型结构
print(model)

# nn.Module 的内置功能,返回模型的可训练参数迭代器
for name, param in model.named_parameters():
    print(f"Parameter name: {name}, Shape: {param.shape}")
# 提取权重数据
import numpy as np
weight_data = {}
for name, param in model.named_parameters():
    if 'weight' in name:
        weight_data[name] = param.detach().cpu().numpy()

# 可视化权重分布
fig, axes = plt.subplots(1, len(weight_data), figsize=(15, 5))
fig.suptitle('Weight Distribution of Layers')

for i, (name, weights) in enumerate(weight_data.items()):
    # 展平权重张量为一维数组
    weights_flat = weights.flatten()
    
    # 绘制直方图
    axes[i].hist(weights_flat, bins=50, alpha=0.7)
    axes[i].set_title(name)
    axes[i].set_xlabel('Weight Value')
    axes[i].set_ylabel('Frequency')
    axes[i].grid(True, linestyle='--', alpha=0.7)

plt.tight_layout()
plt.subplots_adjust(top=0.85)
plt.show()

# 计算并打印每层权重的统计信息
print("\n=== 权重统计信息 ===")
for name, weights in weight_data.items():
    mean = np.mean(weights)
    std = np.std(weights)
    min_val = np.min(weights)
    max_val = np.max(weights)
    print(f"{name}:")
    print(f"  均值: {mean:.6f}")
    print(f"  标准差: {std:.6f}")
    print(f"  最小值: {min_val:.6f}")
    print(f"  最大值: {max_val:.6f}")
    print("-" * 30)

=== 权重统计信息 ===
fc1.weight:
  均值: 0.013520
  标准差: 0.935024
  最小值: -2.185144
  最大值: 2.903806
------------------------------
fc2.weight:
  均值: 0.027174
  标准差: 1.232366
  最小值: -3.307564
  最大值: 3.074636
------------------------------

对比 fc1.weight 和 fc2.weight 的统计信息 ,它们的均值、标准差、最值等存在的差异同样具有参考价值

权重统计信息可以为超参数调整提供参考。例如,如果发现权重标准差过大导致训练不稳定,可以尝试调整学习率,使权重更新更平稳;或者改变权重初始化方法,使初始权重分布更合理。如果最小值和最大值在训练后期仍波动较大,可能需要考虑调整正则化参数,防止过拟合或欠拟

1.2 torchsummary库的summary方法

# pip install torchsummary -i https://pypi.tuna.tsinghua.edu.cn/simple

from torchsummary import summary
# 打印模型摘要,可以放置在模型定义后面
summary(model, input_size=(4,))
----------------------------------------------------------------
        Layer (type)               Output Shape         Param #
================================================================
            Linear-1                   [-1, 10]              50
              ReLU-2                   [-1, 10]               0
            Linear-3                    [-1, 3]              33
================================================================
Total params: 83
Trainable params: 83
Non-trainable params: 0
----------------------------------------------------------------
Input size (MB): 0.00
Forward/backward pass size (MB): 0.00
Params size (MB): 0.00
Estimated Total Size (MB): 0.00
----------------------------------------------------------------

因为输入的神经网是自己设置的,所以不需要显示输入层的尺寸。 但是在使用该方法时,input_size=(4,) 参数是必需的,因为 PyTorch 需要知道输入数据的形状才能推断模型各层的输出形状和参数数量。

这是因为PyTorch 的模型在定义时是动态的,它不会预先知道输入数据的具体形状。nn.Linear(4, 10) 只定义了 “输入维度是 4,输出维度是 10”,但不知道输入的批量大小和其他维度,比如卷积层需要知道输入的通道数、高度、宽度等信息——并非所有输入数据都是结构化数据

因此,要生成模型摘要(如每层的输出形状、参数数量),必须提供一个示例输入形状input_size=(4,),让 PyTorch “运行” 一次模型,从而推断出各层的信息。

summary 函数的核心逻辑是:

  1. 创建一个与 input_size 形状匹配的虚拟输入张量(通常填充零)summary(model, input_size=input_size)
  2. 将虚拟输入传递给模型,执行一次前向传播(但不计算梯度)
  3. 记录每一层的输入和输出形状,以及参数数量
  4. 生成可读的摘要报告

不同场景下的 input_size 示例

模型类型输入类型input_size 示例实际输入形状(batch_size=32)
MLP(单样本)一维特征向量(4,)(32, 4)
CNN(图像)三维图像(C,H,W)(3, 224, 224)(32, 3, 224, 224)
RNN(序列)二维序列(seq_len, feat)(10, 5)(32, 10, 5)

其中最开始的参数的值是默认初始化的,初始化有很多方法,后面接触到复杂的模型再提

构建神经网络的时候

  1. 输入层不需要写:x多少个特征,输入层就有多少神经元
  2. 隐藏层需要写,从第一个隐藏层可以看出特征的个数
  3. 输出层的神经元和任务有关,比如分类任务,输出层有3个神经元,一个对应每个类别

 

可学习参数计算

  1. Linear-1对应self.fc1 = nn.Linear(4, 10),表明前一层有4个神经元,这一层有10个神经元,每2个神经元之间靠着线相连,所有有4*10个权重参数+10个偏置参数=50个参数
  2. relu层不涉及可学习参数,可以把它和前一个线性层看成一层,图上也是这个含义
  3. Linear-3层对应代码 self.fc2 = nn.Linear(10,3),10*3个权重参数+3个偏置=33个参数

总参数83个,占用内存几乎为0

1.3 torchinfo库的summary方法

torchinfo 是提供比 torchsummary 更详细的模型摘要信息,包括每层的输入输出形状、参数数量、计算量等。

from torchinfo import summary
summary(model, input_size=(4, ))
==========================================================================================
Layer (type:depth-idx)                   Output Shape              Param #
==========================================================================================
MLP                                      [3]                       --
├─Linear: 1-1                            [10]                      50
├─ReLU: 1-2                              [10]                      --
├─Linear: 1-3                            [3]                       33
==========================================================================================
Total params: 83
Trainable params: 83
Non-trainable params: 0
Total mult-adds (M): 0.00
==========================================================================================
Input size (MB): 0.00
Forward/backward pass size (MB): 0.00
Params size (MB): 0.00
Estimated Total Size (MB): 0.00
==========================================================================================

torchinfo这个库常常和tensorboard一起使用,我们后面会介绍

二、 进度条功能

我们介绍下tqdm这个库,他非常适合用在循环中观察进度。尤其在深度学习这种训练是循环的场景中。他最核心的逻辑如下

  1. 创建一个进度条对象,并传入总迭代次数。一般用with语句创建对象,这样对象会在with语句结束后自动销毁,保证资源释放。with是常见的上下文管理器,这样的使用方式还有用with打开文件,结束后会自动关闭文件。

  2. 更新进度条,通过pbar.update(n)指定每次前进的步数n(适用于非固定步长的循环)。

2.1 手动更新

from tqdm import tqdm  # 先导入tqdm库
import time  # 用于模拟耗时操作

# 创建一个总步数为10的进度条
with tqdm(total=10) as pbar:  # pbar是进度条对象的变量名
    # pbar 是 progress bar(进度条)的缩写,约定俗成的命名习惯。
    for i in range(10):  # 循环10次(对应进度条的10步)
        time.sleep(0.5)  # 模拟每次循环耗时0.5秒
        pbar.update(1)  # 每次循环后,进度条前进1步
100%|██████████| 10/10 [00:05<00:00,  1.95it/s]
from tqdm import tqdm
import time

# 创建进度条时添加描述(desc)和单位(unit)
with tqdm(total=5, desc="下载文件", unit="个") as pbar:
    # 进度条这个对象,可以设置描述和单位
    # desc是描述,在左侧显示
    # unit是单位,在进度条右侧显示
    for i in range(5):
        time.sleep(1)
        pbar.update(1)  # 每次循环进度+1
下载文件: 100%|██████████| 5/5 [00:05<00:00,  1.01s/个]

unit 参数的核心作用是明确进度条中每个进度单位的含义,使可视化信息更具可读性。在深度学习训练中,常用的单位包括:

  • epoch:训练轮次(遍历整个数据集一次)。
  • batch:批次(每次梯度更新处理的样本组)。
  • sample:样本(单个数据点)

2.2 自动更新

from tqdm import tqdm
import time

# 直接将range(3)传给tqdm,自动生成进度条
# 这个写法我觉得是有点神奇的,直接可以给这个对象内部传入一个可迭代对象,然后自动生成进度条
for i in tqdm(range(3), desc="处理任务", unit="epoch"):
    time.sleep(1)
处理任务: 100%|██████████| 3/3 [00:03<00:00,  1.01s/epoch]

for i in tqdm(range(3), desc="处理任务", unit="个")这个写法则不需要在循环中调用update()方法,更加简洁

实际上这2种写法都随意选取,这里都介绍下

# 用tqdm的set_postfix方法在进度条右侧显示实时数据(如当前循环的数值、计算结果等):
from tqdm import tqdm
import time

total = 0  # 初始化总和
with tqdm(total=10, desc="累加进度") as pbar:
    for i in range(1, 11):
        time.sleep(0.3)
        total += i  # 累加1+2+3+...+10
        pbar.update(1)  # 进度+1
        pbar.set_postfix({"当前总和": total})  # 显示实时总和
累加进度: 100%|██████████| 10/10 [00:03<00:00,  3.22it/s, 当前总和=55]
import torch
import torch.nn as nn
import torch.optim as optim
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import MinMaxScaler
import time
import matplotlib.pyplot as plt
from tqdm import tqdm  # 导入tqdm库用于进度条显示

# 设置GPU设备
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
print(f"使用设备: {device}")

# 加载鸢尾花数据集
iris = load_iris()
X = iris.data  # 特征数据
y = iris.target  # 标签数据

# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 归一化数据
scaler = MinMaxScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)

# 将数据转换为PyTorch张量并移至GPU
X_train = torch.FloatTensor(X_train).to(device)
y_train = torch.LongTensor(y_train).to(device)
X_test = torch.FloatTensor(X_test).to(device)
y_test = torch.LongTensor(y_test).to(device)

class MLP(nn.Module):
    def __init__(self):
        super(MLP, self).__init__()
        self.fc1 = nn.Linear(4, 10)  # 输入层到隐藏层
        self.relu = nn.ReLU()
        self.fc2 = nn.Linear(10, 3)  # 隐藏层到输出层

    def forward(self, x):
        out = self.fc1(x)
        out = self.relu(out)
        out = self.fc2(out)
        return out

# 实例化模型并移至GPU
model = MLP().to(device)

# 分类问题使用交叉熵损失函数
criterion = nn.CrossEntropyLoss()

# 使用随机梯度下降优化器
optimizer = optim.SGD(model.parameters(), lr=0.01)

# 训练模型
num_epochs = 20000  # 训练的轮数

# 用于存储每100个epoch的损失值和对应的epoch数
losses = []
epochs = []

start_time = time.time()  # 记录开始时间

# 创建tqdm进度条
with tqdm(total=num_epochs, desc="训练进度", unit="epoch") as pbar:
    # 训练模型
    for epoch in range(num_epochs):
        # 前向传播
        outputs = model(X_train)  # 隐式调用forward函数
        loss = criterion(outputs, y_train)

        # 反向传播和优化
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()

        # 记录损失值并更新进度条
        if (epoch + 1) % 200 == 0:
            losses.append(loss.item())
            epochs.append(epoch + 1)
            # 更新进度条的描述信息
            pbar.set_postfix({'Loss': f'{loss.item():.4f}'})

        # 每1000个epoch更新一次进度条
        if (epoch + 1) % 1000 == 0:
            pbar.update(1000)  # 更新进度条

    # 确保进度条达到100%
    if pbar.n < num_epochs:
        pbar.update(num_epochs - pbar.n)  # 计算剩余的进度并更新

time_all = time.time() - start_time  # 计算训练时间
print(f'Training time: {time_all:.2f} seconds')

# # 可视化损失曲线
# plt.figure(figsize=(10, 6))
# plt.plot(epochs, losses)
# plt.xlabel('Epoch')
# plt.ylabel('Loss')
# plt.title('Training Loss over Epochs')
# plt.grid(True)
# plt.show()
使用设备: cuda:0
训练进度: 100%|██████████| 20000/20000 [00:10<00:00, 1885.37epoch/s, Loss=0.0630]
Training time: 10.61 seconds

三、 模型的推理

之前我们说完了训练模型,那么现在我们来测试模型。测试这个词在大模型领域叫做推理(inference),意味着把数据输入到训练好的模型的过程。

注意损失和优化器在训练阶段

# 在测试集上评估模型,此时model内部已经是训练好的参数了
# 评估模型
model.eval() # 设置模型为评估模式
with torch.no_grad(): # torch.no_grad()的作用是禁用梯度计算,可以提高模型推理速度
    outputs = model(X_test)  # 对测试数据进行前向传播,获得预测结果
    _, predicted = torch.max(outputs, 1) # torch.max(outputs, 1)返回每行的最大值和对应的索引
    # 这个函数返回2个值,分别是最大值和对应索引,参数1是在第1维度(行)上找最大值,_ 是Python的约定,表示忽略这个返回值,所以这个写法是找到每一行最大值的下标
    # 此时outputs是一个tensor,p每一行是一个样本,每一行有3个值,分别是属于3个类别的概率,取最大值的下标就是预测的类别


    # predicted == y_test判断预测值和真实值是否相等,返回一个tensor,1表示相等,0表示不等,然后求和,再除以y_test.size(0)得到准确率
    # 因为这个时候数据是tensor,所以需要用item()方法将tensor转化为Python的标量
    # 之所以不用sklearn的accuracy_score函数,是因为这个函数是在CPU上运行的,需要将数据转移到CPU上,这样会慢一些
    # size(0)获取第0维的长度,即样本数量

    correct = (predicted == y_test).sum().item() # 计算预测正确的样本数
    accuracy = correct / y_test.size(0)
    print(f'测试集准确率: {accuracy * 100:.2f}%')
测试集准确率: 96.67%

模型的评估模式简单来说就是评估阶段会关闭一些训练相关的操作和策略 ,比如更新参数 正则化等操作,确保模型输出结果的稳定性和一致性。

可能有同学好奇,为什么评估模式不关闭梯度计算,推理不是不需要更新参数么?

主要还是因为在某些场景下,评估阶段可能需要计算梯度(虽然不更新参数)。例如计算梯度用于可视化(如 CAM 热力图,主要用于cnn相关)。所以为了避免这种需求不被满足,还是需要手动关闭梯度计算。

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

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

相关文章

目标检测 RT-DETR(2023)详细解读

文章目录 主干网络&#xff1a;Encoder&#xff1a;不确定性最小Query选择Decoder网络&#xff1a; 将DETR扩展到实时场景&#xff0c;提高了模型的检测速度。网络架构分为三部分组成&#xff1a;主干网络、混合编码器、带有辅助预测头的变换器编码器。具体来说&#xff0c;先利…

微信小程序 隐私协议弹窗授权

开发微信小程序的第一步往往是隐私协议授权&#xff0c;尤其是在涉及用户隐私数据时&#xff0c;必须确保用户明确知晓并同意相关隐私政策。我们才可以开发后续的小程序内容。友友们在按照文档开发时可能会遇到一些问题&#xff0c;我把所有的授权方法和可能遇到的问题都整理出…

金众诚业财一体化解决方案如何提升项目盈利能力?

在工程项目管理领域&#xff0c;复杂的全生命周期管理、成本控制的精准性以及业务与财务的高效协同&#xff0c;是决定项目盈利能力的核心要素。随着数字化转型的深入&#xff0c;传统的项目管理方式已难以满足企业对效率、透明度和盈利能力的需求。基于金蝶云星空平台打造的金…

LabVIEW中EtherCAT从站拓扑离线创建及信息查询

该 VI 主要用于演示如何离线创建 EtherCAT 从站拓扑结构&#xff0c;并查询从站相关信息。EtherCAT&#xff08;以太网控制自动化技术&#xff09;是基于以太网的实时工业通信协议&#xff0c;凭借其高速、高效的特性在自动化领域广泛应用。与其他常见工业通讯协议相比&#xf…

Flutter 3.32 新特性

2天前&#xff0c;Flutter发布了最新版本3.32&#xff0c;我们来一起看下29到32有哪些变化。 简介 欢迎来到Flutter 3.32&#xff01;此版本包含了旨在加速开发和增强应用程序的功能。准备好在网络上进行热加载&#xff0c;令人惊叹的原生保真Cupertino&#xff0c;以及与Fir…

windows和mac安装虚拟机-详细教程

简介 虚拟机&#xff1a;Virtual Machine&#xff0c;虚拟化技术的一种&#xff0c;通过软件模拟的、具有完整硬件功能的、运行在一个完全隔离的环境中的计算机。 在学习linux系统的时候&#xff0c;需要安装虚拟机&#xff0c;在虚拟机上来运行操作系统&#xff0c;因为我使…

【C++】vector容器实现

目录 一、vector的成员变量 二、vector手动实现 &#xff08;1&#xff09;构造 &#xff08;2&#xff09;析构 &#xff08;3&#xff09;尾插 &#xff08;4&#xff09;扩容 &#xff08;5&#xff09;[ ]运算符重载 5.1 迭代器的实现&#xff1a; &#xff08;6&…

使用Docker Compose部署Dify

目录 1. 克隆项目代码2. 准备配置文件3. 配置环境变量4. 启动服务5. 验证部署6. 访问服务注意事项 1. 克隆项目代码 首先&#xff0c;克隆Dify项目的1.4.0版本&#xff1a; git clone https://github.com/langgenius/dify.git --branch 1.4.02. 准备配置文件 进入docker目录…

杰发科技AC7840——CSE硬件加密模块使用(1)

1. 简介 2. 功能概述 3. 简单的代码分析 测试第二个代码例程 初始化随机数 这里的CSE_CMD_RND在FuncID中体现了 CSE_SECRET_KEY在17个用户KEY中体现 最后的读取RNG值&#xff0c;可以看出计算结果在PRAM中。 总的来看 和示例说明一样&#xff0c;CSE 初次使用&#xff0c;添加…

前端地图数据格式标准及应用

前端地图数据格式标准及应用 坐标系EPSGgeojson标准格式基于OGC标准的地图服务shapefile文件3D模型数据常见地图框架 坐标系EPSG EPSG&#xff08;European Petroleum Survey Group&#xff09;是一个国际组织&#xff0c;负责维护和管理地理坐标系统和投影系统的标准化编码 E…

threejs几何体BufferGeometry顶点

1. 几何体顶点位置数据和点模型 本章节主要目的是给大家讲解几何体geometry的顶点概念,相对偏底层一些&#xff0c;不过掌握以后&#xff0c;你更容易深入理解Threejs的几何体和模型对象。 缓冲类型几何体BufferGeometry threejs的长方体BoxGeometry、球体SphereGeometry等几…

向量数据库选型实战指南:Milvus架构深度解析与技术对比

导读&#xff1a;随着大语言模型和AI应用的快速普及&#xff0c;传统数据库在处理高维向量数据时面临的性能瓶颈日益凸显。当文档经过嵌入模型处理生成768到1536维的向量后&#xff0c;传统B-Tree索引的检索效率会出现显著下降&#xff0c;而现代应用对毫秒级响应的严苛要求使得…

java方法重写学习笔记

方法重写介绍 子类和父类有两个返回值&#xff0c;参数&#xff0c;名称都一样的方法&#xff0c; 子类的方法会覆盖父类的方法。 调用 public class Overide01 {public static void main(String[] args) {Dog dog new Dog();dog.cry();} }Animal类 public class Animal {…

TensorBoard安装与基本操作指南(PyTorch)

文章目录 什么是TensorBoard&#xff1f;TensorBoardX与TensorBoard的依赖关系易混关系辨析Pytorch安装TensorBoard并验证1. TensorBoard安装和访问2. TensorBoard主要界面介绍实用技巧 什么是TensorBoard&#xff1f; TensorBoard是TensorFlow生态系统中的一款强大的可视化工…

2025/5/25 学习日记 linux进阶命令学习

tree:以树状结构显示目录下的文件和子目录&#xff0c;方便直观查看文件系统结构。 -d&#xff1a;仅显示目录&#xff0c;不显示文件。-L [层数]&#xff1a;限制显示的目录层级&#xff08;如 -L 2 表示显示当前目录下 2 层子目录&#xff09;。-h&#xff1a;以人类可读的格…

【MPC控制 - 从ACC到自动驾驶】4 MPC的“实战演练”:ACC Simulink仿真与结果深度解读

【MPC控制 - 从ACC到自动驾驶】MPC的“实战演练”&#xff1a;ACC Simulink仿真与结果深度解读 在过去的几天里&#xff0c;我们一起&#xff1a; Day 1: 认识了ACC这位聪明的“跟车小能手”和MPC这位“深谋远虑的棋手”。Day 2: 给汽车“画了像”&#xff0c;建立了它的纵向…

OPENEULER搭建私有云存储服务器

一、关闭防火墙和selinux 二、下载相关软件 下载nginx&#xff0c;mariadb、php、nextcloud 下载nextcloud&#xff1a; sudo wget https://download.nextcloud.com/server/releases/nextcloud-30.0.1.zip sudo unzip nextcloud-30.0.1.zip -d /var/www/html/ sudo chown -R…

卷积神经网络(CNN)深度讲解

卷积神经网络&#xff08;CNN&#xff09; 本篇博客参考自大佬的开源书籍&#xff0c;帮助大家从头开始学习卷积神经网络&#xff0c;谢谢各位的支持了&#xff0c;在此期待各位能与我共同进步​ 卷积神经网络&#xff08;CNN&#xff09;是一种特殊的深度学习网络结构&#x…

Docker部署Zookeeper集群

简介 ZooKeeper 是一个开源的分布式协调服务&#xff0c;由 Apache 软件基金会开发和维护。它主要用于管理和协调分布式系统中的多个节点&#xff0c;以解决分布式环境下的常见问题&#xff0c;如配置管理、服务发现、分布式锁等。ZooKeeper 提供了一种可靠的机制&#xff0c;…

数据结构—(概述)

目录 一 数据结构&#xff0c;相关概念 1. 数据结构&#xff1a; 2. 数据(Data): 3. 数据元素(Data Element): 4. 数据项&#xff1a; 5. 数据对象(Data Object): 6. 容器&#xff08;container&#xff09;&#xff1a; 7. 结点&#xff08;Node&#xff09;&#xff…