用manim实现Gram-Schmidt正交化过程

news2024/11/27 18:39:36

        在线性代数中,正交基有许多美丽的性质。例如,由正交列向量组成的矩阵(又称正交矩阵)可以通过矩阵的转置很容易地进行反转。此外,例如:在由彼此正交的向量张成的子空间上投影向量也更容易。Gram-Schmidt过程是一个重要的算法,它允许我们将任意基转换为生成同一子空间的正交基。在这篇文章中,我们将使用一个流行的开源库。manim在3D中实现和可视化这个算法

        Gram-Schmidt过程是一种用于将一组线性无关的向量转化为一组正交(或正交归一化)的向量的算法。这个过程在数学和工程中广泛应用,特别是在计算机图形学、信号处理和统计分析中。

Gram-Schmidt 正交化的步骤

假设我们有一组线性无关的向量 {v_{1},v_{2},...,v_{n}},Gram-Schmidt过程的步骤如下:

  1. 初始化:给定向量v_{1},定它为第一个正交向量 u_{1}:

u_{1}=v_{1}

     2.后续向量的正交化:对于每个i=1,2,3,...,n,计算新的正交向量 u_{1}​:

u_{1}=v_{1}- \sum_{j=1}^{i-1}proj_{u_{i}}(v_{i})

        其中,投影 proj_{u_{i}}(v_{i}) 是:

proj_{u_{i}}(v_{i})=\frac{v_{i}.u_{j}}{v_{j}.u_{j}}.u_{j}

        这里表示向量的点积。

     3.归一化(可选):如果需要将向量归一化,使其单位长度,可以通过以下公式进行:

q_{i}=\frac{u_{i}}{||u_{i}||}

        其中 ||u_{i}||是向量u_{i}的模。

应用

  • 正交基:Gram-Schmidt过程的输出结果是正交基,可以用于简化内积空间中的计算。
  • 数值稳定性:在计算中使用正交向量能提高数值稳定性,特别是在进行矩阵分解(如QR分解)时。
  • 计算简化:在许多应用中(如最小二乘法),正交向量可以简化计算,使得更容易处理高维数据。

用manim实现向量的表示

        代码为了实现 Gram-Schmidt 正交化的可视化过程而构建,使用了 Manim 库。

from manim import *  # 导入 Manim 库  
import numpy as np  # 导入 NumPy 库以进行数值计算  
from enum import Enum  # 导入枚举模块以创建动作类型  

# 定义颜色  
basis_i_color = GREEN  # 基向量 i 的颜色  
basis_j_color = RED    # 基向量 j 的颜色  
basis_k_color = GOLD   # 基向量 k 的颜色  
q_color = PURPLE       # 向量 q 的颜色  
q_shifted_color = PINK # 移动的向量 q 的颜色  
projection_color = BLUE # 投影向量的颜色  

# 定义动作枚举,便于管理不同的操作  
class Action(Enum):  
    UPDATE_MATRIX_REMOVE_Q = 1  # 更新矩阵并移除 q 向量  
    ADD_PROJECTION = 2           # 添加一个投影向量  
    REMOVE_PROJECTIONS_SET_Q = 3 # 移除投影向量并设置新的 q 向量  
    NORMALIZE_Q = 4              # 规范化 q 向量  

# 实现 Gram-Schmidt 过程  
def gram_schmidt(A):  
    (n, m) = A.shape  # 获取矩阵 A 的形状  
    
    for i in range(m):  
        q = A[:, i]  # 选取矩阵 A 的第 i 列  
        
        for j in range(i):  
            # 计算并从 q 中减去之前列的投影  
            projection = np.dot(A[:, j], A[:, i]) * A[:, j]  
            q = q - projection  
        
        # 归一化 q 向量  
        q /= np.linalg.norm(q)  
        yield Action.NORMALIZE_Q, q  # 返回规范化的 q 向量  

# 创建一个新的场景,用于展示 Gram-Schmidt  
class GramSchmidt(Scene):  
    def construct(self):  
        # 创建基础向量的颜色,并初始化向量和矩阵 M  
        M = np.random.rand(3, 3)  # 随机初始化 3x3 矩阵 M  
        projection_vectors = []     # 初始化用于存储投影向量的列表  
        q = None                    # 初始化 q 向量为 None  

        # 初始化基向量箭头  
        i_vec = Vector(M[:, 0], color=basis_i_color)  # i 向量  
        j_vec = Vector(M[:, 1], color=basis_j_color)  # j 向量  
        k_vec = Vector(M[:, 2], color=basis_k_color)  # k 向量  

        # 播放箭头和矩阵的动画  
        self.play(GrowArrow(i_vec), GrowArrow(j_vec), GrowArrow(k_vec))  
        self.wait()  

        # 遍历 Gram-Schmidt 的步骤  
        for (action, payload) in gram_schmidt(M):  
            if action == Action.UPDATE_MATRIX_REMOVE_Q:  
                # 此步骤用于更新矩阵,并移除旧的 q 向量  
                assert q is not None  
                M_rounded = np.round(M.copy(), 2)  # 对矩阵 M 进行四舍五入  
                matrix = self.create_matrix(M_rounded)  # 创建新的矩阵对象  
                self.remove(matrix)  # 移除旧的矩阵  

                # 更新基向量  
                i_vec_new = Vector(M[:, 0], color=basis_i_color)  
                j_vec_new = Vector(M[:, 1], color=basis_j_color)  
                k_vec_new = Vector(M[:, 2], color=basis_k_color)  

                animation_time = 2.0  # 动画时间  
                
                # 播放更新基向量的动画  
                self.play(  
                    FadeOut(q, run_time=animation_time * 0.75),  
                    ReplacementTransform(i_vec, i_vec_new, run_time=animation_time),  
                    ReplacementTransform(j_vec, j_vec_new, run_time=animation_time),  
                    ReplacementTransform(k_vec, k_vec_new, run_time=animation_time)  
                )  
                
                self.wait()  # 等待一段时间  
                # 更新现有向量引用  
                i_vec, j_vec, k_vec = i_vec_new, j_vec_new, k_vec_new  

            elif action == Action.ADD_PROJECTION:  
                # 添加新的投影向量  
                p = Vector(payload, color=projection_color)  
                projection_vectors.append(p)  # 将投影向量添加到列表中  
                self.play(GrowArrow(p))  # 播放投影箭头的动画  

                self.wait()  # 等待  

                if len(projection_vectors) == 2:  
                    # 当有两个投影向量时,更新其显示效果  
                    first_projection_end = projection_vectors[0].get_end()  
                    p_shifted = Arrow(first_projection_end, first_projection_end + payload, buff=0, color=projection_color)  
                    projection_vectors[1] = p_shifted  

                    self.play(ReplacementTransform(p, p_shifted))  # 替换动画  
                    self.wait()  # 等待  

            elif action == Action.REMOVE_PROJECTIONS_SET_Q:  
                # 移除投影并设置新的 q 向量  
                if not projection_vectors:  
                    q = Vector(payload, color=q_color)  
                    self.play(GrowArrow(q))  # 播放 q 向量的动画  
                    self.wait()  
                else:  
                    last_projection_end = projection_vectors[-1].get_end()  
                    q_shifted = Arrow(last_projection_end, last_projection_end + payload, buff=0, color=q_shifted_color)  
                    self.play(GrowArrow(q_shifted))  
                    self.wait()  

                    q = Vector(payload, color=q_color)  # 设置新的 q 向量  
                    self.play(  
                        ReplacementTransform(q_shifted, q),  
                        *[FadeOut(p) for p in projection_vectors]  # 移除所有投影  
                    )  
                    self.wait()  
                    projection_vectors = []  # 清空投影向量列表  

            elif action == Action.NORMALIZE_Q:  
                # 规范化 q 向量  
                q_normalized = Vector(payload, color=q_color)  
                self.play(ReplacementTransform(q, q_normalized))  # 播放规范化动画  
                self.wait()  
                q = q_normalized  # 更新 q 向量  

            else:  
                assert False  # 确保没有未识别的动作  

            self.wait(1)  # 在每轮操作间等待  

        # 验证结果  
        assert np.allclose(M.T @ M, np.identity(3))  # 确保 M 的转置乘以 M 为单位矩阵  
        self.wait(15)  # 等待更长时间以查看最终结果

代码解释

  1. 依赖导入:导入了 Manim 和 NumPy 库,Manim 用于创建动画,NumPy 用于数值计算。
  2. 颜色和动作类型定义:定义了不同颜色用于表示基向量、投影、规范化向量等,并通过枚举类型管理不同的动画操作。
  3. 实现 Gram-Schmidt:定义了 gram_schmidt 函数,用于计算 Gram-Schmidt 正交化,逐列处理输入矩阵。
  4. 创建场景:在 GramSchmidt 类中,设置基向量和矩阵,并实现了多个动画步骤,以展示算法的每一步。
  5. 动画逻辑:根据不同的 Action 执行相应的动画,包括更新向量、添加和移除投影向量、规范化向量等。
  6. 验证结果:程序的最后一步确保生成的矩阵是正交的,即其转置乘以自身等于单位矩阵。

你可以根据自己的需求调整参数、颜色或动画,以实现所需的效果。

运行结果:

 

 

 

 

 

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

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

相关文章

GESP C++三级样题卷

(满分:100 分 考试时间:90 分钟) 一、单选题(每题 2 分,共 30 分) 1.下列关于负数的原码、反码、补码的描述中,正确的是( ) A 原码和反码互为按位取反(符号位除外&…

[ComfyUI]Flux:太强了!任意扩图神器,小红书极致逼真风格出游打卡写实风

随着人工智能技术的不断发展,图像生成与反推技术已经成为了AI领域的一大热点。今天,我们就来为大家详细介绍一款由ComfyUI团队开发的超强图像反推工具——Flux,以及如何使用它实现任意扩图和极致逼真风格出游打卡写实风。 一、Flux&#xff…

k8s-集群部署1

k8s-集群部署1 一、基础环境准备二、docker环境准备三、k8s集群部署1.kubeadm创建集群2.使用kubeadm引导集群 总结 一、基础环境准备 首先,需要准备三个服务器实例,这里我使用了阿里云创建了三个实例,如果不想花钱,也可以在VM上创…

第十一章 缓存之更新/穿透/雪崩/击穿

目录 一、什么是缓存 二、缓存更新策略 2.1. 缓存主动更新策略 2.1.1. Cache Aside模式(主流)‌ 2.1.2. Read/Write Through模式‌ 2.1‌.3. Write Behind模式‌ 2.1.4. 总结 三、缓存穿透 四、缓存雪崩 五、缓存击穿 5.1. 互斥锁实现 5.1.1…

好用且不伤眼镜的超声波清洗机排名!谁才是清洁小能手?

对于经常佩戴眼镜的人来说,眼镜的日常清洁保养极为关键。传统清洁方式可能导致镜片刮花和残留污渍,鉴于此,眼镜专用的超声波清洗机应运而生,利用超声振动技术深入微细缝隙,彻底扫除污垢与油脂,保护镜片免受…

计算机编程入门先学什么最好?零基础入门到精通,收藏这篇就够了

看完其他知友的回答,我认为他们的观点过于局限,并没有真正切中问题的要害。 我们不妨换个角度,站在更高一层来看这个问题「计算机编程入门先学什么最好?」 计算机入门最应该学的是 Linux,而非任何的编程语言。 这篇文…

A_H_README_TO_RECOVER勒索恢复---惜分飞

有客户mysql数据库被黑(业务数据库被删除),创建了一个A_H_README_TO_RECOVER库 [rootwww.xifenfei.com ~]# mysql -uroot -pxxxxx Warning: Using a password on the command line interface can be insecure. Welcome to the MySQL monitor. Commands end with ; …

站岗放哨树形dp

前言&#xff1a;好久没有写树上dp了&#xff0c;这儿题目还是挺有意思的 题目地址 #include<bits/stdc.h> #include<iostream> using namespace std;//#define int long long int n; const int N (int)1e510; int e[N],ne[N],h[N],idx 0; int dp[2][N];void add…

【笔记】神领物流Day1.1.20权限管家

传智权限管家是一个通用的权限管理中台服务&#xff0c;在神领物流项目中&#xff0c;我们使用权限系统管理企业内部员工&#xff0c;比如&#xff1a;快递员、司机、管理员等。 在权限管家中可以管理用户&#xff0c;管理后台系统的菜单&#xff0c;以及角色的管理。 权限管家…

【百度文心智能体】想开发爆款智能体?来看看 万圣节之夜探秘者 智能体开发流程大揭秘

目录 前言 一. 创作灵感 二. 智能体中Prompt如何设计 2.1 头像 && 聊天背景 2.2 智能体简介 && 角色定位与目标 2.3 思考路径 && 个性化 2.4 开场白 && 自动追问 2.5 插件选择 三. 总结 前言 从2022年11月底ChatGPT …

JavaEE: 数据链路层的奇妙世界

文章目录 数据链路层以太网源地址和目的地址 类型数据认识 MTU 数据链路层 以太网 以太网的帧格式如下所示: 源地址和目的地址 源地址和目的地址是指网卡的硬件地址(也叫MAC地址). mac 地址和 IP 地址的区别: mac 地址使用6个字节表示,IP 地址4个字节表示. 一般一个网卡,在…

论文选题没思路?用这7个GPT提示词10分钟确定论文选题

选题是论文写作的第一步&#xff0c;也是至关重要的一步。毕业论文选题都是让大学生头疼的大事。没有灵感、方向不清、信息太多&#xff0c;常常让人无从下手。现在有了ChatGPT这样的AI写作辅助工具&#xff0c;它可以帮你快速生成丰富的选题思路&#xff0c;轻松解决选题难题。…

Anaconda创建环境

目录 前言 第一步&#xff1a;更改环境创建位置 第二步&#xff1a;安装环境 前言 在我们创建多个项目的时候&#xff0c;有时会安装的库版本冲突&#xff0c;所以最好是一个项目一个环境 第一步&#xff1a;更改环境创建位置 新安装Anaconda后&#xff0c;在创建环境时环…

洛谷每日一题(P1205 [USACO1.2] 方块转换 Transformations)矩阵变换

原题目链接&#xff1a; P1205 [USACO1.2] 方块转换 Transformations - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 原题目截图&#xff1a; 思路分析&#xff1a; 这题目还是比较简单&#xff0c;模拟一下旋转变化的过程&#xff0c;然后注意变换的规律就行了。 读取输入…

电脑提示msvcp140.dll丢失如何解决,马上教你6种解决方法

在使用电脑时&#xff0c;我们可能会遇到提示缺少msvcp140.dll的错误信息。这个提示意味着我们的电脑中缺少MSVCP140.dll这个文件&#xff0c;它是某些程序运行所必需的。如果我们遇到这个问题&#xff0c;应该如何解决呢&#xff1f;本文将详细解析如何解决msvcp140.dll丢失的…

C. Tree Pruning【Codeforces Round 975 (Div. 1)】

C. Tree Pruning (永远不知道为什么TLE直到把初始化的memset换成for循环 题意很简单&#xff0c;就是找到一个深度&#xff0c;使得删除最少的节点且所有的叶子节点都为这个深度。 从小到大遍历可能的深度i&#xff0c;容易知道所有 深度大于i的节点 和所有 子树最大深度小于i…

vue出现Component name “Politic“ should always be multi-word错误

效果 原因 组件名不能为单个单词&#xff0c;怕和html标签混淆 解决方法 1.选择多个单词区分 2.修改package.json里的rules规则&#xff0c;忽略文件命名校验

详细解释:前向传播、反向传播等

详细解释:前向传播、反向传播等 在机器学习和深度学习中,**前向传播(Forward Propagation)和反向传播(Backward Propagation)**是训练神经网络的两个核心过程。理解这两个概念对于掌握神经网络的工作原理、优化方法以及模型微调技术(如LoRA、P-tuning等)至关重要。以下…

YOLO11改进|注意力机制篇|引入ELA注意力机制

目录 一、【ELA】注意力机制1.1【ELA】注意力介绍1.2【ELA】核心代码 二、添加【ELA】注意力机制2.1STEP12.2STEP22.3STEP32.4STEP4 三、yaml文件与运行3.1yaml文件3.2运行成功截图 一、【ELA】注意力机制 1.1【ELA】注意力介绍 这篇论文的作者通过分析Coordinate Attention(C…

Python中的数据可视化:从入门到进阶

数据可视化是数据分析和科学计算中的重要环节&#xff0c;它通过图形化的方式呈现数据&#xff0c;使复杂的统计信息变得直观易懂。Python提供了多种强大的库来支持数据可视化&#xff0c;如Matplotlib、Seaborn、Plotly等。本文将从基础到进阶&#xff0c;详细介绍如何使用这些…