深度学习 Pytorch 张量的线性代数运算

news2025/1/20 6:57:31

pytorch中并未设置单独的矩阵对象类型,因此pytorch中,二维张量就相当于矩阵对象,并且拥有一系列线性代数相关函数和方法。

在实际机器学习和深度学习建模过程中,矩阵或者高维张量都是基本对象类型,而矩阵所涉及到的线性代数理论也是深度学习用户必备的基本数学基础。

import torch
import numpy as np

16 矩阵的形变及特殊矩阵构造方法

矩阵的形变方法其实也就是二维张量的形变方法,再此基础上补充转置的基本方法。

另外,在实际线性代数运算过程中,经常涉及一些特殊矩阵,如单位矩阵、对角矩阵等。


Tensor矩阵运算

函数描述
torch.t(t)t转置
torch.eye(n)创建包含n个分量的单位矩阵
torch.diag(t)以t中各元素,创建对角矩阵
torch.triu(t)取矩阵t中的上三角矩阵
torch.tril(t)取矩阵t中的下三角矩阵
# 创建一个2*3的矩阵
t1 = torch.arange(1, 7).reshape(2, 3).float()
t1
# output :
tensor([[1., 2., 3.],
        [4., 5., 6.]])
# 转置
torch.t(t1)
# output :
tensor([[1., 4.],
        [2., 5.],
        [3., 6.]])
# 也可以调用方法
t1.t()
# output :
tensor([[1., 4.],
        [2., 5.],
        [3., 6.]])

矩阵的转置就是每个元素行列位置互换。


# 创建单位阵
torch.eye(3)
# output :
tensor([[1., 0., 0.],
        [0., 1., 0.],
        [0., 0., 1.]])

# 创建对角矩阵
t = torch.arange(1,6)
torch.diag(t)
# output :
tensor([[1, 0, 0, 0, 0],
        [0, 2, 0, 0, 0],
        [0, 0, 3, 0, 0],
        [0, 0, 0, 4, 0],
        [0, 0, 0, 0, 5]])
# 对角线向右上偏移一位
torch.diag(t, 1)
# output :
tensor([[0, 1, 0, 0, 0, 0],
        [0, 0, 2, 0, 0, 0],
        [0, 0, 0, 3, 0, 0],
        [0, 0, 0, 0, 4, 0],
        [0, 0, 0, 0, 0, 5],
        [0, 0, 0, 0, 0, 0]])
# 注意偏移后依然是一个方阵,从五行五列变成了六行六列
# 对角线向右上偏移一位
torch.diag(t, -1)
# output :
tensor([[0, 0, 0, 0, 0, 0],
        [1, 0, 0, 0, 0, 0],
        [0, 2, 0, 0, 0, 0],
        [0, 0, 3, 0, 0, 0],
        [0, 0, 0, 4, 0, 0],
        [0, 0, 0, 0, 5, 0]])

t1 = torch.arange(1, 9).reshape(3, 3)
t1
# output :
tensor([[1, 2, 3],
        [4, 5, 6],
        [7, 8, 9]])
# 取上三角矩阵
torch.triu(t1)
# output :
tensor([[1, 2, 3],
        [0, 5, 6],
        [0, 0, 9]])
# 上三角矩阵向左下偏移一位
torch.triu(t1, -1)
# output :
tensor([[1, 2, 3],
        [4, 5, 6],
        [0, 8, 9]])
# 上三角矩阵向右上偏移一位
torch.triu(t1, 1)
# output :
tensor([[0, 2, 3],
        [0, 0, 6],
        [0, 0, 0]])
# 下三角矩阵
torch.tril(t1)
# output :
tensor([[1, 0, 0],
        [4, 5, 0],
        [7, 8, 9]])

17 矩阵的基本运算

矩阵不同于普通的二维数组,其具备一定的线性代数含义。

而这些特殊的性质,其实就主要体现在矩阵的基本运算上。


矩阵的基本运算

函数描述
torch.dot(t1, t2)计算t1, t2张量内积
torch.mm(t1, t2)矩阵乘法
torch.mv(t1, t2)矩阵乘向量
torch.bmm(t1, t2)批量矩阵乘法
torch.addmm(t, t1, t2)矩阵相乘后相加
torch.addbmm(t, t1, t2)批量矩阵相乘后相加

dot/vdot:点积计算

注意: dotvdot 只能作用于一维张量 ,且对于数值型对象,二者计算结果并没有区别,两种函数只在进行复数计算时会有区别。

t = torch.arange(1, 4)
t
# output :
tensor([1, 2, 3])
torch.dot(t, t)
# output :
tensor(14)
torch.vdot(t, t)
# output :
tensor(14)
# 不能进行除了一维张量以外的计算
t1 = torch.arange(1, 9).reshape(3, 3)
torch.dot(t1, t1)
# output :
RuntimeError: shape '[3, 3]' is invalid for input of size 8

mm:矩阵乘法

t1 = torch.arange(1, 7).reshape(2, 3)
t2 = torch.arange(1, 10).reshape(3, 3)
# 对应元素相乘
t1*t1
# output :
tensor([[ 1,  4,  9],
        [16, 25, 36]])
# 矩阵乘法
torch.mm(t1, t2)
# output :
tensor([[30, 36, 42],
        [66, 81, 96]])

矩阵乘法执行过程如下所示:

在这里插入图片描述


mv:矩阵和向量相乘

矩阵和向量相乘可以看作是先将向量转化为列向量然后再相乘。

在实际执行向量和矩阵相乘的过程中,需要矩阵的列数和向量的元素个数相同。

met = torch.arange(1, 7).reshape(2, 3)
met
# output :
tensor([[1, 2, 3],
        [4, 5, 6]])
vec = torch.arange(1, 4)
vec
# output :
tensor([1, 2, 3])
torch.mv(met, vec)
# output :
tensor([14, 32])

bmm:批量矩阵相乘

批量矩阵相乘指的是三维张量的矩阵乘法。

例如,一个(3,2,2)的张量,本质上就是一个包含了3个2*2矩阵的张量。而三维张力的矩阵相乘,则是三维张量内部各对应位置的矩阵相乘。

注意:

  • 三维张量包含的矩阵个数需要相同
  • 每个内部矩阵,需要满足矩阵乘法的条件,也就是左乘矩阵的行数要等于右乘矩阵的列数
t3 = torch.arange(1, 13).reshape(3, 2, 2)
t3
# output :
tensor([[[ 1,  2],
         [ 3,  4]],

        [[ 5,  6],
         [ 7,  8]],

        [[ 9, 10],
         [11, 12]]])
t4 = torch.arange(1, 19).reshape(3, 2, 3)
t4
# output :
tensor([[[ 1,  2,  3],
         [ 4,  5,  6]],

        [[ 7,  8,  9],
         [10, 11, 12]],

        [[13, 14, 15],
         [16, 17, 18]]])
torch.bmm(t3, t4)
# output :
tensor([[[  9,  12,  15],
         [ 19,  26,  33]],

        [[ 95, 106, 117],
         [129, 144, 159]],

        [[277, 296, 315],
         [335, 358, 381]]])

addmm:矩阵相乘后相加

addmm函数结构:addmm(input, mat 1 , mat 2 , beta = 1, alpha = 1)

输出结果:beta * input + alpha * (mat 1 * mat 2)

t1
# output :
tensor([[1, 2, 3],
        [4, 5, 6]])

t2
# output :
tensor([[1, 2, 3],
        [4, 5, 6],
        [7, 8, 9]])

t = torch.arange(3)
t
# output :
tensor([0, 1, 2])
torch.mm(t1, t2)
# output :
tensor([[30, 36, 42],
        [66, 81, 96]])
torch.addmm(t, t1, t2)
# output :
tensor([[30, 37, 44],
        [66, 82, 98]])
torch.addmm(t, t1, t2, beta = 0, alpha = 10)
# output :
tensor([[300, 360, 420],
        [660, 810, 960]])

addbmm:批量矩阵相乘后相加

addmm类似,都是先乘后加,并且可以设置权重。不同的是addbmm是批量矩阵相乘,并且,再相乘的过程中而是矩阵相加,而非向量加矩阵。

t = torch.arange(6).reshape(2, 3)
t
# output :
tensor([[0, 1, 2],
        [3, 4, 5]])

t3
# output :
tensor([[[ 1,  2],
         [ 3,  4]],

        [[ 5,  6],
         [ 7,  8]],

        [[ 9, 10],
         [11, 12]]])

t4
# output :
tensor([[[ 1,  2,  3],
         [ 4,  5,  6]],

        [[ 7,  8,  9],
         [10, 11, 12]],

        [[13, 14, 15],
         [16, 17, 18]]])
torch.bmm(t3, t4)
# output :
tensor([[[  9,  12,  15],
         [ 19,  26,  33]],

        [[ 95, 106, 117],
         [129, 144, 159]],

        [[277, 296, 315],
         [335, 358, 381]]])
torch.addbmm(t, t3, t4)
# output :
tensor([[381, 415, 449],
        [486, 532, 578]])

注: addbmm会在原来三维张量基础之上,对其内部矩阵进行求和。


18 矩阵的线性代数运算

如果说矩阵的基本运算是矩阵基本性质,那么矩阵的线性代数运算,则是外面利用矩阵数据类型在求解实际问题过程中经常涉及到的线性代数方法。


矩阵的线性代数运算

函数描述
torch.trace(A)矩阵的迹
torch.linalg.matrix_rank(A)矩阵的秩
torch.det(A)计算矩阵A的行列式
torch.inverse(A)矩阵求逆
torch.lstsq(A, B)最小二乘法

矩阵的迹(trace)

就是求矩阵对角线之和

A = torch.tensor([[1, 2], [4, 5]]).float()
A
# output :
tensor([[1., 2.],
        [4., 5.]])
torch.trace(A)
# output :
tensor(6.)

当然,计算过程不需要是方阵

B = torch.arange(1, 7).reshape(2, 3)
B
# output :
tensor(6)

矩阵的秩(rank)

矩阵的秩是指矩阵中行或列的极大线性无关组,且矩阵中行、列极大无关数总是相同的,任何矩阵的秩都是唯一值。

满秩指的是方阵(行数和列数相同的矩阵)中行数、列数和秩相同,满秩矩阵有线性唯一解等重要特性,而其他矩阵也能通过求解秩来降维。

同时,秩也是奇异值分解等运算中涉及到的重要概念。

注: 秩的计算要求浮点型张量

A = torch.arange(1, 5).reshape(2, 2).float()
A
# output :
tensor([[1., 2.],
        [3., 4.]])
torch.torch.linalg.matrix_rank(A)
# output :
tensor(2)

对于矩阵B来说,第一列和第二列明显线性相关,最大线性无关组只有1组,因此矩阵的秩结果为1。

B = torch.tensor([[1, 2], [2, 4]]).float()
B
# output :
tensor([[1., 2.],
        [2., 4.]])
torch.torch.linalg.matrix_rank(B)
# output :
tensor(1)

矩阵的行列式(det)

我们可以将行列式简单理解为矩阵的一个基本性质或属性。通过行列式的计算,我们能够知道矩阵是否可逆,从而可以进一步求解矩阵所对应的线性方程。

更加专业的解释,行列式作为一个基本数学工具,实际上就是矩阵进行线性变换的伸缩因子。

对于任何一个n维方阵,行列式计算过程如下
D = ∣ a 11 a 12 … a 1 n a 21 a 22 … a 2 n ⋮ ⋮ ⋱ ⋮ a n 1 a n 2 … a n n ∣ D = \left| \begin{array}{cccc} a_{11} & a_{12} & \ldots & a_{1n} \\ a_{21} & a_{22} & \ldots & a_{2n} \\ \vdots & \vdots & \ddots & \vdots \\ a_{n1} & a_{n2} & \ldots & a_{nn} \\ \end{array} \right| D= a11a21an1a12a22an2a1na2nann

D = ∑ ( − 1 ) k a 1 k 1 a 2 k 2 … a n k n D = \sum (-1)^k a_{1k_1} a_{2k_2} \ldots a_{nk_n} D=(1)ka1k1a2k2ankn

更为简单的情况,如果对于一个2*2的矩阵,行列式的计算就是主对角线元素之积减去另外两个元素之积。

A = torch.tensor([[1, 2], [4, 5]]).float()
A
# output :
tensor([[1., 2.],
        [4., 5.]])
torch.det(A)
# output :
tensor(-3.)

A的行列式计算过程如下

在这里插入图片描述

对于行列式的计算,要求二维张量必须是方阵,也就是行列数必须一致。

B = torch.arange(1, 7).reshape(2, 3)
B
# output :
tensor([[1, 2, 3],
        [4, 5, 6]])
torch.det(B)
# output :
RuntimeError: linalg.det: A must be batches of square matrices, but they are 2 by 3 matrices

19 线性方程组的矩阵表达式

在正式进入到更进一步矩阵运算的讨论之前,我们需要对矩阵建立一个更加形象化的理解。

通常来说,我们会把高维空间中的一个个数看成是向量,而由这些向量组成的数组看成是一个矩阵。

例如:(1,2)(3,4)是二维空间中的两个点,矩阵A就代表这两个点所组成的矩阵。

A = torch.arange(1, 5).reshape(2, 2).float()
A
# output :
tensor([[1., 2.],
        [3., 4.]])
import matplotlib as mpl
import matplotlib.pyplot as plt
plt.plot(A[:, 0], A[:, 1], 'o')
# output :

在这里插入图片描述

如果更近一步,我们希望在二维空间中找到一条直线,来拟合这两个点,也就是所谓的构建线性回归模型,我们可以设置线性回归方程如下:
y = a x + b y = ax + b y=ax+b
带入(1,2)和(3,4)两个点后,我们还可以进一步将表达式改写成矩阵表示形式,改写过程如下:

在这里插入图片描述

而用矩阵表示线性方程组,则是矩阵的另一种常见用途。接下来,我们就可以通过上述矩阵方程组来求解系数向量x

首先一个基本思路是,如果有个和A矩阵相关的另一个矩阵,假设为A−1,可以使得二者相乘之后等于1,也就是A∗A−1=1,那么在方程组左右两边同时左乘该矩阵,等式右边的计算结果A−1∗B就将是x系数向量的取值。而此处的A−1就是所谓的A的逆矩阵。

逆矩阵定义:如果存在两个矩阵A、B,并在矩阵乘法运算下,A * B = E(单位矩阵),则我们称A、B互为逆矩阵。

在上述线性方程组求解场景中,我们已经初步看到了逆矩阵的用途,而一般来说,我们往往会通过伴随矩阵来进行逆矩阵的求解。由于伴随矩阵本身并无其他核心用途,且PyTorch中也未给出伴随矩阵的计算函数(目前),因此我们直接调用inverse函数来进行逆矩阵的计算。

当然,并非所有矩阵都有逆矩阵,对于一个矩阵来说,首先必须是方正,其次矩阵的秩不能为零,满足两个条件才能求解逆矩阵。


inverse函数:求解逆矩阵

首先根据上述矩阵表达式重新定义A和B

A = torch.tensor([[1.0, 1], [3, 1]])
A
# output :
tensor([[1., 1.],
        [3., 1.]])
B = torch.tensor([2.0, 4])
B
# output :
tensor([2., 4.])

然后使用inverse函数进行逆矩阵求解

torch.inverse(A)
# output :
tensor([[-0.5000,  0.5000],
        [ 1.5000, -0.5000]])

简单试探逆矩阵的基本特性

torch.mm(torch.inverse(A), A)
# output :
tensor([[ 1.0000e+00, -5.9605e-08],
        [-1.1921e-07,  1.0000e+00]])

乍一看不像是单位阵,实际上除了对角线元素是1外,其他元素取值都非常非常小,在实际运算过程中可以忽略不计。

在方程组左右两边同时左乘 A − 1 A^{-1} A1,求解x
A − 1 ⋅ A ⋅ x = A − 1 ⋅ B E ⋅ x = A − 1 ⋅ B x = A − 1 ⋅ B \begin{align*} A^{-1} \cdot A \cdot x &= A^{-1} \cdot B \\ E \cdot x &= A^{-1} \cdot B \\ x &= A^{-1} \cdot B \end{align*} A1AxExx=A1B=A1B=A1B

torch.mv(torch.inverse(A), B)
# output :
tensor([1.0000, 1.0000])

最终得到线性方程为:
y = x + 1 y = x+1 y=x+1
上述计算过程只是一个简化的线性方程组求解系数的过程,同时也是一个简单的一元线性方程拟合数据的过程。


20 矩阵的分解

矩阵的分解也是矩阵运算中的常规计算,矩阵分解也有很多种类,常见的例如QR分解、LU分解、特征分解、SVD分解等等等等,虽然大多数情况下,矩阵分解都是在形式上将矩阵拆分成几种特殊矩阵的乘积,但本质上,矩阵的分解是去探索矩阵更深层次的一些属性。

本节将主要围绕特征分解和SVD分解展开。

值得一提的是,此前的逆矩阵,其实也可以将其看成是一种矩阵分解的方式,分解之后的等式如下:
A = A ∗ A − 1 ∗ A A = A * A^{-1} * A A=AA1A
而大多数情况下,矩阵分解都是分解成形如下述形式
A = V U D A = VUD A=VUD

特征分解

特征分解中,矩阵分解形式为:
A = Q Λ Q − 1 A = Q\Lambda Q^{-1} A=QΛQ1
其中,Q和 Q − 1 Q^{-1} Q1互为逆矩阵,并且Q的列就是A的特征值所对应的特征向量,而 Λ \Lambda Λ为矩阵A的特征值按照降序排列组成的对角矩阵。

torch.eig函数:特征分解

A = torch.arange(1, 10).reshape(3, 3).float()
A
# output :
tensor([[1., 2., 3.],
        [4., 5., 6.],
        [7., 8., 9.]])
torch.eig(A, eigenvectors = True)
# output :
torch.return_types.eig(
eigenvalues=tensor([[ 1.6117e+01,  0.0000e+00],
        [-1.1168e+00,  0.0000e+00],
        [-1.2253e-07,  0.0000e+00]]),
eigenvectors=tensor([[-0.2320, -0.7858,  0.4082],
        [-0.5253, -0.0868, -0.8165],
        [-0.8187,  0.6123,  0.4082]]))

输出结果中,eigenvalues表示特征值向量,即A矩阵分解后的Λ矩阵的对角线元素值,并按照由大到小依次排列,eigenvectors表示A矩阵分解后的Q矩阵。

此处需要理解特征值,所谓特征值,可简单理解为对应列在矩阵中的信息权重,如果该列能够简单线性变换来表示其他列,则说明该列信息权重较大,反之则较小。

特征值概念和秩的概念有点类似,但不完全相同,矩阵的秩表示矩阵列向量的最大线性无关数,而特征值的大小则表示某列向量能多大程度解读矩阵列向量的变异度,即所包含信息量,秩和特征值关系可用下面这个例子来进行解读。

B = torch.tensor([1, 2, 2, 4]).reshape(2, 2).float()
B
# output :
tensor([[1., 2.],
        [2., 4.]])
torch.matrix_rank(B)
# output :
tensor(1)
torch.eig(B)          # 返回结果中只有一个特征
# output :
torch.return_types.eig(
eigenvalues=tensor([[0., 0.],
        [5., 0.]]),
eigenvectors=tensor([]))
C = torch.tensor([[1, 2, 3], [2, 4, 6], [3, 6, 9]]).float()
C
# output :
tensor([[1., 2., 3.],
        [2., 4., 6.],
        [3., 6., 9.]])
torch.eig(C)                # 只有一个特征的有效值
# output :
torch.return_types.eig(
eigenvalues=tensor([[ 1.4000e+01,  0.0000e+00],
        [-1.6447e-07,  0.0000e+00],
        [ 2.8710e-07,  0.0000e+00]]),
eigenvectors=tensor([]))

特征值一般用于表示矩阵对应线性方程组解空间以及数据降维,当然,由于特征分解只能作用于方阵,而大多数实际情况下矩阵行列数未必相等,此时要进行类似的操作就需要采用和特征值分解思想类似的奇异值分解(SVD)


奇异值分解(SVD)

奇异值分解(SVD)来源于代数学中的矩阵分解问题,对于一个方阵来说,我们可以利用矩阵特征值和特征向量的特殊性质(矩阵点乘特征向量等于特征值数乘特征向量),通过求特征值与特征向量来达到矩阵分解的效果
A = Q Λ Q − 1 A = Q\Lambda Q^{-1} A=QΛQ1
这里,Q是由特征向量组成的矩阵,而Λ是特征值降序排列构成的一个对角矩阵(对角线上每个值是一个特征值,按降序排列,其他值为0),特征值的数值表示对应的特征的重要性。 在很多情况下,最大的一小部分特征值的和即可以约等于所有特征值的和,而通过矩阵分解的降维就是通过在Q、Λ 中删去那些比较小的特征值及其对应的特征向量,使用一小部分的特征值和特征向量来描述整个矩阵,从而达到降维的效果。 但是,实际问题中大多数矩阵是以奇异矩阵形式,而不是方阵的形式出现的,奇异值分解是特征值分解在奇异矩阵上的推广形式,它将一个维度为m×n的奇异矩阵A分解成三个部分 :
A = U ∑ V T A = U\sum V^{T} A=UVT
其中U、V是两个正交矩阵,其中的每一行(每一列)分别被称为左奇异向量和右奇异向量,他们和∑中对角线上的奇异值相对应,通常情况下我们只需要保留前k个奇异向量和奇异值即可,其中U是m×k矩阵V是n×k矩阵∑是k×k的方阵,从而达到减少存储空间的效果,即
A m ∗ n = U m ∗ m ∑ m ∗ n V n ∗ n T ≈ U m ∗ k ∑ k ∗ k V k ∗ n T A_{m*n} = U_{m*m}\sum_{m*n}V^{T}_{n*n}\approx U_{m*k}\sum_{k*k}V^{T}_{k*n} Amn=UmmmnVnnTUmkkkVknT

奇异值分解函数

C
# output :
tensor([[1., 2., 3.],
        [2., 4., 6.],
        [3., 6., 9.]])
torch.svd(C)
# output :
torch.return_types.svd(
U=tensor([[-0.2673, -0.8018, -0.5345],
        [-0.5345, -0.3382,  0.7745],
        [-0.8018,  0.4927, -0.3382]]),
S=tensor([14.0000,  0.0000,  0.0000]),
V=tensor([[-0.2673,  0.0000,  0.9636],
        [-0.5345, -0.8321, -0.1482],
        [-0.8018,  0.5547, -0.2224]]))
CU, CS, CV = torch.svd(C)	# 验证SVD分解
torch.mm(torch.mm(CU, torch.diag(CS)), CV.t())
# output :
tensor([[1.0000, 2.0000, 3.0000],
        [2.0000, 4.0000, 6.0000],
        [3.0000, 6.0000, 9.0000]])

能够看出,上述输出完整还原了C矩阵,此时我们可根据svd输出结果对C进行降维,此时C可只保留第一列(后面的奇异值过小),即k = 1

U1 = CU[:, 0].reshape(3, 1)         # U的第一列
U1
# output :
tensor([[-0.2673],
        [-0.5345],
        [-0.8018]])
C1 = CS[0]                           # C的第一个值
C1
# output :
tensor(14.0000)
V1 = CV[:, 0].reshape(1, 3)           # V的第一行
V1
# output :
tensor([[-0.2673, -0.5345, -0.8018]])
torch.mm((U1 * C1), V1)
# output :
tensor([[1.0000, 2.0000, 3.0000],
        [2.0000, 4.0000, 6.0000],
        [3.0000, 6.0000, 9.0000]])

此时输出的Cd矩阵已经和原矩阵C高度相似了,损失信息在R的计算中基本可以忽略不计,经过SVD分解,矩阵的信息能够被压缩至更小的空间内进行存储,从而为PCA(主成分分析)、LSI(潜在语义索引)等算法做好了数学工具层面的铺垫。

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

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

相关文章

Linux下构建OpenEuler22.03+Nginx的Docker镜像

1. 制作OpenEuler22.03的Docker镜像 首先,下载OpenEuler20.03的镜像压缩包: 下载链接为: https://mirrors.aliyun.com/openeuler/openEuler-22.03-LTS/docker_img/x86_64/openEuler-docker.x86_64.tar.xz 这里我们可以顺便下载一下对应的…

Coder星球-测试用例设计

项目介绍 Coder星球是一个前后端分离的开源技术交流平台,包括管理后台和web前端,旨在打造一个互相交流技术并共同进步的平台。 项目功能结构图 测试用例 1.登录 2.注册 3.文章发布 4.点赞 5.评论

wow-agent---task2使用llama-index创建Agent

一:创造俩个函数,multiply和add作为fuction calling被LLM当做工具来使用,实现计算一个简单的计算题: from llama_index.llms.ollama import Ollama from llama_index.core.agent import ReActAgent from llama_index.core.tools …

React的应用级框架推荐——Next、Modern、Blitz等,快速搭建React项目

在 React 企业级应用开发中,Next.js、Modern.js 和 Blitz 是三个常见的框架,它们提供了不同的特性和功能,旨在简化开发流程并提高应用的性能和扩展性。以下是它们的详解与比较: Next、Modern、Blitz 1. Next.js Next.js 是由 Ve…

Git - 将指定文件夹或文件忽略(无论添加缓存区或提交都不会显示)

前言 有些时候,我们 不希望 项目有些文件夹被 Git “监控” 起来,而是与 Git 毫无关系。 第一步 注意:touch 与 . 之间有空格。 在 Gitbash 命令窗口中,输入以下命令: touch .gitignore此时,你的项目文件…

HTML5+Canvas实现的鼠标跟随自定义发光线条源码

源码介绍 HTML5Canvas实现的鼠标跟随自定义发光线条特效源码非常炫酷&#xff0c;在黑色的背景中&#xff0c;鼠标滑过即产生彩色变换的发光线条效果&#xff0c;且线条周围散发出火花飞射四溅的粒子光点特效。 效果预览 源码如下 <!DOCTYPE html PUBLIC "-//W3C//D…

C++:bfs解决多源最短路与拓扑排序问题习题

1. 多源最短路 其实就是将所有源头都加入队列&#xff0c; 01矩阵 LCR 107. 01 矩阵 - 力扣&#xff08;LeetCode&#xff09; 思路 求每个元素到离其最近0的距离如果我们将1当做源头加入队列的话&#xff0c;无法处理多个连续1的距离存储&#xff0c;我们反其道而行之&…

Java基础--类和对象

目录 什么是类&#xff1f; 什么是对象 为什么java会设计对象 Java对象该怎么用 程序执行流程 类的加载顺序 什么是类&#xff1f; 类是构建对象的模板&#xff0c;一个类可以创建多个对象&#xff0c;每个对象的数据的最初来源来自对象 public class Student{public in…

学习ASP.NET Core的身份认证(基于JwtBearer的身份认证6)

重新创建WebApi项目&#xff0c;安装Microsoft.AspNetCore.Authentication.JwtBearer包&#xff0c;将之前JwtBearer测试项目中的初始化函数&#xff0c;jwt配置类、token生成类全部挪到项目中。   重新编写login函数&#xff0c;之前测试Cookie和Session认证时用的函数适合m…

Electron实践继续

文章目录 前言一、知识储备前提二、开发工具集&#xff08;一&#xff09;代码编辑器之选&#xff08;二&#xff09;命令行工具运用&#xff08;三&#xff09;Git 与 GitHub 协作利器&#xff08;四&#xff09;Node.js 与 npm 核心环境 你的第一个Electron应用程序 前言 上…

《自动驾驶与机器人中的SLAM技术》ch8:基于预积分和图优化的紧耦合 LIO 系统

和组合导航一样&#xff0c;也可以通过预积分 IMU 因子加上雷达残差来实现基于预积分和图优化的紧耦合 LIO 系统。一些现代的 Lidar SLAM 系统也采用了这种方式。相比滤波器方法来说&#xff0c;预积分因子可以更方便地整合到现有的优化框架中&#xff0c;从开发到实现都更为便…

【CSS】---- CSS 实现超过固定高度后出现展开折叠按钮

1. 实现效果 2. 实现方法 使用 JS 获取盒子的高度&#xff0c;来添加对应的按钮和样式&#xff1b;使用 CSS 的浮动效果&#xff0c;参考CSS 实现超过固定高度后出现展开折叠按钮&#xff1b;使用容器查询 – container 语法&#xff1b;使用 clamp 函数进行样式判断。 3. 优…

【C语言】_字符串拷贝函数strcpy

目录 1. 函数声明及功能 2. 使用示例 3. 注意事项 4. 模拟实现 4.1 第一版&#xff1a;基本功能判空const修饰 4.2 第二版&#xff1a;优化对于\0的单独拷贝 4.3 第三版&#xff1a;仿strcpy的char*返回值 1. 函数声明及功能 char * strcpy ( char * destination, cons…

大文件上传服务-后端V1V2

文章目录 大文件上传概述:minio分布式文件存储使用的一些技术校验MD5的逻辑 uploadV1 版本 1uploadv2 版本 2 大文件上传概述: 之前项目做了一个文件上传的功能,最近看到有面试会具体的问这个上传功能的细节&#xff0c;把之前做的项目拿过来总结一下&#xff0c;自己写的一个…

【k8s面试题2025】1、练气期

主要通过呼吸吐纳等方法&#xff0c;将外界的天地灵气吸入体内&#xff0c;初步改造身体&#xff0c;使身体素质远超常人。 文章目录 docker 和虚拟机的不同Kubernetes 和 docker 的关系Kube-proxy IPVS 和 iptables 的异同蓝绿发布Kubernetes中常见的数据持久化方式关于 Docke…

快速入门:如何注册并使用GPT

文章目录 ProtonMail邮箱步骤 1&#xff1a;访问Proton官网步骤 2&#xff1a;创建ProtonMail账户步骤 3&#xff1a;选择注册免费账户步骤 4&#xff1a;填写邮箱地址和手机号&#xff08;可选&#xff09;步骤 5&#xff1a;邮箱验证&#xff08;必须进行验证&#xff09;步骤…

浅谈云计算22 | Kubernetes容器编排引擎

Kubernetes容器编排引擎 一、Kubernetes管理对象1.1 Kubernetes组件和架构1.2 主要管理对象类型 二、Kubernetes 服务2.1 服务的作用与原理2.2 服务类型 三、Kubernetes网络管理3.1 网络模型与目标3.2 网络组件3.2.1 kube-proxy3.2.2 网络插件 3.3 网络通信流程 四、Kubernetes…

Vulnhub DC-8靶机攻击实战(一)

导语   Vulnhub DC-8靶机教程来了,好久没有更新打靶的教程了,这次我们在来更新一期关于Vulnhub DC-8的打靶训练,如下所示。 安装并且启动靶机 安装并且启动靶机,如下所示。 开始信息采集 进入到Kali中,通过如下的命令来查找到靶机的IP地址。 arp-scan -l根据上面的结…

自学SpringBoot笔记

概念 什么是SpringBoot&#xff1f; Spring Boot 是基于 Spring Framework 的一款开源框架&#xff0c;主要用于简化 Spring 应用程序的开发。它通过提供一系列的 开箱即用的功能 和 自动配置&#xff0c;让开发者可以快速构建生产级别的独立应用程序&#xff0c;而无需手动配…

通过学习更多样化的生成数据进行更广泛的数据分发来改进实例分割

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; 本次使用的英文整理的一些记录&#xff0c;练习一下为后续SCI发表论文打好基础 Improving Instance Segmentation by Learning Wider Data Distribution with More Diverse Generative Data Abstract In…