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

news2025/1/9 12:50:32

深度学习中避免不了矩阵运算,或者张量(其实是矩阵数组)运算。卷积是矩阵加、乘法,注意力也是一样。本质都一样,所谓注意力,卷积、滤波,是对不必了解数学的人说的,底层都是矩阵运算,线性变换。神经网络中的权重矩阵W可看作是对输入的数据进行特征转换,即先将数据编码为另一种形式,然后在此基础上进行一系列学习。

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

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

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

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

看看旋转变换:

比如上图所示,向量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()函数之前。

张量运算常见错误:

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

  • 当 bias 为 False 时,公式简化为:output=input⋅weightToutput=input⋅weightT

4.device (torch.device, optional):

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

5.dtype (torch.dtype, optional):

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

简单例子:

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())

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

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

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

相关文章

C/C++程序性能测试方法综述

摘要 性能测试是软件开发中不可或缺的一部分,特别是在对性能要求较高的C/C程序中。本文将详细介绍多种C/C程序性能测试方法,包括时间复杂度分析、事后统计方法、事前分析估算方法、使用性能测试工具(如Google Benchmark、gprof、Valgrind等&…

jmeter 中 BeanShell 预处理程序、JSR223后置处理程序使用示例

1. 各个组件如何新建的? 2. "http请求" 组件内容样例: "消息体数据" 源码: {"task_tag": "face_detect","image_type": "base64","extra_args": [{"model"…

电脑32位和64位之区别(Difference between 32-Bit and 64 Bit Computers)

电脑32位和64位之区别 很多小伙伴还不知道电脑32位和64位是什么意思,今天小编就来普及一下。 32位和64位是指电脑处理器(CPU)和操作系统的架构,决定了电脑如何处理数据、存储信息、运行程序等。 32位和64位是指电脑系统中每个处…

vue -关于浏览器localstorge数据定期清除的实现

1.实现背景 用户登录时的信息存在了localstorge中,但它会一直存在。一般来说,我们希望这个数据能够定期被清除掉,以下一个定时清除的实现。 2.实现原理 在用户登录时,将用户信息存入localstorge的同时,将当前时间作…

【JavaEE进阶】获取Cookie/Session

🍀Cookie简介 HTTP协议自身是属于 "⽆状态"协议. "⽆状态"的含义指的是: 默认情况下 HTTP 协议的客⼾端和服务器之间的这次通信,和下次通信之间没有直接的联系.但是实际开发中,我们很多时候是需要知道请求之间的关联关系的. 例如登陆⽹站成…

【工具变量】统计行业锦标赛激励数据集(2008-2023年)

一、数据简介 坚持创新驱动发展,要强化企业创新主体地位,发挥企业家在技术创新中的重要作用。作为企业组织内部最具有影响力的角色,高级管理人员拥有企业经营管理的自由裁量权,对企业战略决策及由此产生的经营绩效具有举足轻重的…

UVM: TLM机制

topic overview 不建议的方法:假如没有TLM TLM TLM 1.0 整个TLM机制下,底层逻辑离不开动作发起者和被动接受者这个底层的模型基础,但实际上,在验证环境中,任何一个组件,都有可能成为动作的发起者&#xff0…

Scratch023-(沙漠变绿洲)

提示: 知识回顾: 1、画笔的各个属性 2、“将笔的颜色设为”积木 3、“将笔的颜色增加”积木 文章目录 前言一、案例展示二、功能分析三、步骤拆解1.背景角色和画笔的初始化(1)初始化画笔2、一起绘制一个小雨滴3、绘制多个随机的小…

游戏语音趋势解析,社交互动有助于营造沉浸式体验

语音交互的新架构出现 2024 年标志着对话语音 AI 取得了突破,出现了结合 STT → LLM → TTS 模型来聆听、推理和回应对话的协同语音系统。 OpenAI 的 ChatGPT 语音模式将语音转语音技术变成了现实,引入了基于音频和文本信息进行端到端预训练的模型&…

详细全面讲解C++中重载、隐藏、覆盖的区别

文章目录 总结1、重载示例代码特点1. 模板函数和非模板函数重载2. 重载示例与调用规则示例代码调用规则解释3. 特殊情况与注意事项二义性问题 函数特化与重载的交互 2. 函数隐藏(Function Hiding)概念示例代码特点 3. 函数覆盖(重写&#xff…

计算机网络之---物理层设备

什么是物理层设备 物理层设备是指负责数据在物理媒介上传输的硬件设备,它们主要处理数据的转换、信号的传输与接收,而不涉及数据的内容或意义。常见的物理层设备包括网卡、集线器、光纤收发器、调制解调器等。 物理层设备有哪些 1、网卡(N…

js状态模式

允许一个对象在其内部状态改变时改变它的行为。 状态模式将对象的状态封装成独立的类,并使它们可以互相转换 // 定义状态接口class State {constructor() {if (this.constructor State) {throw new Error(不能实例化抽象类);}}// 定义状态方法handle(context) {th…

平面坐标转大地坐标(arcgisPro中进行)

1、将需要转换的红线导入arcgisPro中,如下: 2、在地图菜单栏中,选择坐标转换工具,如下: 3、打开坐标转换工具 4、开启捕捉 5、 设置大地坐标显示格式 6、如下: 7、显示如图: 8、再依次添加几个待…

(长期更新)《零基础入门 ArcGIS(ArcScene) 》实验七----城市三维建模与分析(超超超详细!!!)

城市三维建模与分析 三维城市模型已经成为一种非常普遍的地理空间数据资源,成为城市的必需品,对城市能化管理至关重要。语义信息丰富的三维城市模型可以有效实现不同领域数据与IS相信息的高层次集成及互操作,从而在城市规划、环境模拟、应急响应和辅助决策等众多领域公挥作用、…

SpringBootWeb 登录认证(day12)

登录功能 基本信息 请求参数 参数格式:application/json 请求数据样例: 响应数据 参数格式:application/json 响应数据样例: Slf4j RestController public class LoginController {Autowiredpriva…

夯实前端基础之HTML篇

知识点概览 HTML部分 1. DOM和BOM有什么区别? DOM(Document Object Model) 当网页被加载时,浏览器会创建页面的对象文档模型,HTML DOM 模型被结构化为对象树 用途: 主要用于网页内容的动态修改和交互&…

UI自动化测试保姆级教程--pytest详解(精简易懂)

欢迎来到啊妮莫的学习小屋 别让过去的悲伤,毁掉当下的快乐一《借东西的小人阿莉埃蒂》 简介 pytest是一个用于Python的测试框架, 支持简单的单元测试和复杂的功能测试. 和Python自带的UnitTest框架类似, 但是相比于UnitTest更加简洁, 效率更高. 特点 非常容易上手…

有序数据中插入不确定数据保证数据插入的位置顺序正确排序

解决有序数据中插入不确定数据保证数据插入的位置顺序正确排序 前言 java 数据库中存储自增id 有序的数据, 前端页面基于 id 5和 6 之间新增一条数据,在 id 6 和 7之间新增 2条,或者更复杂的场景,后台接口如何保存数据使得页面数…

基于 Apache Commons Pool 实现的 gRPC 连接池管理类 GrpcChannelPool 性能分析与优化

基于 Apache Commons Pool 实现的 gRPC 连接池管理类 GrpcChannelPool 性能分析与优化 1. 输出关键信息的代码示例 日志记录方法 使用以下代码记录连接池的关键信息,帮助分析连接池的状态和性能瓶颈: import org.apache.commons.pool2.impl.GenericO…

不同方式获取音频时长 - python 实现

DataBall 助力快速掌握数据集的信息和使用方式,会员享有 百种数据集,持续增加中。 需要更多数据资源和技术解决方案,知识星球: “DataBall - X 数据球(free)” -------------------------------------------------------------…