深度学习blog-深刻理解线性变换和矩阵

深度学习中避免不了矩阵运算,或者张量(其实是矩阵数组)运算。卷积是矩阵加、乘法,注意力也是一样。本质都一样,所谓注意力,卷积、滤波,是对不必了解数学的人说的,底层都是矩阵运算,线性变换。

任何一个向量都可以用基向量的线性组合来表示。

即任何一个向量都可以用基向量通过线性变换得到。

矩阵相乘的几何意义就是两个线性变换的相继作用。

通过线性变换,不仅可以得到这一组合的变换结果,也可以有效地计算任意向量的线性变换结果。

看看旋转变换:

比如上图所示,向量R逆时针旋转角度B前后的情况。

在左图中,有:

x0 = |R| * cosA => cosA = x0 / |R|

y0 = |R| * sinA => sinA = y0 / |R|

同样的,在右图中:

x1 = |R| * cos(A+B)

y1 = |R| * sin(A+B)

其中(x1, y1)就是(x0, y0)旋转角B后得到的向量,展开cos(A+B)和sin(A+B):

x1 = |R| * (cosAcosB - sinAsinB)

y1 = |R| * (sinAcosB + cosAsinB)

把 cosA = x0 / |R| 和 sinA = y0 / |R| 代入上面的式子,得到:

x1 = |R| * (x0 * cosB / |R| - y0 * sinB / |R|) => x1 = x0 * cosB - y0 * sinB

y1 = |R| * (y0 * cosB / |R| + x0 * sinB / |R|) => y1 = x0 * sinB + y0 * cosB

这样就得到了二维坐标下向量的逆时针旋转公式。顺时针旋转就把角度变为负:

x1 = x0 * cos(-B) - y0 * sin(-B) => x1 = x0 * cosB + y0 * sinB

y1 = x0 * sin(-B) + y0 * cos(-B)=> y1 = -x0 * sinB + y0 * cosB

把这个公式写成矩阵的形式,每个线性变换(这里是旋转变换)都对应一个矩阵,叫做变换矩阵。

线性变换的性质

  1. 唯一性:每个线性变换由其在基向量上的值唯一确定。
  2. 矩阵表示:每个线性变换可以用矩阵表示,通过矩阵与向量的乘法来实现变换。
  3. 复合性:两个线性变换的复合依然是线性变换。
  4. 零向量的映射:线性变换总是将零向量映射为零向量,即 T(0)=0T(0)=0。
  5. 负元素的象为原来元素的象的负元素。
  6. 线性变换把线性相关的元素组仍变为线性相关的元素组。
  7. 特征值和特征向量:线性变换的特征值和特征向量可帮助理解变换性质,如缩放、旋转等。

注: 线性无关的元素组经过线性变换不一定再是线性无关的, 变换后的情况与元素组和线性变换有关。若线性变换 T 将所有的元素组仍变换为线性无关的元素组,则称之为满秩的线性变换,其变换矩阵为满秩矩阵。

常见变换:平移变换、 旋转变换、 缩放变换、 反射变换、 投影变换。

1、线性变换是自身空间下的变换,而仿射变换是不同空间下的变换。线性变换作用后,空间维数不变,仿射变换作用后空间维数可能改变。

2、仿射变换与线性变换的区别在于变换前后是否改变原点。仿射变换=线性变换+平移变换

3、旋转,伸缩改变向量的方法,伸缩不改变方向

4、正交变换是指通过正交矩阵进行的线性变换。可以简单理解为矩阵的行(或列)向量是正交的,并且每个向量的长度为1。

性质:
保持角度和长度:正交变换保持向量之间的夹角和长度,意味着不改变几何形状。
几何意义:正交变换可以看作是对空间的旋转或反射。

几种特殊矩阵:对称矩阵、正交矩阵、单位矩阵、酉矩阵、 Hermite矩阵、上下三角矩阵等。

向量完成变换的关键是:要找到那个变换矩阵T

变换矩阵T的本质是:找到一组基向量

找到一组基向量等价于:找到了一个坐标系

找到一组基向量意味着:找到了一个向量空间

PyTorch 张量操作函数:

a. 张量创建

torch.zeros(size):创建全0张量。

torch.ones(size):创建全1张量。

torch.empty(size):创建未初始化的张量。

torch.rand(size):创建随机值张量。
torch.eye(n):创建单位矩阵。

b. 张量形状操作
tensor.view(shape):重塑张量。
tensor.reshape(...):重塑张量,注意跟view的区别。
tensor.permute(dims):改变张量的维度顺序。
tensor.unsqueeze(dim):在指定维度上增加一个维度。
tensor.squeeze(dim):去除指定维度的大小为1的维度。
torch.cat(tensors, dim):沿指定维度拼接多个张量。

c. 张量运算
torch.matmul(a, b):矩阵乘法。
torch.add(a, b):张量加法。
torch.subtract(a, b):张量减法。
torch.multiply(a, b):张量逐元素相乘。
torch.divide(a, b):张量逐元素相除。

d. 张量统计

tensor.mean(dim):计算均值。

tensor.sum(dim):计算和。

tensor.max(dim):计算最大值。

tensor.min(dim):计算最小值。

e. 张量索引与切片

tensor[index]:索引单个元素。

tensor[start:end]:切片操作。

f. 其他操作
transpose(dim0, dim1):交换两个维度。

transpose(-2, -1)交换最后两个维度,负数表示从里层开始算,正数表示从外层开始算。

torch.stack(tensors, dim):在新维度上堆叠多个张量。

tensor.clone():克隆一个张量。
tensor.contiguous() :使张量在内存里连续,一般用在view()函数之前。

张量运算常见错误:

python 复制代码
import torch
import torch.nn as nn
import torch.nn.functional as F

input_tensor = torch.randn(2, 3, 4, 5)
print(input_tensor)
print("----------------")
y=input_tensor.permute(0,2,3,1)
y=y.view(4,3,2,5)
print(y.shape)

运行错误:

y=y.view(4,3,2,5)

RuntimeError: view size is not compatible with input tensor's size and stride (at least one dimension spans across two contiguous subspaces). Use .reshape(...) instead.

解析错误原因

在 PyTorch 中,view 方法要求输入张量的内存是连续的(contiguous)。当你调用 permute 方法时,它会改变张量的维度顺序,但不会改变其在内存中的存储顺序。

因此,经过 permute 后的张量可能不是连续的,这就导致了在使用 view 时出现了错误。在 permute 之后,y 的形状变为 (2, 4, 5, 3),但是这个张量在内存中并不连续。

当你尝试执行 y = y.view(4, 3, 2, 5) 时,PyTorch 检测到 y 的内存布局不符合 view 的要求,因此抛出了 RuntimeError。

解决:view替换为reshape 或者先调用contiguous()

y=y.reshape(3,4,5,2)

y=y.contiguous().view(4,3,2,5)

这同时也展示了view、permute、reshape用法的不同。view和reshape的输入参数是张量的每个维度的大小,在不关心每个维度是多长时,可以用permute,输入原张量维度的序号(0,1,2,3,4...)他们的用途都是重塑张量的形状,但是,view需要张量的内存是连续的,如果一个张量发生了形状的改变,在内存里可能就不是连续的,此时调用view前,先用contiguous()。

在 PyTorch 中, torch.nn.Linear 是用于构建线性变换(又称为全连接层或线性层)的类,常用在神经网络中。原型:torch.nn.Linear(self, in_features: int, out_features: int, bias: bool = True,device=None, dtype=None)

输入参数解析

1.in_features (int):

这是输入特征的维度,即输入向量的大小。例如,如果输入数据是一个具有 10 个特征的样本,则 in_features 应设置为 10。

2.out_features (int):

这是输出特征的维度,即线性变换后输出向量的大小。例如,如果希望输出数据具有 5 个特征,则 out_features 应设置为 5。

3.bias (bool, optional):

默认值为 True。这个参数指示是否包含偏置项(bias term)。如果设置为 True,则该线性层在计算时会添加一个偏置项;如果设置为 False,则省略偏置项。线性变换的公式一般为:

output=input⋅weightT+biasoutput=input⋅weightT+bias

  • biasFalse 时,公式简化为:output=input⋅weightToutput=input⋅weightT

4.device (torch.device, optional):

这个参数用于指定张量要分配到的设备(例如,CPU 或 GPU)。

5.dtype (torch.dtype, optional):

这是指定张量数据类型的参数。例如 torch.float32torch.float64

简单例子:

python 复制代码
import torch
import torch.nn as nn


class Example(nn.Module):
    def __init__(self, d_model, num_heads):
        super(Example, self).__init__()
        self.d_model = d_model
        self.num_heads = num_heads
        # 两个参数分别是输入
        self.W_q = nn.Linear(d_model, d_model)

    def forward(self, x):
        # 输入 x, shape = (batch_size, seq_length, d_model)
        # 假设我们有 batch_size=2, seq_length=3, d_model=4
        x = torch.arange(24).view(2, 3, 4).float()  # Shape: (2, 3, 4)
        print(x)
        # 执行线性变换
        Q = self.W_q(x)  # 仍然是(2, 3, 4)
        print(Q)

        # 对Q进行reshape操作
        Q = Q.view(2, 3, 2, 2)  # Shape: (2, 3, 2, 2), 假设 num_heads=2, d_k=2
        Q = Q.transpose(1, 2)  # Shape: (2, 2, 3, 2)

        # 进行一些示例
        print("原始Q:", x)
        print("线性变换后的Q:", Q)

model = Example(4, 2)
model(torch.randn(2, 3, 4))

# 输入维度为3,输出维度为2
linear_layer = nn.Linear(3, 3)

# 随机输入一个batch大小为1,特征维度为3的张量
input_tensor = torch.tensor([[1.0, 2.0, 3.0]])  # Batch size = 1, Features = 3

# 线性层前向传播
output = linear_layer(input_tensor)
print(output)


print("---------------")
# in_features=4,out_features=3
m = nn.Linear(4, 3)
# 只要最后一维的大小等于 in_features(这里是4)
input = torch.randn(2,3,5,4) 
print(input)
output = m(input)
print(output)
print(output. Size())

总之线性变换对应一个变换矩阵,变换矩阵也是一个函数(映射)。

相关推荐
汀沿河4 分钟前
基于Swarm的大模型应用:一个天气助手
开发语言·人工智能·python
KeyPan8 分钟前
【数据结构与算法:八、排序】
开发语言·数据结构·人工智能·后端·算法·排序算法·scala
LIKEYYLL11 分钟前
【年前学SHU分享】:教育发展、人工智能、电子通信、能源
人工智能
leisigoyle17 分钟前
第五届电网系统与绿色能源国际学术会议(PGSGE 2025)
大数据·人工智能·能源
TGITCIC18 分钟前
AI 将在今年获得“永久记忆”,2028美国会耗尽能源储备
人工智能·aigc·能源·ai新闻·ai最新事·ai奇闻·ai动态
研一计算机小白一枚44 分钟前
Deep blind super-resolution for hyperspectral images_译文
人工智能·深度学习·计算机视觉
狂奔solar1 小时前
图神经网络在yelp数据集上分析用户如何影响彼此的评价
人工智能·深度学习·神经网络
ccmjga1 小时前
升级 Spring Boot 3 配置讲解 —— 如何在 Spring Boot 3 中接入生成式 AI?
java·人工智能·spring boot·后端·docker·面试·单元测试
远洋录1 小时前
Tailwind CSS 实战:深色模式设计与实现
前端·人工智能·react
.远_1 小时前
CUDA C | 第一章 基于CUDA的异构并行计算
linux·c++·人工智能·python