【不写for循环】玩玩行列

利用numpy的并行操作可以比纯用Python的list快很多,不仅如此,代码往往精简得多。

So, 这篇来讲讲进阶的广播和花哨索引操作,少写几个for循环()。

目录

一个二维的例题

一个三维的例题

解法一

解法二

更难的三维例题

解法一

解法二

独热编码

写法一

写法二

一个二维的例题

从一个简单的问题开始,现在有一个向量:

x = \left ( a,b,c \right )

弄出这个东西出来:

\begin{pmatrix} a+a &a+b &a+c \\ b+a & b+b &b+c \\ c+a&c+b &c+c \end{pmatrix}

这个很简单:

x = [1, 2, 3]
res = []
for i in x:for j in x:res.append(i + j)
res = torch.tensor(res).reshape(3, 3)
res# output
tensor([[2, 3, 4],[3, 4, 5],[4, 5, 6]])

以上内容是开玩笑的,下面开始认真起来。自然,这个很明显是个广播的送分题:

x = torch.tensor([1, 2, 3])
x + x.reshape(-1, 1)#output
tensor([[2, 3, 4],[3, 4, 5],[4, 5, 6]])

一个三维的例题

现在有一个向量:

x =\begin{pmatrix} a\\ b\\ c \end{pmatrix}

弄出这个东西出来:

\begin{pmatrix} a+a &a+b &a+c \\ b+a & b+b &b+c \\ c+a&c+b &c+c \end{pmatrix}

不过现在a b c都是长度为4的向量。x是一个(3, 4)的矩阵(还是说明一下,这里不表示分块矩阵),目标是一个(3, 3, 4)的张量。

解法一

这个在GAT里面里面很常见(把“+”换成“concat”就是图卷积注意力的核心步骤之一)。当时看了一大圈的zhihu和CSDN,都是这么写的:

先x.repeat(1,3),横着重复,维度是(3, 3*4):

(||表示两个向量拼接)

x_{1} = \begin{pmatrix} a||a||a\\ b||b||b\\ c||c||c \end{pmatrix}

然后x.reshape(3*3, -1), 维度变成(3*3, 4):

x_{1} = \begin{pmatrix} a\\ a\\ a\\ b\\ b\\ b\\ c\\ c\\ c \end{pmatrix}

另一个竖着重复,x.repeat(3,1),维度是(3*3, 4):

x_{2} = \begin{pmatrix} a\\ b\\ c\\ a\\ b\\ c\\ a\\ b\\ c \end{pmatrix}

然后相加reshape即可。

x = torch.tensor([[1, 1, 1, 1],[2, 2, 2, 2],[3, 3, 3, 3]])
(x.repeat(1, 3).reshape(3*3, 4) + x.repeat(3, 1)).reshape(3, 3, 4)#output
tensor([[[2, 2, 2, 2],[3, 3, 3, 3],[4, 4, 4, 4]],[[3, 3, 3, 3],[4, 4, 4, 4],[5, 5, 5, 5]],[[4, 4, 4, 4],[5, 5, 5, 5],[6, 6, 6, 6]]])

解法二

后来想了一下其实可以直接广播。

解法一虽然复杂一点,但是把题目里面的“+”改成“||”就只能用解法一了。

x = torch.tensor([[1, 1, 1, 1],[2, 2, 2, 2],[3, 3, 3, 3]])
x.unsqueeze(0) + x.unsqueeze(1)  # (1, 3, 4) + (3, 1, 4)#output
tensor([[[2, 2, 2, 2],[3, 3, 3, 3],[4, 4, 4, 4]],[[3, 3, 3, 3],[4, 4, 4, 4],[5, 5, 5, 5]],[[4, 4, 4, 4],[5, 5, 5, 5],[6, 6, 6, 6]]])

更难的三维例题

现在有一个向量:

x =\begin{pmatrix} a\\ b\\ c \end{pmatrix}

弄出这个东西出来:

\begin{pmatrix} a\cdot a &a\cdot b &a\cdot c \\ b\cdot a & b\cdot b &b\cdot c \\ c\cdot c&c\cdot b &c\cdot c \end{pmatrix}

不过现在a b c都是长度为4的向量。x是一个(3, 4)的矩阵(还是说明一下,这里不表示分块矩阵),两两做点积,目标是一个(3, 3)的张量。

先来一个错误示例:

x = torch.tensor([[1, 1, 1, 1],[2, 2, 2, 2],[3, 3, 3, 3]])
np.dot(x.unsqueeze(0), x.unsqueeze(1)), torch.dot(x.unsqueeze(0), x.unsqueeze(1))

两种做法都是错的,torch.dot只支持1D的向量。np,dot处理高维度的张量的逻辑很不同,这里可以

查阅资料,不细说了。

解法一

可以用numpy里面最玄学的函数之一——np.meshgrid

先看看这个函数是干嘛的:

x = torch.tensor([[1, 1, 1, 1],[2, 2, 2, 2],[3, 3, 3, 3]])
i, j = np.meshgrid(np.arange(x.shape[0]), np.arange(x.shape[1]), indexing='ij')
i, j# output
array([[0, 0, 0, 0],[1, 1, 1, 1],[2, 2, 2, 2]]array([[0, 1, 2, 3],[0, 1, 2, 3],[0, 1, 2, 3]])

np.arange(x.shape[0]) : array([0, 1, 2])

np.arange(x.shape[0]) : array([0, 1, 2, 3])

然后这个函数让前者往右重复,让后者往下重复,得到两个矩阵。然后细心看花哨索引和广播就知道:

x == x[i, j]  !!!

了解这个函数干嘛后,那下面我们进入正题。

x = torch.tensor([[1, 1, 1, 1],[2, 2, 2, 2],[3, 3, 3, 3]])
x1, x2 = x.unsqueeze(0), x.unsqueeze(1)  # (1, 3, 4) (3, 1, 4)
x1, x2 = torch.broadcast_tensors(x1, x2)  # (3, 3, 4) (3, 3, 4) 手动广播
i, j = np.meshgrid(np.arange(3), np.arange(3), indexing='ij')
torch.sum(x1[i, j, :] * x2[i, j, :], dim=-1)#output
tensor([[ 4,  8, 12],[ 8, 16, 24],[12, 24, 36]])

用花哨索引固定前两个维度不动,在第三个维度上相乘求和(就是点积)。搞定。

解法二

x = torch.tensor([[1, 1, 1, 1],[2, 2, 2, 2],[3, 3, 3, 3]])
x1, x2 = x.unsqueeze(0), x.unsqueeze(1)  # (1, 3, 4) (3, 1, 4)
torch.einsum('ijk,ijk->ij', x1, x2)  # 这个函数支持广播#output
tensor([[ 4,  8, 12],[ 8, 16, 24],[12, 24, 36]])

np.einsum的全称是Einstein summation convention,即爱因斯坦求和约定。这个约定允许我们通过一个简洁的字符串表达式来指定复杂的数组运算,包括点积、矩阵乘法、张量收缩等。

这里是一个简单的运用。

独热编码

原来利用广播可以写独热编码。

写法一

一般独热编码可以这么写

a = np.array([1, 2, 1, 0])
category = len(np.unique(a))
eye = np.eye(category)
eye, eye[a]#output
array([[1., 0., 0.],[0., 1., 0.],[0., 0., 1.]]array([[0., 1., 0.],[0., 0., 1.],[0., 1., 0.],[1., 0., 0.]]

eye是一个单位矩阵,a构成了一个花哨索引,每次取eye的一行,然后取4次。

十分简洁。缺点是a的每个值必须在[0,category-1]中。

写法二

a = np.array(['a', 'b', 'c', 'd', 'e', 'f'])
b = np.array(['d', 'e', 'f'])
b = b.reshape(-1, 1)  # (3, 1)
(a == b).astype(int)# output
array([[0, 0, 0, 1, 0, 0],[0, 0, 0, 0, 1, 0],[0, 0, 0, 0, 0, 1]]

支持各种类型的数据,而且还能应对b的某个元素不在a中的尴尬情况(此时一排都是0,因为一排都是不等于)。

有一个缺点是,在第四行时,Pycharm不知道这是一个a==b是一个布尔数组,在"astype"会画一个黄色,看着闹心(狗头)。

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

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

相关文章

《Java核心技术 卷I》用户界面中首选项API

首选项API 在桌面程序中,通常都会存储用户首选项,如用户最后处理的文件、窗口的最后位置等。 利用Properties类可以很容易的加载和保存程序的配置信息,但有以下缺点: 有些操作系统没有主目录概念,很难为匹配文件找到…

3步实现贪吃蛇

方法很简单,打开页面,复制,粘贴 一.整体思维架构 我们根据游戏的开始,运行,结束,将整个游戏划分成三个部分。在每个部分下面又划分出多个功能,接下来我们就根据模块一一实现功能。 二.Gamesta…

STL序列式容器之list

相较于vector的连续性空间&#xff0c;list相对比较复杂&#xff1b;list内部使用了双向环形链表的方式对数据进行存储&#xff1b;list在增加元素时&#xff0c;采用了精准的方式分配一片空间对数据及附加指针等信息进行存储&#xff1b; list节点定义如下 template<clas…

【论文模型复现】深度学习、地质流体识别、交叉学科融合?什么情况,让我们来看看

文献&#xff1a;蓝茜茜,张逸伦,康志宏.基于深度学习的复杂储层流体性质测井识别——以车排子油田某井区为例[J].科学技术与工程,2020,20(29):11923-11930. 本文目录 一、前言二、文献阅读-基于深度学习的复杂储层流体性质测井识别2.1 摘要2.2 当前研究不足2.3 本文创新2.4 论文…

(一)- DRM架构

一&#xff0c;DRM简介 linux内核中包含两类图形显示设备驱动框架&#xff1a; FB设备&#xff1a;Framebuffer图形显示框架; DRM&#xff1a;直接渲染管理器&#xff08;Direct Rendering Manager&#xff09;&#xff0c;是linux目前主流的图形显示框架&#xff1b; 1&am…

Java基础-Java中的常用类(上)

(创作不易&#xff0c;感谢有你&#xff0c;你的支持&#xff0c;就是我前行的最大动力&#xff0c;如果看完对你有帮助&#xff0c;请留下您的足迹&#xff09; 目录 String类 创建字符串 字符串长度 连接字符串 创建格式化字符串 String 方法 System类 常用方法 方…

Istio分布式链路监控搭建:Jaeger与Zipkin

分布式追踪定义 分布式追踪是一种用来跟踪分布式系统中请求的方法&#xff0c;它可以帮助用户更好地理解、控制和优化分布式系统。分布式追踪中用到了两个概念&#xff1a;TraceID 和 SpanID。 TraceID 是一个全局唯一的 ID&#xff0c;用来标识一个请求的追踪信息。一个请求…

探索Python网络请求新纪元:httpx库的崛起

文章目录 **探索Python网络请求新纪元&#xff1a;httpx库的崛起**第一部分&#xff1a;背景介绍第二部分&#xff1a;httpx库是什么&#xff1f;第三部分&#xff1a;如何安装httpx库&#xff1f;第四部分&#xff1a;简单的库函数使用方法1. 发送GET请求2. 发送POST请求3. 超…

vue使用List.reduce实现统计

需要对集合的某些元素的值进行计算时&#xff0c;可以在计算属性中使用forEach方法 1.语法&#xff1a;集合.reduce ( ( 定义阶段性累加后的结果 , 定义遍历的每一项 ) > 定义每一项求和逻辑执行后的返回结果 , 定义起始值 ) 2、简单使用场景&#xff1a;例如下面…

层归一化和批归一化

层归一化是针对某一样本的所有特征&#xff0c;批归一化是针对所有样本的某一特征。 计算公式&#xff1a;&#xff08;当前值 - 均值&#xff09;/ 标准差。 作用&#xff1a;缓解梯度消失和梯度爆炸的问题&#xff0c;并提高网络的泛化性能。 为什么Transform和BERT中使用层归…

vueRouter路由切换时实现页面子元素动画效果, 左右两侧滑入滑出效果

说明 vue路由切换时&#xff0c;当前页面左侧和右侧容器分别从两侧滑出&#xff0c;新页面左右分别从两侧滑入 效果展示 路由切换-滑入滑出效果 难点和踩坑 现路由和新路由始终存在一个页面根容器&#xff0c;通过<transition>组件&#xff0c;效果只能对页面根容器有效…

docker 安装之 windows安装

文章目录 1: 在Windows安装Docker报19044版本错误的时候&#xff0c;请大家下载4.24.1之前的版本&#xff08;含4.24.1&#xff09;2: Desktop-WSL kernel version too low3: docker-compose 安装 (v2.21.0)4: 配置镜像源 1: 在Windows安装Docker报19044版本错误的时候&#xf…

【GPTs】Gif-PT:DALL·E制作创意动图与精灵动画

博客主页&#xff1a; [小ᶻZ࿆] 本文专栏: AIGC | GPTs应用实例 文章目录 &#x1f4af;GPTs指令&#x1f4af;前言&#x1f4af;Gif-PT主要功能适用场景优点缺点 &#x1f4af;小结 &#x1f4af;GPTs指令 中文翻译&#xff1a; 使用Dalle生成用户请求的精灵图动画&#…

FastGPT部署通义千问Qwen和智谱glm模型|OneAPI配置免费的第三方API

继这篇博客之后 从零开始FastGPT本地部署|Windows 有同学问&#xff0c;不想在多个平台申请API-Key&#xff0c;不好管理且要付费&#xff0c;有木有白嫖方案呀&#xff1f; 答&#xff1a;有啊。用硅基流动。 注册方法看这篇 【1024送福利】硅基流动送2000万token啦&#xff0…

JsonCpp

参考文档&#xff1a;https://zhuanlan.zhihu.com/p/374319504 json是一种轻量级数据交换格式&#xff0c;易于阅读和编写&#xff0c;也易于机器解析和生成。使用json格式可以方便地在各个系统之间传递数据。在c中&#xff0c;有许多开源的json库可以进行json的处理。比如&am…

7.揭秘C语言输入输出内幕:printf与scanf的深度剖析

揭秘C语言输入输出内幕&#xff1a;printf与scanf的深度剖析 C语言往期系列文章目录 往期回顾&#xff1a; VS 2022 社区版C语言的安装教程&#xff0c;不要再卡在下载0B/s啦C语言入门&#xff1a;解锁基础概念&#xff0c;动手实现首个C程序C语言概念之旅&#xff1a;解锁关…

XXL-JOB相关面试题

分布式任务调度-xxl-job 任务量大&#xff0c;分片执行 定义cron表达式灵活 定时任务失败了&#xff0c;重试和统计 xxl-job路由策略有哪些&#xff1f; 轮询 故障转移 分片广播:**广播触发对应的集群中所有机器执行一次任务,同时系统自动传递分片参数,**可以根据分片参数开发…

华东师范大学数学分析第五版PDF习题答案上册及下册

“数学分析”是数学专业最重要的一门基础课程&#xff0c;也是报考数学类专业硕士研究生的专业考试科目。为了帮助、指导广大读者学好这门课程&#xff0c;编者编写了与华东师范大学数学科学学院主编的《数学分析》(第五版)配套的辅导用书&#xff0c;以帮助读者加深对基本概念…

MATLAB实现GARCH(广义自回归条件异方差)模型计算VaR(Value at Risk)

MATLAB实现GARCH(广义自回归条件异方差)模型计算VaR(Value at Risk) 1.计算模型介绍 使用GARCH&#xff08;广义自回归条件异方差&#xff09;模型计算VaR&#xff08;风险价值&#xff09;时&#xff0c;方差法是一个常用的方法。GARCH模型能够捕捉到金融时间序列数据中的波…

基于YOLOv8深度学习的智慧课堂学生专注度检测系统(PyQt5界面+数据集+训练代码)

本研究提出了一种基于YOLOv8深度学习的智慧课堂学生专注度检测系统&#xff0c;旨在实现对课堂中学生专注度的实时分析与评估。随着智慧教育的快速发展&#xff0c;学生的课堂表现和专注度成为评估学习效果的重要因素之一。然而&#xff0c;传统的专注度评估方法往往依赖于主观…