kan代码阅读

目录

工具

torch.linspace(a,b,n)

张量的克隆(复制)

mlp文件夹

导入准备

mlp类

定义to函数

get_act获取激活值

前向传播forward()

@property 装饰器辅助获取权重

torch.einsum语法

爱因斯坦求和约定

示例

点积

矩阵-向量乘法

矩阵乘法

转置和乘法

优点

注意事项

kan文件夹

__init__

kanlayer

class kanlayer

参数解释


工具

torch.linspace(a,b,n)

和np的一样,n(亦作steps)是点的个数

t = torch.linspace(2, 10, 5)
print(t)

输出:tensor([ 2., 4., 6., 8., 10.])

张量的克隆(复制)

torch.clone 和 torch.copy_ 在 PyTorch 中用于创建张量的副本,但它们在用法和目的上有所不同。

  1. torch.clone:

    • 返回一个新的张量,它是输入张量的一个深拷贝。
    • 新张量和原始张量在内存中是独立的,修改新张量不会影响原始张量,反之亦然。
    • 使用方法:new_tensor = original_tensor.clone()
  2. torch.copy_:

    • 将所有数据从源张量复制到目标张量,并原地修改目标张量。
    • 目标张量必须已经存在于内存中,且必须足够大以容纳源张量的数据。
    • 使用方法:destination_tensor.copy_(source_tensor)

下面是两者主要的区别:

  • 调用方式:clone() 是一个独立函数,而 copy_() 是一个原地(in-place)操作。
  • 目标张量:clone() 创建一个新的张量,而 copy_() 需要一个预先存在的目标张量,并在原地修改它。
  • 用途:clone() 常用于需要创建独立副本的场合,而 copy_() 常用于在原地更新张量的场合。

例如:

import torch# 使用 clone
original = torch.tensor([1, 2, 3])
cloned = original.clone()
cloned[0] = 0
print(original)  # 输出: tensor([1, 2, 3])
print(cloned)    # 输出: tensor([0, 2, 3])# 使用 copy_
destination = torch.zeros(3)
destination.copy_(original)
destination[0] = 0
print(original)  # 输出: tensor([1, 2, 3])
print(destination)  # 输出: tensor([0, 2, 3])

在上面的例子中,可以看到 clone() 创建了一个独立的新张量,而 copy_() 则将数据复制到了预先存在的 destination 张量中。

mlp文件夹

导入准备

from tqdm import tqdm
  • 这行代码从tqdm模块导入tqdm函数,它用于在Python循环中添加一个进度条,提供直观的进度显示。

 

from .LBFGS import LBFGS
  • 这行代码从当前目录下的LBFGS模块导入LBFGS类,这通常是一个自定义的优化器类。

 

seed = 0
  • 这行代码设置一个名为seed的变量,值为0,通常用于设置随机数生成器的种子,以确保结果的可重复性。

 

torch.manual_seed(seed)
  • 这行代码将PyTorch的随机数生成器种子设置为seed变量的值,确保每次运行代码时,随机数生成器的结果是一致的。

mlp类

class MLP(nn.Module):
  • 这行代码定义了一个名为MLP的类,它继承自nn.Module。这是创建自定义神经网络模型的标准做法。

 

    def __init__(self, width, act='silu', save_act=True, seed=0, device='cpu'):
  • 这行代码定义了MLP类的构造函数__init__,它接受几个参数:width(网络的宽度,即每层的神经元数量),act(激活函数类型,默认为’silu’),save_act(是否保存激活值,默认为True),seed(随机数种子,默认为0),device(运行设备,默认为’cpu’)。

 

        super(MLP, self).__init__()

所以,这行代码的作用是调用 nn.Module 类的构造函数,这是必要的,因为 MLP 是从 nn.Module 继承而来的,并且需要初始化父类中的属性和方法。在自定义PyTorch模型时,这是一个常见的做法,以确保所有的初始化步骤都被正确执行,例如注册参数和钩子等。

简而言之,super(MLP, self).__init__() 确保了 MLP 类能够继承并使用 nn.Module 类的所有功能和特性。

  • 这行代码调用父类nn.Module的构造函数,这是在自定义PyTorch模块中常见的做法。
  • 更进一步——
  • super(MLP, self):这部分代码是获取当前类 MLP 的父类(在这种情况下是 nn.Module)的引用,self 是当前类的实例。
  • .__init__():这部分代码是调用父类 nn.Module 的构造函数 __init__()

 

        torch.manual_seed(seed)
  • 这行代码再次设置随机数生成器的种子,以确保网络初始化的一致性。

  

        linears = []self.width = widthself.depth = depth = len(width) - 1
  • 这三行代码初始化一个空列表linears用于存储线性层,并将width参数保存为实例变量。同时计算网络深度depth,即width列表的长度减1。

 

        for i in range(depth):linears.append(nn.Linear(width[i], width[i+1]))
  • 这行代码通过循环为网络添加线性层(全连接层),每个线性层的输入和输出尺寸分别由width列表中的连续两个元素指定。

 

        self.linears = nn.ModuleList(linears)
  • linears是由nn.linear()构成的列表
  • 这行代码将包含所有线性层的列表(上一行那个列表)转换为nn.ModuleList,这是PyTorch中用于存储模块列表的一种方式。

 

        self.act_fun = torch.nn.SiLU()
  • 这行代码创建一个SiLU激活函数,它是一种常用的激活函数。

 

        self.save_act = save_actself.acts = None
  • 这两行代码设置一个标志save_act,用于指示是否保存激活值,并初始化一个变量acts用于存储激活值。

 

        self.cache_data = None
  • 这行代码初始化一个变量cache_data,它可能用于存储其他数据,但目前设置为None

 

        self.device = deviceself.to(device)
  • 这两行代码将网络的设备设置为指定的设备(如CPU或GPU),并将网络的所有参数和缓冲区移动到该设备上。

定义to函数

def to(self, device):
  • 定义了一个名为 to 的方法,它接受一个参数 device。这个方法用于将模型的所有参数和缓冲区移动到指定的设备上,这个设备可以是CPU或者GPU。

 

    super(MLP, self).to(device)
  • 使用 super() 调用父类(这里是 nn.Module)的 to 方法,并将当前实例 self 和 device 参数传递给它。这行代码的作用是将当前模型(MLP 的实例)的所有参数和缓冲区移动到指定的 device 上。

 

    self.device = device
  • 这行代码将 device 参数的值赋给实例变量 self.device。这样做是为了在后续的操作中可以引用这个设备,比如在模型的其他方法中使用这个设备来创建或操作张量。

 

    return self
  • 这行代码返回了 self,即当前模型的实例。这使得 to 方法可以被链式调用,也就是说,你可以像这样连续调用方法:model.to(device).train()

 

这段代码总体上是为了确保模型可以在不同的设备之间移动,并保持对当前设备引用的跟踪。这在处理多设备环境时非常有用,尤其是在使用GPU进行训练时。

get_act获取激活值

   def get_act(self, x=None):
3 months agoadd swap methodif isinstance(x, dict):x = x['train_input']if x == None:if self.cache_data != None:x = self.cache_dataelse:raise Exception("missing input data x")save_act = self.save_actself.save_act = Trueself.forward(x)self.save_act = save_act
def get_act(self, x=None):
  • 定义了一个名为 get_act 的方法,它接受一个可选参数 x。这个方法可能是用来获取神经网络在给定输入 x 下的激活值。

 

    if isinstance(x, dict):x = x['train_input']
  • 这行代码检查参数 x 是否是一个字典。如果是,它将 x 的值更新为 x 字典中键为 'train_input' 的值。这意味着如果输入是一个字典,它期望字典中包含一个键为 'train_input' 的条目,该条目是网络的实际输入。

    if x == None:if self.cache_data != None:x = self.cache_dataelse:raise Exception("missing input data x")
  • 这是一个条件判断,如果 x 是 None,它将检查 self.cache_data 是否不为 None。如果 self.cache_data 存在,则将 x 设置为 self.cache_data 的值。如果 self.cache_data 也是 None,则抛出一个异常,指出缺少输入数据 x

 

    save_act = self.save_act
  • 这行代码将 self.save_act 的当前值保存到局部变量 save_act 中。self.save_act 可能是一个布尔值,指示是否应该保存激活值。

 

    self.save_act = True
  • 这行代码将 self.save_act 设置为 True,确保在接下来的 forward 调用中保存激活值。

python

复制

    self.forward(x)
  • 调用 self.forward 方法,这通常是神经网络的前向传播方法,它使用输入 x 计算网络的输出。由于前面设置了 self.save_act 为 True这个过程也会保存激活值。

 

    self.save_act = save_act
  • 这行代码将 self.save_act 的值恢复为最初保存的值,即 save_act 变量的值。这样,get_act 方法结束后,self.save_act 的值不会被永久改变。

整体上,这个方法是为了获取给定输入 x 的网络激活值,并且可以选择性地使用缓存的数据。如果输入数据缺失,它会抛出一个异常。这个方法还确保了在获取激活值之后,self.save_act 的值会被恢复到原来的状态。

前向传播forward()

如果只是要求传播完的x,只要两句话就好了

def forward(self,x):for i in range(self.depth):x=self.linears[i](x)return x

但是,还有很多细节要考虑,比如是否保存激活值:

if self.save_act:act = x.clone()act_scale = torch.std(x, dim=0)wa_forward = act_scale[None, :] * self.linears[i].weightself.acts.append(act)if i > 0:self.acts_scale.append(act_scale)self.wa_forward.append(wa_forward)
  • 如果 self.save_act 为 True,则克隆当前激活值 x,计算其标准差 act_scale,计算权重与激活值尺度的乘积 wa_forward,并将这些值添加到相应的列表中。
  • 具体算法————

    表达式 wa_forward = act_scale[None, :] * self.linears[i].weight 是在PyTorch中常见的一种操作,用于在神经网络的前向传播过程中对权重进行调整。这里,act_scale 是一个张量,表示每个特征维度的标准差,而 self.linears[i].weight 是第 i 个线性层的权重。下面解释这个表达式的各个部分:

  • act_scale[None, :]

    • act_scale 是一个一维张量,假设它的形状是 (C,),其中 C 是特征的数量。
    • [None, :] 是一个索引操作,它将 act_scale 增加一个维度,使其形状变为 (1, C)。这样做的目的是为了确保在进行广播操作时,act_scale 可以与 self.linears[i].weight 的形状兼容。
  • self.linears[i].weight

    • self.linears[i] 是一个线性层(例如 nn.Linear),而 .weight 是这个线性层的权重张量。
    • 假设这个线性层的输入特征数量是 C,输出特征数量是 D,那么 self.linears[i].weight 的形状是 (D, C)
  • *

    • 这是逐元素乘法操作。在这里,它将形状为 (1, C) 的 act_scale[None, :] 与形状为 (D, C) 的 self.linears[i].weight 进行逐元素相乘。
  • 结果 wa_forward

    • 结果的形状将是 (D, C),与 self.linears[i].weight 的形状相同。
    • 这个操作的效果是调整第 i 个线性层的权重,使得每个输出特征维度的权重都乘以相应的特征标准差 act_scale

 总括——

  • 如果 self.save_act 为 True,则克隆当前激活值 x,计算其标准差 act_scale,计算权重与激活值尺度的乘积 wa_forward,并将这些值添加到相应的列表中。
  • 如果当前层不是最后一层(i < self.depth - 1),则应用激活函数 self.act_fun 到输出 x 上。这意味着在每一层线性层之后(除了最后一层),都会进行激活。
  • 如果当前层是最后一层,并且 self.save_act 为 True,则计算最后一层激活值的标准差 act_scale 并保存。
  • 每经过一层线性层(除了最后一层)都会激活一次。这是深度学习中常见的模式,其中非线性激活函数被用于引入非线性,使得模型能够学习更复杂的函数。最后一层通常不使用激活函数,特别是在回归问题或某些特定的分类问题中,例如输出层的维度与目标维度相同的情况。
    

@property 装饰器辅助获取权重

在Python中,@property 装饰器用于将一个方法转换为属性访问,这样就可以像访问属性一样访问这个方法,而不需要使用传统的函数调用方式(即不带括号)。这在实现面向对象编程时非常有用,特别是在需要通过属性访问来获取或设置对象状态时。

 @property 装饰器用于 w 方法:

 

@property
def w(self):return [self.linears[l].weight for l in range(self.depth)]

以下是 @property 装饰器的作用:

  1. 属性访问:允许用户通过 self.w 而不是 self.w() 来访问权重列表,这使得代码更加简洁和直观。

  2. 只读属性:在这个例子中,w 方法没有定义一个设置器(setter),这意味着它是一个只读属性。用户可以获取权重列表,但不能直接修改它。

  3. 隐藏实现细节:通过将方法转换为属性,可以在不公开内部实现细节的情况下,提供对对象状态的访问。在这个例子中,用户不需要知道权重是如何被组织或计算的,他们只需要知道可以通过 self.w 获取它们。

下面是如何使用这个属性的一个例子:

 

# 假设有一个 MLP 实例叫做 mlp
weights = mlp.w  # 获取所有层的权重,不需要调用 mlp.w() 作为函数

在这个例子中,每次你访问 mlp.w,它都会返回一个列表,其中包含了 mlp 对象中所有线性层的权重。由于 w 是一个只读属性,你不能通过赋值来改变它,例如 mlp.w = something 是不允许的,除非你定义了一个相应的设置器方法。

1暂时还没看到在哪里用了

torch.einsum语法

torch.einsum 是PyTorch中一个强大的函数,它允许用户使用爱因斯坦求和约定(Einstein summation convention)来执行多维数组(张量)的运算。爱因斯坦求和约定是一种表示多维数组(张量)运算的方法,它通过省略求和符号和索引来简化数学表达式的书写。

下面是对 torch.einsum 函数的具体讲解:

 

torch.einsum(equation, *operands)
  • equation: 一个字符串,定义了操作的形式,包括输入和输出张量的索引以及它们之间的关系。
  • operands: 一个或多个张量,它们将根据 equation 中定义的规则进行运算。

爱因斯坦求和约定

在爱因斯坦求和约定中,如果一个索引在输入张量中出现两次,那么它就表示对该索引进行求和。如果索引在输出张量中出现,那么它就表示该索引是输出张量的一个维度。

示例

以下是一些使用 torch.einsum 的示例:

点积

计算两个一维张量的点积:

 

x = torch.randn(5)
y = torch.randn(5)
result = torch.einsum('i,i', x, y)  # 等价于 torch.dot(x, y)

在这个例子中,‘i,i’ 表示对索引 i 求和,x 和 y 的对应元素相乘。

矩阵-向量乘法

计算矩阵和向量的乘积:

 

A = torch.randn(4, 5)
x = torch.randn(5)
result = torch.einsum('ik,k', A, x)  # 等价于 torch.mv(A, x)

这里,‘ik,k’ 表示对索引 k 求和,A 的每一行与 x 相乘。

矩阵乘法

计算两个矩阵的乘积:

 

A = torch.randn(4, 5)
B = torch.randn(5, 6)
result = torch.einsum('ik,kj', A, B)  # 等价于 torch.mm(A, B)

在这个例子中,‘ik,kj’ 表示对索引 k 求和,A 的行与 B 的列相乘。

转置和乘法

计算矩阵的转置与另一个矩阵的乘积:

 

A = torch.randn(4, 5)
B = torch.randn(4, 6)
result = torch.einsum('ji,jk', A, B)  # 等价于 torch.mm(A.t(), B)

这里,‘ji,jk’ 表示 A 被转置(通过交换索引 i 和 j),然后与 B 相乘。

优点

  • 表达能力强:可以简洁地表示复杂的多维数组运算。
  • 性能优化:torch.einsum 在某些情况下可以比传统的矩阵乘法函数(如 torch.mm 或 torch.matmul)更高效,因为它允许PyTorch优化器选择最佳的执行路径。

注意事项

  • 使用 torch.einsum 时,需要确保输入张量的维度与求和约定中的索引相匹配。
  • 对于非常大的张量,使用 torch.einsum 可能不如直接使用专门的函数(如 torch.mm 或 torch.matmul)高效,因为后者通常经过了更深入的优化。

91行

kan文件夹

__init__

在Python中,`__init__.py` 文件是用于标识一个目录为Python包(package)的特殊文件。在这个图片中,虽然“__init__.py”这个名称出现在列表中,但通常它不会以这种方式显示为一个普通文件。相反,它会作为包内部的一个隐藏或特殊的文件存在。
如果你希望创建一个新的Python包,你应该在你的包目录下创建一个空的 `__init__.py` 文件。这样,Python就会把这个目录识别为一个可以导入的包。
 

只有三行

from .MultKAN import *
from .utils import *
#torch.use_deterministic_algorithms(True)

这个文件可以非常简单,甚至可以为空,只要它的文件名恰好是 __init__.py 即可。然而,你也可以在其中放置一些特定的代码和行为,这些代码会在导入该包时自动执行。

kanlayer

class kanlayer

参数解释

in_dim: int
    输入维度
out_dim: int
    输出维度
num: int
    网格间隔的数量
k: int
    样条函数的分段多项式阶数
noise_scale: float
    初始化时样条函数的尺度
coef: 2D torch.tensor
    B样条基的系数
scale_base_mu: float
    残差函数 b(x) 从 N(μ, σ^2) 中抽取的量级,(magnitude),μ = sigma_base_mu
scale_base_sigma: float
    残差函数 b(x) 从 N(μ, σ^2) 中抽取的量级,μ = sigma_base_sigma
scale_sp: float
    样条函数 spline(x) 的量级
base_fun: fun
    残差函数 b(x)
mask: 1D torch.float
    样条函数的掩码。将掩码中的某些元素设置为零意味着将相应的激活函数设置为零。
grid_eps: float ∈ [0,1]
    在 update_grid_from_samples 中使用的超参数。当 grid_eps = 1 时,网格是均匀的;当 grid_eps = 0 时,网格使用样本的百分位数进行划分。0 < grid_eps < 1 在两个极端之间插值。
    锁定的激活函数的ID
device: str
    设备
 

下棋待续。

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

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

相关文章

了解 WebSocket

了解 WebSocket 轮询方式、短轮询长轮询SSE WebSocket为什么说 WebSocket 是基于 Http 协议的&#xff1f;如何通过 Sec-WebSocket-Key 与 验证 Sec-WebSocket-Accept验证 demo SpringBoot 中使用 WebSocket引入依赖增加 WebSocketConfig修改 ServerEndpointConfig定义 ServerE…

保研考研机试攻略:python笔记(1)

&#x1f428;&#x1f428;&#x1f428;宝子们好呀 ~ 我来更新欠大家的python笔记了&#xff0c;从这一篇开始我们来学下python&#xff0c;当然&#xff0c;如果只是想应对机试并且应试语言以C和C为主&#xff0c;那么大家对python了解一点就好&#xff0c;重点可以看高分篇…

易基因:Nat Commun:ATAC-seq等揭示恒河猴大脑高分辨率解剖区域的转录组和开放染色质图谱

大家好&#xff0c;这里是专注表观组学十余年&#xff0c;领跑多组学科研服务的易基因。 恒河猴是神经科学研究中常用的模型动物&#xff0c;其大脑结构和功能与人类大脑相似。大脑中复杂的遗传网络是灵长类动物行为、认知和情感的基础&#xff0c;一直是神经科学的核心。大脑…

禾川SV-X2E A伺服驱动器参数设置——脉冲型

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家&#xff01;人工智能学习网站 前言&#xff1a; 大家好&#xff0c;我是上位机马工&#xff0c;硕士毕业4年年入40万&#xff0c;目前在一家自动化公司担任…

【Android】基础回顾--四大组件

1. 四大组件是什么&#xff1f; 四大组件&#xff1a;Activity、Service、BroadcastReceiver、ContentProvider。 2. 四大组件的生命周期和简单用法 Activity&#xff1a; 特殊情况下的生命周期&#xff1a; 典型的生命周期好像没什么可说的&#xff0c;主要说一下特殊情况…

基于Datawhale开源量化投资学习指南(11):LightGBM在量化选股中的优化与实战

1. 概述 在前几篇文章中&#xff0c;我们初步探讨了如何通过LightGBM模型进行量化选股&#xff0c;并进行了一些简单的特征工程和模型训练。在这一篇文章中&#xff0c;我们将进一步深入&#xff0c;通过优化超参数和实现交叉验证来提高模型的效果&#xff0c;并最终通过回测分…

C++ | Leetcode C++题解之第516题最长回文子序列

题目&#xff1a; 题解&#xff1a; class Solution { public:int longestPalindromeSubseq(string s) {int n s.length();vector<vector<int>> dp(n, vector<int>(n));for (int i n - 1; i > 0; i--) {dp[i][i] 1;char c1 s[i];for (int j i 1; j…

2-135 基于matlab的有限差分法计算电位分布

基于matlab的有限差分法计算电位分布&#xff0c;设置目标尺寸的矩形区域&#xff0c;设置矩形区域内的网格数量&#xff0c;根据网格位置在区域内设置电位&#xff0c;实现电位分布计算。程序已调通&#xff0c;可直接运行。 下载源程序请点链接&#xff1a;2-135 基于matlab…

微信小程序的日期区间选择组件的封装和使用

组件化开发是一种将大型软件系统分解为更小、更易于管理和复用的独立模块或组件的方法。这种方法在现代软件开发中越来越受到重视&#xff0c;尤其是在前端开发领域。微信小程序的日期区间选择组件的使用 wxml 代码 <view><view bind:tap"chooseData">…

【Redis】内存淘汰策略

文章目录 什么是内存淘汰策略设置Redis最大内存执行内存淘汰策略的流程Redis的八大内存淘汰策略深入源码进行理解内存淘汰策略流程 什么是内存淘汰策略 Redis内存淘汰策略是指当Redis的内存使用达到其配置的最大内存限制&#xff08;maxmemory&#xff09;时&#xff0c;Redis…

论文笔记(五十)Segmentation-driven 6D Object Pose Estimation

Segmentation-driven 6D Object Pose Estimation 文章概括摘要1. 引言2. 相关工作3. 方法3.1 网络架构3.2 分割流3.3 回归流3.4 推理策略 4. 实验4.1 评估 Occluded-LINEMOD4.1.1 与最先进技术的比较4.1.2 不同融合策略的比较4.1.3 与人体姿态方法的比较 4.2 在YCB-Video上的评…

uniapp使用easyinput文本框显示输入的字数和限制的字数

uniapp使用easyinput文本框显示输入的字数和限制的字数 先上效果图&#xff1a; 整体代码如下&#xff1a; <template><view class"nameInfoContent"><uni-easyinput class"uni-mt-5" suffixIcon"checkmarkempty" v-model&quo…

【MyBatis源码】SqlSessionFactoryBuilder源码分析

文章目录 概述类结构从 InputStream 创建 SqlSessionFactoryXMLConfigBuilder构建ConfigurationXMLConfigBuilder初始化方法parse()方法parseConfiguration属性&#xff08;properties&#xff09; 概述 SqlSessionFactory 是 MyBatis 的核心接口之一&#xff0c;提供创建 Sql…

vue通过JSON文件生成WPML文件源码

可以使用封装的json解析器进行JSON数据获取&#xff0c;读取点的经度、维度、高程等数据&#xff0c;再使用对应的WPML文件生成函数使用该源码下载WPML文件&#xff08;固定WPML生成&#xff1a;js模板式生成大疆上云wpml文件&#xff08;含详细注释&#xff0c;已封装成函数&a…

(7) cuda异常处理

文章目录 上节概要异常处理代码 上节概要 上一节 block_width 64的时候&#xff0c;64644096 > 1024&#xff08;一个block里面最多只能有1024个线程&#xff0c;所以这里计算会有问题&#xff09; 异常处理 __FILE__: 编译器内部定义的一个宏。表示的是当前文件的文件…

【C++单调栈 贡献法】907. 子数组的最小值之和|1975

本文涉及的基础知识点 C单调栈 LeetCode907. 子数组的最小值之和 给定一个整数数组 arr&#xff0c;找到 min(b) 的总和&#xff0c;其中 b 的范围为 arr 的每个&#xff08;连续&#xff09;子数组。 由于答案可能很大&#xff0c;因此 返回答案模 109 7 。 示例 1&#x…

项目:Boost 搜索引擎

项目&#xff1a;Boost 搜索引擎 1、项目背景 公司&#xff1a;百度、360、搜狗、谷歌 …站内搜索&#xff1a;搜索的数据更垂直&#xff08;相关&#xff09;&#xff0c;数据量小 2、整体框架 3、技术栈和项目环境 技术栈&#xff1a;C/C C11&#xff0c;STL&#xff0c;jso…

error Unexpected mutation of “xxxxx“ prop

错误是在进行 eslint 检查的时候触发的&#xff0c;这个错误的原因是我们在子组件中改变了父组件传递过来的 props 解决方法一&#xff1a; 不改变父组件传递过来的 props&#xff0c;如果需要改变父组件传递过来的值&#xff0c;可以使用 defineModel() 进行接收值&#xff…

【零售和消费品&软件包】快递包装类型检测系统源码&数据集全套:改进yolo11-HSPAN

改进yolo11-EfficientHead等200全套创新点大全&#xff1a;快递包装类型检测系统源码&#xff06;数据集全套 1.图片效果展示 项目来源 人工智能促进会 2024.10.24 注意&#xff1a;由于项目一直在更新迭代&#xff0c;上面“1.图片效果展示”和“2.视频效果展示”展示的系统…

STM32第15章 RCC-使用HSE/HSI配置时钟

时间:2024.10.21-10.23 参考资料: 《零死角玩转STM32》“RCC-使用HSE/HIS配置时钟”章节 TIPS: 从前面的历程中我们知道,程序在启动的时候会执行汇编文件,汇编文件里会调用System_Init(固件库编程的函数),它里面会把时钟初始化成72M,因此前面我们在用固件库写程序的…