NVIDIA 初创加速计划,免费加速您的创业启动 了解详情
写点什么

深度学习入门(三):多维数组的运算

  • 2020-03-29
  • 本文字数:4023 字

    阅读完需:约 13 分钟

深度学习入门(三):多维数组的运算

编者按:本文节选自图灵程序设计丛书 《深度学习入门》一书中的部分章节。


如果掌握了 NumPy 多维数组的运算,就可以高效地实现神经网络。因此,本节将介绍 NumPy 多维数组的运算,然后再进行神经网络的实现。

多维数组

简单地讲,多维数组就是“数字的集合”,数字排成一列的集合、排成长方形的集合、排成三维状或者(更加一般化的) 维状的集合都称为多维数组。下面我们就用 NumPy 来生成多维数组,先从前面介绍过的一维数组开始。


>>> <b>import numpy as np</b>>>> <b>A = np.array([1, 2, 3, 4])</b>>>> <b>print(A)</b>[1 2 3 4]>>> <b>np.ndim(A)</b>1>>> <b>A.shape</b>## 4,>>> <b>A.shape[0]</b>4
复制代码


如上所示,数组的维数可以通过 np.dim() 函数获得。此外,数组的形状可以通过实例变量 shape 获得。在上面的例子中,A 是一维数组,由 4 个元素构成。注意,这里的 A.shape 的结果是个元组(tuple)。这是因为一维数组的情况下也要返回和多维数组的情况下一致的结果。例如,二维数组时返回的是元组 (4,3),三维数组时返回的是元组 (4,3,2),因此一维数组时也同样以元组的形式返回结果。下面我们来生成一个二维数组。



>>> <b>B = np.array([[1,2], [3,4], [5,6]])</b>>>> <b>print(B)</b>[[1 2] [3 4] [5 6]]>>> <b>np.ndim(B)</b>2>>> <b>B.shape</b>## 3, 2
复制代码


这里生成了一个 3 × 2 的数组 B。3 × 2 的数组表示第一个维度有 3 个元素,第二个维度有 2 个元素。另外,第一个维度对应第 0 维,第二个维度对应第 1 维(Python 的索引从 0 开始)。二维数组也称为 矩阵 (matrix)。如图 1 所示,数组的横向排列称为 (row),纵向排列称为 (column)。



图 1 横向排列称为行,纵向排列称为列

矩阵乘法

下面,我们来介绍矩阵(二维数组)的乘积。比如 2 × 2 的矩阵,其乘积可以像图 2 这样进行计算(按图中顺序进行计算是规定好了的)。



图 2 矩阵的乘积的计算方法


如本例所示,矩阵的乘积是通过左边矩阵的行(横向)和右边矩阵的列(纵向)以对应元素的方式相乘后再求和而得到的。并且,运算的结果保存为新的多维数组的元素。比如, 的第 1 行和 的第 1 列的乘积结果是新数组的第 1 行第 1 列的元素, 的第 2 行和 的第 1 列的结果是新数组的第 2 行第 1 列的元素。另外,在本书的数学标记中,矩阵将用黑斜体表示(比如,矩阵 ),以区别于单个元素的标量(比如,)。这个运算在 Python 中可以用如下代码实现。



>>> <b>A = np.array([[1,2], [3,4]])</b>>>> <b>A.shape</b>## 2, 2>>> <b>B = np.array([[5,6], [7,8]])</b>>>> <b>B.shape</b>## 2, 2>>> <b>np.dot(A, B)</b>array([[19, 22], [43, 50]])
复制代码


这里, 都是 2 × 2 的矩阵,它们的乘积可以通过 NumPy 的 np.dot() 函数计算(乘积也称为点积)。np.dot() 接收两个 NumPy 数组作为参数,并返回数组的乘积。这里要注意的是,np.dot(A, B)np.dot(B, A) 的值可能不一样。和一般的运算(+* 等)不同,矩阵的乘积运算中,操作数(AB)的顺序不同,结果也会不同。


这里介绍的是计算 2 × 2 形状的矩阵的乘积的例子,其他形状的矩阵的乘积也可以用相同的方法来计算。比如,2 × 3 的矩阵和 3 × 2 的矩阵的乘积可按如下形式用 Python 来实现。



>>> <b>A = np.array([[1,2,3], [4,5,6]])</b>>>> <b>A.shape</b>## 2, 3>>> <b>B = np.array([[1,2], [3,4], [5,6]])</b>>>> <b>B.shape</b>## 3, 2>>> <b>np.dot(A, B)</b>array([[22, 28], [49, 64]])
复制代码


2 × 3 的矩阵 和 3 × 2 的矩阵 的乘积可按以上方式实现。这里需要注意的是矩阵的形状(shape)。具体地讲,矩阵 的第 1 维的元素个数(列数)必须和矩阵 的第 0 维的元素个数(行数)相等。在上面的例子中,矩阵 的形状是 2 × 3,矩阵 的形状是 3 × 2,矩阵 的第 1 维的元素个数(3)和矩阵 的第 0 维的元素个数(3)相等。如果这两个值不相等,则无法计算矩阵的乘积。比如,如果用 Python 计算 2 × 3 的矩阵 和 2 × 2 的矩阵 的乘积,则会输出如下错误。



>>> <b>C = np.array([[1,2], [3,4]])</b>>>> <b>C.shape</b>## 2, 2>>> <b>A.shape</b>## 2, 3>>> <b>np.dot(A, C)</b>Traceback (most recent call last): File "<stdin>", line 1, in <module>ValueError: shapes (2,3) and (2,2) not aligned: 3 (dim 1) != 2 (dim 0)
复制代码


这个错误的意思是,矩阵 的第 1 维和矩阵 的第 0 维的元素个数不一致(维度的索引从 0 开始)。也就是说,在多维数组的乘积运算中,必须使两个矩阵中的对应维度的元素个数一致,这一点很重要。我们通过图 3 再来确认一下。



图 3 在矩阵的乘积运算中,对应维度的元素个数要保持一致


图 3 中,3 × 2 的矩阵 和 2 × 4 的矩阵 的乘积运算生成了 3 × 4 的矩阵 。如图所示,矩阵 和矩阵 的对应维度的元素个数必须保持一致。此外,还有一点很重要,就是运算结果的矩阵 的形状是由矩阵 的行数和矩阵 的列数构成的。


另外,当 是二维矩阵、 是一维数组时,如图 4 所示,对应维度的元素个数要保持一致的原则依然成立。


可按如下方式用 Python 实现图 4 的例子。



>>> <b>A = np.array([[1,2], [3, 4], [5,6]])</b>>>> <b>A.shape</b>## 3, 2>>> <b>B = np.array([7,8])</b>>>> <b>B.shape</b>## 2,>>> np.dot(A, B)array([23, 53, 83])
复制代码



图 4  是二维矩阵、 是一维数组时,也要保持对应维度的元素个数一致

神经网络的内积

下面我们使用 NumPy 矩阵来实现神经网络。这里我们以图 5 中的简单神经网络为对象。这个神经网络省略了偏置和激活函数,只有权重。



图 5 通过矩阵的乘积进行神经网络的运算


实现该神经网络时,要注意 的形状,特别是 的对应维度的元素个数是否一致,这一点很重要。



>>> <b>X = np.array([1, 2])</b>>>> <b>X.shape</b>## 2,>>> <b>W = np.array([[1, 3, 5], [2, 4, 6]])</b>>>> <b>print(W)</b>[[1 3 5] [2 4 6]]>>> <b>W.shape</b>## 2, 3>>> <b>Y = np.dot(X, W)</b>>>> <b>print(Y)</b>[ 5 11 17]
复制代码


如上所示,使用 np.dot(多维数组的点积),可以一次性计算出 的结果。这意味着,即便 的元素个数为 1001000,也可以通过一次运算就计算出结果!如果不使用 np.dot,就必须单独计算 的每一个元素(或者说必须使用 for 语句),非常麻烦。因此,通过矩阵的乘积一次性完成计算的技巧,在实现的层面上可以说是非常重要的。


图书简介https://www.ituring.com.cn/book/1921



相关阅读


深度学习入门(一):神经网络


深度学习入门(二):激活函数


公众号推荐:

跳进 AI 的奇妙世界,一起探索未来工作的新风貌!想要深入了解 AI 如何成为产业创新的新引擎?好奇哪些城市正成为 AI 人才的新磁场?《中国生成式 AI 开发者洞察 2024》由 InfoQ 研究中心精心打造,为你深度解锁生成式 AI 领域的最新开发者动态。无论你是资深研发者,还是对生成式 AI 充满好奇的新手,这份报告都是你不可错过的知识宝典。欢迎大家扫码关注「AI前线」公众号,回复「开发者洞察」领取。

2020-03-29 19:251495

评论

发布
暂无评论
发现更多内容

科普:Java 后端开发常用的 10 种第三方服务

沉默王二

Java 后端 第三方服务

这13道面试题,哪怕背你也要背过来。别说我没提醒你

小Q

Java 源码 架构 面试 多线程

字节跳动半夜给员工发钱,全员沸腾了

程序员生活志

字节跳动 职场 薪资

USDT支付通道搭建,USDT承兑商跑分系统

云小课 |选定合适的证书,做“有证”的合规域名

华为云开发者联盟

证书 课程练习 ssl

合约跟单模式系统开发,交易所合约跟单源码

13530558032

话题讨论 | 程序员们来说一说,你们从编程开始到现在共使用过多少种语言?

InfoQ写作社区官方

写作平台 话题讨论 语言

大厂面试爱问的「调度算法」,20 张图一举拿下

小林coding

算法 操作系统 内存 进程

oeasy教您玩转linux010210管理应用aptitude

o

区块链数字钱包开发,数字钱包app

13530558032

从零开始搭建完整的电影全栈系统(四)——restfulApi用户的认证授权及用户注册

刘强西

RESTful API yii

大项目写代码写到晕头转向?敏捷多项目框架解君愁

Philips

敏捷开发 程序设计 软件架构

多线程与高并发之锁

彭阿三

多线程 多线程与高并发

LiteOS间歇计算技术:IOT终端真正感受“电量自由”

华为云开发者联盟

物联网 LiteOS

如何利用Chrome DevTools优化网页性能

熊斌

学习

Pulsar Flink Connector 2.5.0 正式发布

Apache Pulsar

flink 开源 flink 消费 kafak Apache Pulsar

拥抱K8S系列-06-K8S如何解决docker部署的问题

张无忌

Docker Kubernetes 运维 service

滴滴AR实景导航背后的技术

滴滴技术

人工智能 滴滴技术 实景导航 地图与公交事业群分享月

区块链支付通道系统搭建,USDT跑分承兑商系统

Flink SQL 1.11 新功能与最佳实践

Apache Flink

flink

GaussDB(DWS)应用实战:对被视图引用的表进行DDL操作

华为云开发者联盟

数据库 dll postgre

编程的修养

紫枫

读书笔记

探路人与解题者:腾讯数字生态大会上AI语音助手+X的无限可能

脑极体

[翻译]Go Code Review Comments

卓丁

我四面字节跳动,拿下1-2级offer,太感谢这份“神仙级面试真经pdf”

编程 面试 计算机网络 架构师

熟悉又陌生的 k8s 字段:finalizers

郭旭东

Kubernetes

超酷! Atlas给黑白视频“上色”

华为云开发者联盟

视频 Atlas

USDT承兑支付系统,区块链跨境支付源码

13530558032

为了面个好公司!拼了!3.5W字的Java面试题整理(答案+学习路线)上!

Java架构师迁哥

年薪150万的阿里大佬工资全部上交!家务全包!却被老婆嘲讽嫌弃!网友:你老婆外面有人!

程序员生活志

互联网 职场 大厂 薪资

数字货币交易所开发方案,交易所源码

13530558032

深度学习入门(三):多维数组的运算_AI&大模型_斋藤康毅_InfoQ精选文章