创新概念:柯尔莫哥洛夫-阿诺德网络

文章目录

  • 一、说明
  • 二、基础概念
  • 三、kolmogorov-Arnold 网络性质
    • 3.1 KAN 的潜在优势
    • 3.2 挑战和注意事项
  • 四、基本 KAN 超参数
  • 五、COLAB 代码
  • 六、注意点

一、说明

kolmogorov-Arnold 网络 (KAN) 是深度学习领域的一项“创新”,它提供了一种受现有 Kolmogorov-Arnold 表示定理启发的构建神经网络的新方法。它们被认为是广泛使用的多层感知器 (MLP) 的潜在替代品,而 MLP 为许多深度学习应用提供了支持。

二、基础概念

虽然 MLP 在节点(“神经元”)上具有固定的激活函数,但 KAN 在边缘(“权重”)上具有可学习的激活函数。KAN 根本没有线性权重——每个权重参数都被参数化为样条函数的单变量函数取代,从而允许在粗粒度和细粒度网格之间切换。

在这里插入图片描述

如果f是有界域上的多元连续函数,则f可以写成单变量连续函数与二元加法运算的有限组合。

在这里插入图片描述
其中 ϕq,p : [0, 1] → R 且 Φq : R → R。对于下一层l,我们有:
在这里插入图片描述
其中 Φ l是第 l个 KAN 层对应的函数矩阵。一般的 KAN 网络是由 L 层组成的:给定一个输入向量x0 ∈ R ,KAN 的输出为
在这里插入图片描述
在数学中,符号“◦”通常用来表示函数组合。

工作原理如下:

  • 假设有两个函数,f(x) 和 g(x)。
  • 函数组合,表示为f ∘ g(读作“f 与 g 组合”),是通过先应用g(x) ,然后取g(x)的输出并将其作为f(x)的输入来创建的一个新函数。
    它将高维函数分解为几个一维函数,得到 α = k+1(其中 k 是样条函数的分段多项式阶)。

分段多项式函数是由其域内不同区间的不同多项式函数定义的函数。它本质上是将较简单的多项式片段拼接在一起以创建更复杂的函数。

从数学上来说,它被写成:

( f ∘ g ) ( x ) = f ( g ( x ) ) (f ∘ g)(x) = f(g(x)) (fg)(x)=f(g(x))

这基本上意味着您对输入值x执行g(x),然后获取结果输出并将其插入f(x)以获得最终答案。
以下是关于函数组合的一些要点:

  • 顺序很重要:(f ∘ g)(x) 通常与 (g ∘ f)(x) 不同,这意味着函数组合是非交换的。
  • 函数组合可以与多个函数链接在一起。例如, (h ∘ f ∘ g)(x) 将首先应用g(x) ,然后将f应用于g的输出,最后将h应用于f的输出。

西虽然 MLP 依赖于在隐藏层内的每个神经元上应用的固定激活函数(如 ReLU 或 sigmoid),但 KAN 采用​​了不同的方法。它们将重点放在神经元之间的连接(边缘)上。它们的区别如下:

  • MLP: MLP 中的激活函数是预定义的非线性函数。它们为网络引入了学习输入数据和期望输出之间复杂关系的基本能力。神经元之间的连接带有简单的权重,这些权重在训练期间会进行调整。
  • KAN: KAN 不会在每个神经元上使用固定的激活函数,而是在边缘本身上使用可学习的激活函数。这些激活函数是使用基函数(如B 样条函数)构建的。将基函数想象成可以组合起来创建更复杂函数的构建块。通过学习这些基函数的系数,KAN 可以在每个连接上实现高度灵活且富有表现力的激活函数。值得注意的是,KAN 完全从网络中移除了传统的线性权重,所有权重参数都被边缘激活函数中的系数所取代。

三、kolmogorov-Arnold 网络性质

3.1 KAN 的潜在优势

  • 提高准确率:与 MLP 的固定激活相比,KAN 中的可学习激活函数有可能捕捉数据中更复杂的关系。这种灵活性可以使模型在特定任务上表现出色,尤其是那些涉及复杂模式的任务。
  • 可解释性增强:与 MLP(黑匣子)的不透明性不同,KAN 提供了一定程度的可解释性。通过分析学习到的基函数系数,研究人员可以深入了解网络如何做出决策。这对于理解模型的内部工作原理并进一步提高其性能非常有价值。这将消除许多采用障碍,尤其是在人工智能监管过度的国家。

3.2 挑战和注意事项

  • 增加训练时间:学习激活函数中基函数系数的过程可能耗费大量计算资源。与 MLP 相比,这意味着 KAN 需要更长的训练时间和更多的 RAM 需求,尤其是对于复杂的网络架构而言。
  • 超参数调整: KAN 引入了与所用基函数的选择和数量相关的新超参数。与调整更简单的 MLP 架构相比,找到这些超参数的最佳配置需要付出更多努力。
    KAN 可能对所有事物都过度拟合:在这个实验中,KAN 将特征中的纯随机数据与提供的标签进行拟合,准确率极高。这很麻烦。
    与 MLP 一样,KAN 具有必须在训练期间进行调整的超参数。以下是 Kolmogorov-Arnold 神经网络中宽度、网格和 k 的细分:

四、基本 KAN 超参数

  • 宽度width

在标准神经网络中,宽度是指隐藏层中神经元的数量。在 KAN 中,该概念类似,但侧重于用于构建每层激活函数的基函数数量。
更广泛的 KAN(更多基础函数)允许更复杂、更具表现力的激活,从而有可能在特定任务上带来更好的性能。
然而,增加宽度也会导致更长的训练时间和潜在的过度拟合。

  • 网格grid

KAN 利用B 样条(或类似技术)来定义激活函数。这些 B 样条是在点网格上构建的。
网格定义了激活函数运行的间隔及其可以捕获的细节级别。
更精细的网格(更多点)可以捕获数据中更精细的细节,但也会增加计算成本和过度拟合。

  • k

此参数与激活函数中使用的B 样条函数的具体类型有关。它决定了B 样条函数的平滑程度。正如你可能猜测的那样,我们也可以把 k 用作正则化工具。
较高的 k 值会导致B 样条曲线更平滑,从而可能提高训练期间的稳定性。
然而,非常高的 k 可能会限制激活函数的灵活性。

  • 关键点:

宽度、网格和 k 都是 KAN 中的超参数,需要进行调整才能在特定任务上获得最佳性能。
在选择这些值时,需要在表达力、训练时间和潜在的过度拟合之间进行权衡。
在 KAN 中,每条边的索引为 ( l,i,j ),其中l 是层索引,i是输入神经元索引,j是输出神经元索引。当我们为每一层、输入和输出神经元创建公式时,您将看到这一点。

五、COLAB 代码

我们从 Colab 开始安装必要的库:

!pip install pykan==0.0.5 -q

数据集可以在kaggle上找到,与信用卡欺诈有关。“该数据集包含欧洲持卡人在 2013 年 9 月通过信用卡进行的交易。该数据集显示两天内发生的交易,在 284,807 笔交易中,有 492 笔是欺诈交易。该数据集非常不平衡,正类(欺诈)占所有交易的 0.172%。

它仅包含数值输入变量,这些变量是 PCA 转换的结果。[…] 特征 V1、V2、…V28 是通过 PCA 获得的主要成分,唯一没有通过 PCA 转换的特征是“时间”和“金额”。特征“时间”包含数据集中每笔交易与第一笔交易之间经过的秒数。特征“金额”是交易金额,此特征可用于基于示例的成本敏感学习。特征“类别”是响应变量,在存在欺诈的情况下取值为 1,否则取值为 0。”

获取 CSV 文件并添加到您的 Google Drive文件夹。然后:

from google.colab import drive
drive.mount('/content/drive')

然后转到 CSV 所在的文件夹:

%cd /content/drive/My Drive/folder/

我们已经准备好开始了:

from kan import KAN
import matplotlib.pyplot as plt
import torch
import numpy as np
import pandas as pd
from scipy import stats## DATASET AT : https://www.kaggle.com/datasets/mlg-ulb/creditcardfrauddf=pd.read_csv('creditcard.csv').reset_index()
df=df.iloc[:,1:]
df.shape

数据形状:(284807, 31)

如果有必要,我们会删除缺失的值。

df=df.dropna().sample(frac=1)
df.shape

对于变量选择,我使用了一个简单的 t 检验,这是一种统计检验,用于比较两组的平均值以确定它们之间是否有显著差异。它可以用来评估连续变量的平均值在分类变量定义的类别之间是否有差异。差异越大越显著,从选择该变量中获得的信息就越多。

# t-test
selected=[]
for i in range(1,df.shape[1]-1):t_stat, p_value = stats.ttest_ind(df[df.Class==0].iloc[:,i], df[df.Class==1].iloc[:,i])if p_value<0.01 and abs(t_stat>19):selected.append(i)

我们选择 3 个变量,V12、V14 和 V17。现在我们准备数据,对其进行混洗并拆分训练/测试。在这里,您可能希望减少示例数量,以避免在下一步 ( model.symbolic_formula() ) 中耗尽计算机 RAM。

from sklearn.model_selection import train_test_splitdataset = {}
X_train, X_test, y_train, y_test = train_test_split(df.iloc[:,select], np.array(df.Class), test_size=0.2, random_state=42, shuffle=True)
dataset['train_input'] = torch.from_numpy(np.array(X_train))
dataset['test_input'] = torch.from_numpy(np.array(X_test))
dataset['train_label'] = torch.from_numpy(np.array(y_train))
dataset['test_label'] = torch.from_numpy(np.array(y_test))X = dataset['train_input']
y = dataset['train_label']

我们定义KAN模型、第一个隐藏层、第二个隐藏层、深度和分段多项式:

model = KAN(width=[3,3], grid=3, k=3) 

在这里插入图片描述
我们还定义了训练和测试准确度的函数:

def train_acc():return torch.mean((torch.argmax(model(dataset['train_input']), dim=1) == dataset['train_label']).float())def test_acc():return torch.mean((torch.argmax(model(dataset['test_input']), dim=1) == dataset['test_label']).float())

然后我们对 KAN 进行 20 个 epoch 的训练。由于我们处理的是分类问题,因此我们将使用 CrossEntropy 作为损失函数。

results = model.train(dataset, opt="Adam", steps=20, metrics=(train_acc, test_acc), loss_fn=torch.nn.CrossEntropyLoss())

在这里插入图片描述
请注意,更重要的权重更加明显,而不太重要的权重则逐渐消失:

model.plot(beta=0.2,scale=1.3,in_vars=[r'$x_{}$'.format(i) for i in range(1,4)])

在这里插入图片描述
让我们提取激活函数的值:l 是层索引,i是输入神经元索引,j是输出神经元索引。

让我们绘制所有的激活函数:

import numpy as np
import matplotlib.pyplot as pltfig, ax = plt.subplots(3, 3, figsize=(6, 6))
l=0# Iterate over all combinations of i, j
for i in range(3):for j in range(3):# Get the appropriate subplotinputs = model.spline_preacts[l][:, j, i]outputs = model.spline_postacts[l][:, j, i]rank = np.argsort(inputs)inputs = inputs[rank]outputs = outputs[rank]# Plot on the appropriate subplotax[i, j].plot(inputs, outputs, marker="o")ax[i, j].set_title(f'l={l}, i={i}, j={j}')# Adjust layout
plt.tight_layout()
plt.show()

在这里插入图片描述
接下来,我们修剪模型并重新训练:

model = model.prune()
model(dataset['train_input'])
results = model.train(dataset, opt="Adam", steps=20, metrics=(train_acc, test_acc), loss_fn=torch.nn.CrossEntropyLoss());
results['train_acc'][-1], results['test_acc'][-1]

在这里插入图片描述

model.plot()

在这里插入图片描述

model.fix_symbolic(0,0,0,'sin') # Symbolification
model.plot(beta=0.2)

在这里插入图片描述

model.unfix_symbolic(0,0,0)
model.plot(beta=0.2)

在这里插入图片描述
现在我们将获得包含这 3 个变量(输入、第 1 层中的变量/激活 B 样条、第 2 层中的变量/激活 B 样条)的所有符号公式:

lib = ['x','x^2','x^3','x^4','exp','log','sqrt','tanh','sin','tan','abs']
model.auto_symbolic(lib=lib)
formula = model.symbolic_formula()[0][0]

在这里插入图片描述

formula1, formula2,formula3 = model.symbolic_formula()[0]
formula1

在这里插入图片描述
正如您所注意到的,我们在这个公式中加入了权重,这使得它具有可解释性,这与 MLP 不同。现在我们来检查一下这个公式的准确性。在下面的代码中,subs是一种逐项用变量值替换公式中的值的方法:

# how accurate is this formula? subs == substitute value in formula by variable value
def acc(formula1, formula2,formula3, X, y):batch = X.shape[0]correct = 0for i in range(batch):logit1 = np.array(formula1.subs('x_1', X[i,0]).subs('x_2', X[i,1]).subs('x_3', X[i,2])).astype(np.float64)logit2 = np.array(formula2.subs('x_1', X[i,0]).subs('x_2', X[i,1]).subs('x_3', X[i,2])).astype(np.float64)logit3 = np.array(formula3.subs('x_1', X[i,0]).subs('x_2', X[i,1]).subs('x_3', X[i,2])).astype(np.float64)correct += (logit3 > logit2 > logit1) == y[i]return correct/batchprint('train acc of the formula:', acc(formula1, formula2,formula3, dataset['train_input'], dataset['train_label']))
print('test acc of the formula:', acc(formula1, formula2,formula3, dataset['test_input'], dataset['test_label']))

在这里插入图片描述
在原文中,每个B 样条函数的公式(或方程)都是按顺序排列的,以确保函数f的正确表示和近似。B样条函数是在特定区间内定义的,并且它们的支撑(非零区域)是有限的。因此,按顺序排列B 样条方程可确保通过将这些基函数以线性组合的形式相加,从而准确地重建函数f在其整个域上的值。

此外,这种有序结构对于近似界限至关重要。该定理依赖于B 样条函数的有序应用,以网格大小G为依据提供近似误差的界限。这种有序应用保持了近似所需的连续性和可微性。

按照这个顺序,我们可以系统地细化网格(从粗到细),同时保持近似过程的准确性和稳定性。这种方法对于确保近似误差随着网格变得更细而减小至关重要,这是基于样条的近似理论的一个关键方面。

logit1 = np.array(formula1.subs('x_1', X[i,0]).subs('x_2', X[i,1]).subs('x_3', X[i,2])).astype(np.float64)
logit2 = np.array(formula2.subs('x_1', X[i,0]).subs('x_2', X[i,1]).subs('x_3', X[i,2])).astype(np.float64)
logit3 = np.array(formula3.subs('x_1', X[i,0]).subs('x_2', X[i,1]).subs('x_3', X[i,2])).astype(np.float64)(logit1>logit2>logit3)

我们将会得到如下结果:

(155.2>143.7>162.5)

在这里插入图片描述

(logit1>logit2>logit3).astype(float)

在这里插入图片描述

六、注意点

H然而,在测试多个超参数和正则化因子设置时,我直觉地认为 KAN 绝对适合一切,甚至是随机数据。所以,我做了一个测试,我使用随机变量作为特征:

df.V12=np.random.random(df.shape[0])
df.V14=np.random.random(df.shape[0])
df.V17=np.random.random(df.shape[0])

输出如下:
在这里插入图片描述
请注意,无论是在训练集还是测试集中,准确率确实非常高。事实上,KAN 能够拟合任何连续函数,包括随机数据,其机制类似于向 MLP 添加不相关变量以提高准确率,但要极端得多。据说,通过适当的正则化、B 样条的平滑度和网络的深度,KAN 找到最佳拟合的机会比 MLP 更高。但这种说法需要实证支持,需要更多的研究。

有趣的是,作者在论文中指出,“柯尔莫哥洛夫-阿诺德表示定理在机器学习中基本上被判了死刑,被认为理论上合理但实际上毫无用处[1][2]”。

请注意,我采取了一种批判性的方法,强调需要对这种过度拟合问题的原因进行更深入的分析。我并不是想贬低 KAN。但在 MLP 中,至少我们有垃圾进垃圾出问题,MLP 不会无差别地适应一切。

根据 [2],柯尔莫哥洛夫定理是一个迷人的数学定理,它告诉我们如何用更简单的函数(仅依赖于一个变量的函数)来表示复杂函数(依赖于多个变量的函数),就像我们之前看到的一样。这对于设计神经网络来说可能非常有用,神经网络本质上是我们用来逼近复杂函数的工具。

然而,早在 1989 年,[2] 就指出柯尔莫哥洛夫定理对于创建实用的神经网络没有帮助,原因如下:

  1. 辅助函数的复杂性:为了使柯尔莫哥洛夫定理奏效,它使用了一些更简单的函数(我们称之为“辅助函数”)。但为了使该定理成立,这些辅助函数往往非常复杂。如果我们希望这些辅助函数平滑(以处理噪音)且易于使用,该定理就无法按预期发挥作用。另一位名叫维图什金的数学家早在 1954 年就证明了这一点。在 KAN 中,这是可调的,我们也有正则化工具。

  2. 辅助函数的特殊性:在实际的神经网络中,我们希望我们的网络具有固定的结构,我们可以对其进行调整以适应不同的问题。在 Kolmogorov 的设置中,我们需要的特定辅助函数实际上取决于我们试图表示的特定函数。这意味着对于每个新问题,我们都需要一组完全不同的辅助函数。嗯,MLP 也存在这个问题,这就是 CNN 存在的原因,也是我们将 MLP 微调到特定领域的原因。

  3. 实践中的复杂性:即使我们可以使用该定理,辅助函数最终也可能与我们试图近似的原始函数一样复杂。这违背了目的,因为我们想要一种更简单的方法来处理和计算这些函数。这一点引起了我的注意,因为 35 年后,KAN 和 MLP 都存在这个问题。我看到到处都是数学体操,试图解决只有认识论颠覆才能解决的问题。

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

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

相关文章

python基础---1.变量、运算符和表达式、基本数据结构

&#x1f388;个人主页&#xff1a;靓仔很忙i &#x1f4bb;B 站主页&#xff1a;&#x1f449;B站&#x1f448; &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 &#x1f917;收录专栏&#xff1a;python &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&…

使用Docker搭建MySql的主从同步+ShardingSphere搭建Mysql的读写分离

参考课程 尚硅谷ShardingSphere5实战教程&#xff08;快速入门掌握核心&#xff09;_哔哩哔哩_bilibili 主服务器 创建容器 docker run -d \ -p 3306:3306 \ -v /kira/mysql/master/conf:/etc/mysql/conf.d \ -v /kira/mysql/master/data:/var/lib/mysql \ -e MYSQL_ROOT…

(day26)leecode热题——找到字符串中所有字母异位词

描述 给定两个字符串 s 和 p&#xff0c;找到 s 中所有 p 的 异位词 的子串&#xff0c;返回这些子串的起始索引。不考虑答案输出的顺序。 异位词 指由相同字母重排列形成的字符串&#xff08;包括相同的字符串&#xff09;。 示例 1: 输入: s "cbaebabacd", p …

【Git-驯化】一文搞懂git中代码冲突的解决方案大全

【Git-驯化】一文搞懂git中代码冲突的解决方案大全 本次修炼方法请往下查看 &#x1f308; 欢迎莅临我的个人主页 &#x1f448;这里是我工作、学习、实践 IT领域、真诚分享 踩坑集合&#xff0c;智慧小天地&#xff01; &#x1f387; 免费获取相关内容文档关注&#xff1a…

[C++实战]日期类的实现

&#x1f496;&#x1f496;&#x1f496;欢迎来到我的博客&#xff0c;我是anmory&#x1f496;&#x1f496;&#x1f496; 又和大家见面了 欢迎来到C探索系列 作为一个程序员你不能不掌握的知识 先来自我推荐一波 个人网站欢迎访问以及捐款 推荐阅读 如何低成本搭建个人网站…

ELK安装(Elasticsearch+Logstash+Kibana+Filebeat)

一、简介 1.1、软件简介 ELK其实是Elasticsearch&#xff0c;Logstash 和 Kibana三个产品的首字母缩写&#xff0c;这三款都是开源产品。 1.1.1、Elasticsearch简介 Elasticsearch 是一个分布式、高扩展、高实时的搜索与数据分析引擎。它能很方便的使大量数据具有搜索、分析…

springboot微信老人健康与饮食管理系统-计算机毕业设计源码82939

基于微信老人健康与饮食管理系统的小程序 摘 要 基于Spring Boot的微信老人健康与饮食管理系统的小程序致力于为老年人提供便捷的健康管理和饮食指导服务。该小程序整合了健康资讯浏览、食谱推荐、健康评估等功能模块&#xff0c;通过系统的设计与实现&#xff0c;旨在帮助老年…

古丝绸之路传闻二:十年败壳精灵显,一介穷神富贵来

古丝绸之路传闻二&#xff1a;十年败壳精灵显&#xff0c;一介穷神富贵来 &#xff08;接上节&#xff1a;古丝绸之路传闻&#xff1a;分内功名匣里财&#xff0c;不关聪慧不关呆&#xff09; 先别说闲话。且说众人带着经纪主人到船上发货&#xff0c;文若虚把之前的事情说了一…

AccessLog| 一款开源的日志分析系统

前言 ClkLog作为分析系列产品中的前端数据分析系统&#xff0c;通过采集前端应用数据进行用户行为分析。其社区版从23年9月发布至今已有近一年&#xff0c;商业版也上线快半年&#xff0c;感谢大家一直以来的关注和支持&#xff0c;ClkLog会继续做好产品升级与服务&#xff0c;…

Linux冯诺依曼体系、操作系统、进程概念、进程状态、进程切换

个人主页&#xff1a;仍有未知等待探索-CSDN博客 专题分栏&#xff1a;Linux 目录 一、冯诺依曼体系结构 二、操作系统 1、概念 2、为什么要有操作系统&#xff1f; 3、理解操作系统 1.管理的本质 2.管理的概念 3.操作系统结构图 4.为什么要有操作系统&#xff1f; 三…

python-NLP:2词性标注与命名实体识别

文章目录 词性标注命名实体识别时间命名实体&#xff08;规则方法&#xff09;CRF 命名实体识别方法 词性标注 词性是词汇基本的语法属性&#xff0c;通常也称为词类。词性标注是在给定句子中判定每个词的语法范畴&#xff0c;确定其词性并加以标注的过程。例如&#xff0c;表示…

Python机器学习实战:分类算法之逻辑回归-泰坦尼克号乘客生还预测

为了解决特定问题而进行的学习是提高效率的最佳途径。这种方法能够使我们专注于最相关的知识和技能&#xff0c;从而更快地掌握解决问题所需的能力。 目录 逻辑回归算法介绍 练习题 Python代码与分析 1、读入数据&#xff0c;观察数据情况 2、各属性与生还情况的关联 3、…

用Python做一个翻译软件,比上浏览器快100倍

简单的用Python来做一个翻译软件 开发环境 Python 3.10 Pycharm模块使用 requests -> pip install requests hashlib tkinter案例分为三部分: 1. 爬虫: 获取翻译接口, 请求获取翻译结果问题1: 接口抓包分析问题2: 请求需要写cookie问题3: 不同文本翻译, s加密参数2. 界面…

PDF解锁网站

https://smallpdf.com/cn/unlock-pdfhttps://smallpdf.com/cn/unlock-pdfhttps://www.freemypdf.comhttps://www.freemypdf.com

【python】python图书管理系统_普通用户+管理员菜单(源码+论文)【独一无二】

&#x1f449;博__主&#x1f448;&#xff1a;米码收割机 &#x1f449;技__能&#x1f448;&#xff1a;C/Python语言 &#x1f449;公众号&#x1f448;&#xff1a;测试开发自动化【获取源码商业合作】 &#x1f449;荣__誉&#x1f448;&#xff1a;阿里云博客专家博主、5…

[代码审计]记一次简单的java代码审计

如果觉得该文章有帮助的&#xff0c;麻烦师傅们可以搜索下微信公众号&#xff1a;良月安全。点个关注&#xff0c;感谢师傅们的支持。 免责声明 本博客所发布的所有内容&#xff0c;包括但不限于信息、工具、项目以及文章&#xff0c;均旨在提供学习与研究之用。所有工具安全…

FastAPI(七十六)实战开发《在线课程学习系统》接口开发-- 课程详情

源码见&#xff1a;"fastapi_study_road-learning_system_online_courses: fastapi框架实战之--在线课程学习系统" 这个接口用户可以不登录&#xff0c;因为我们的课程随意浏览 那么我们梳理下这里的逻辑 1.根据课程id判断课程是否存在 2.课程需要返回课程的详情 3…

C# Task.WaitAll 的用法

目录 简介 1.WaitAll(Task[], Int32, CancellationToken) 2.WaitAll(Task[]) 3.WaitAll(Task[], Int32) 4.WaitAll(Task[], CancellationToken) 5.WaitAll(Task[], TimeSpan) 结束 简介 Task.WaitAll 是 C# 中用于并行编程的一个的方法&#xff0c;它属于 System.Threa…

DjangoRF-5-用户管理-users接口

1、创建模型&#xff0c;user模型之前创建过了&#xff0c;继承了原有的模型类 2、序列化器 在 users/serializers.py 模块中添加&#xff1a; class UserSerializer(serializers.ModelSerializer):class Meta:model Userfields [id, username, password, mobile, email, is…

【简单讲解Perl语言】

&#x1f3a5;博主&#xff1a;程序员不想YY啊 &#x1f4ab;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f917;点赞&#x1f388;收藏⭐再看&#x1f4ab;养成习惯 ✨希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出…