TensorFlow2.0(二):数学运算

1 基本运算:加(+)、减(-)、点乘(*)、除(/)、地板除法(//)、取余(%)

基本运算中所有实例都以下面的张量a、b为例进行:

>>> a = tf.random.uniform([2, 3], minval=1, maxval=6,dtype=tf.int32)
>>> b = tf.random.uniform([2, 3], minval=1, maxval=6,dtype=tf.int32)
>>> a
<tf.Tensor: id=18, shape=(2, 3), dtype=int32, numpy=
array([[2, 1, 4],
[1, 2, 2]])>
>>> b
<tf.Tensor: id=22, shape=(2, 3), dtype=int32, numpy=
array([[4, 2, 4],
[1, 5, 2]])>

(1)加(+)

>>> tf.add(a,b)
<tf.Tensor: id=25, shape=(2, 3), dtype=int32, numpy=
array([[6, 3, 8],
[2, 7, 4]])>
>>> a + b
<tf.Tensor: id=27, shape=(2, 3), dtype=int32, numpy=
array([[6, 3, 8],
[2, 7, 4]])>

(2)减(-)

>>> tf.subtract(a,b)
<tf.Tensor: id=29, shape=(2, 3), dtype=int32, numpy=
array([[-2, -1, 0],
[ 0, -3, 0]])>
>>> a - b
<tf.Tensor: id=31, shape=(2, 3), dtype=int32, numpy=
array([[-2, -1, 0],
[ 0, -3, 0]])>

(3)乘法(*)

>>> tf.multiply(a,b)
<tf.Tensor: id=33, shape=(2, 3), dtype=int32, numpy=
array([[ 8, 2, 16],
[ 1, 10, 4]])>
>>> a * b
<tf.Tensor: id=35, shape=(2, 3), dtype=int32, numpy=
array([[ 8, 2, 16],
[ 1, 10, 4]])>

(4)除法(/)

>>> tf.divide(a,b)
<tf.Tensor: id=39, shape=(2, 3), dtype=float64, numpy=
array([[0.5, 0.5, 1. ],
[1. , 0.4, 1. ]])>
>>> a/b
<tf.Tensor: id=43, shape=(2, 3), dtype=float64, numpy=
array([[0.5, 0.5, 1. ],
[1. , 0.4, 1. ]])>

(5)地板除法(//)

>>> tf.floor_div(a,b)
<tf.Tensor: id=47, shape=(2, 3), dtype=int32, numpy=
array([[0, 0, 1],
[1, 0, 1]])>
>>> a//b
<tf.Tensor: id=49, shape=(2, 3), dtype=int32, numpy=
array([[0, 0, 1],
[1, 0, 1]])>

(6)取余(%)

>>> tf.mod(b,a)
<tf.Tensor: id=65, shape=(2, 3), dtype=int32, numpy=
array([[0, 0, 0],
[0, 1, 0]])>
>>> b % a
<tf.Tensor: id=67, shape=(2, 3), dtype=int32, numpy=
array([[0, 0, 0],
[0, 1, 0]])>

可以看出,对于基本运算加(+)、减(-)、点乘(*)、除(/)、地板除法(//)、取余(%),都是对应元素进行运算。

2 指数运算、开方、对数运算

(1)对数运算

TensorFlow提供tf.math.log()方法来求对数,当然,求的是以自然常数$e$为底的对数:

>>> e = 2.71828183
>>> a = tf.constant([e, e*e, e*e*e])
>>> tf.math.log(a)
<tf.Tensor: id=96, shape=(3,), dtype=float32, numpy=array([0.99999994, 2.        , 3.        ], dtype=float32)>

>>> c = tf.fill([2,2],1.)
>>> tf.math.log(c)
<tf.Tensor: id=72, shape=(2, 2), dtype=float32, numpy=
array([[0., 0.],
[0., 0.]], dtype=float32)>

注意:TensorFlow中没有提供函数实现以其他数值为底的对数运算,例如$lo{g_2}8$, $lg100$。不过,我们可以通过其他方式来求取,记得下面这个高中时学过的公式吗:

$$lo{g_a}b = \frac{{lo{g_c}b}}{{lo{g_c}a}}$$

所以有:

>>> f = tf.constant([[1., 9.], [16., 100.]])
>>> g = tf.constant([[2., 3.], [2., 10.]])
>>> tf.math.log(f) / tf.math.log(g)
<tf.Tensor: id=92, shape=(2, 2), dtype=float32, numpy=
array([[0., 2.],
[4., 2.]], dtype=float32)>

(2)指数运算

>>> g = tf.constant([[2, 3], [2, 10]])
>>> tf.pow(g, 2)
<tf.Tensor: id=104, shape=(2, 2), dtype=int32, numpy=
array([[ 4, 9],
[ 4, 100]])>

也可以直接通过运算符来完成:

>>> g ** 2
<tf.Tensor: id=100, shape=(2, 2), dtype=int32, numpy=
array([[ 4, 9],
[ 4, 100]])>

(3)开方

>>> f = tf.constant([[1., 9.], [16., 100.]])
>>> tf.sqrt(f)
<tf.Tensor: id=108, shape=(2, 2), dtype=float32, numpy=
array([[ 1., 3.],
[ 4., 10.]], dtype=float32)>

自然常数$e$的指数运算:

>>> d = tf.constant([[1.,2.],[3.,4.]])
>>> tf.exp(d)
<tf.Tensor: id=76, shape=(2, 2), dtype=float32, numpy=
array([[ 2.7182817, 7.389056 ],
[20.085537 , 54.598152 ]], dtype=float32)>

注意:对数运算函数log()与指数运算函数在不同的模块中。

在我看来,上面提到的指数运算与对数运算不在通知模块以及没有提供以其他自然数为底的对数运算,应该应该是TensorFlow中的遗留问题,希望能够在正式版中得到修正。

3 矩阵相乘

注意,矩阵相乘与上面的矩阵点乘可不一样,这里的矩阵相乘是线性代数中的矩阵乘法,通过TensorFlow提供的matmul()方法实现:

>>> import tensorflow as tf
>>> import numpy as np
>>> a = tf.constant(np.arange(6),shape=(2,3))
>>> b = tf.constant(np.arange(6),shape=(3,2))
>>> a
<tf.Tensor: id=5, shape=(2, 3), dtype=int32, numpy=
array([[0, 1, 2],
[3, 4, 5]])>
>>> b
<tf.Tensor: id=8, shape=(3, 2), dtype=int32, numpy=
array([[0, 1],
[2, 3],
[4, 5]])>
>>> tf.matmul(a,b)
<tf.Tensor: id=9, shape=(2, 2), dtype=int32, numpy=
array([[10, 13],
[28, 40]])>

矩阵相乘也可以通过符号来操作进行,用“@”表示:

>>> [email protected]
<tf.Tensor: id=13, shape=(2, 2), dtype=int32, numpy=
array([[10, 13],
[28, 40]])>

这里的张量a和b都是二维的,但在实际应用中,数据往往高于二维,这时候怎么应算呢?

>>> a = tf.constant(np.arange(12),shape=(2,2,3))
>>> b = tf.constant(np.arange(12),shape=(2,3,2))
>>> a
<tf.Tensor: id=17, shape=(2, 2, 3), dtype=int32, numpy=
array([[[ 0, 1, 2],
[ 3, 4, 5]],

[[ 6, 7, 8],
[ 9, 10, 11]]])>
>>> b
<tf.Tensor: id=20, shape=(2, 3, 2), dtype=int32, numpy=
array([[[ 0, 1],
[ 2, 3],
[ 4, 5]],

[[ 6, 7],
[ 8, 9],
[10, 11]]])>
>>> [email protected]
<tf.Tensor: id=23, shape=(2, 2, 2), dtype=int32, numpy=
array([[[ 10, 13],
[ 28, 40]],

[[172, 193],
[244, 274]]])>

可以看到,当高于二维的张量进行矩阵相乘时,最终的实现还是二维矩阵相乘,只不过分成了多个二维矩阵,四维张量也是一样的:

>>> a = tf.constant(np.arange(24),shape=(2,2,2,3))
>>> b = tf.constant(np.arange(24),shape=(2,2,3,2))
>>> [email protected]
<tf.Tensor: id=42, shape=(2, 2, 2, 2), dtype=int32, numpy=
array([[[[ 10, 13],
[ 28, 40]],

[[ 172, 193],
[ 244, 274]]],

[[[ 550, 589],
[ 676, 724]],

[[1144, 1201],
[1324, 1390]]]])>

4 Broadcasting机制

上面的所有实例中所用到的张量都是在维度数和形状相同情况下进行,那么,当两个张量维度数或者形状不一样时能不能进行运算呢?

>>> a = tf.constant([1,2,3])
>>> b = tf.constant(np.arange(12),shape=(2,2,3))
>>> b
<tf.Tensor: id=86, shape=(2, 2, 3), dtype=int32, numpy=
array([[[ 0, 1, 2],
[ 3, 4, 5]],

[[ 6, 7, 8],
[ 9, 10, 11]]])>
>>> a+b
<tf.Tensor: id=88, shape=(2, 2, 3), dtype=int32, numpy=
array([[[ 1, 3, 5],
[ 4, 6, 8]],

[[ 7, 9, 11],
[10, 12, 14]]])>
>>> a*b
<tf.Tensor: id=90, shape=(2, 2, 3), dtype=int32, numpy=
array([[[ 0, 2, 6],
[ 3, 8, 15]],

[[ 6, 14, 24],
[ 9, 20, 33]]])>

可以看到,一个一维的张量与一个三维张量进行运算是完全没有问题的,从运算结果上可以看出,相当于是三维张量中的每一行数据与张量a进行运算,为什么可以这样运输呢?这就得益于TensorFlow中的Broadcasting机制。

Broadcasting机制解除了只能维度数和形状相同的张量才能进行运算的限制,当两个数组进行算术运算时,TensorFlow的Broadcasting机制首先对维度较低的张量形状数组填充1,从后向前,逐元素比较两个数组的形状,当逐个比较的元素值(注意,这个元素值是指描述张量形状数组的值,不是张量的值)满足以下条件时,认为满足 Broadcasting 的条件:

(1)相等

(2)其中一个张量形状数组元素值为1。

当不满足时进行运算则会抛出 ValueError: frames are not aligne 异常。算术运算的结果的形状的每一元素,是两个数组形状逐元素比较时的最大值。

回到上面张量a与b相乘的例子,a的形状是(3,),b的形状是(2, 2, 3),在Broadcasting机制工作时,首先比较维度数,因为a的维度为1,小于b的维度3,所以填充1,a的形状就变成了(1,1,3),然后从最后端的形状数组元素依次往前比较,先是就是3与3比,结果是相等,接着1与2相比,因为其中一个为1,所以a的形状变成了(1,2,3),继续1与2比较,因为其中一个为1,所以a的形状变成了(2,2,3),a中的数据每一行都填充a原来的数据,也就是[1,2,3],然后在与b进行运算。

当然,在TensorFlow的Broadcasting机制运行过程中,上述操作只是理论的,并不会真正的将a的形状变成(2,2,3,),更不会将每一行填充[1,2,3],只是虚拟进行操作,真正计算时,依旧是使用原来的张量a。这么做的好处是运算效率更高,也更节省内存。

再举一些例子加深理解:

A (2d array): 5 x 4
B (1d array): 1
Result (2d array): 5 x 4

A (2d array): 5 x 4
B (1d array): 4
Result (2d array): 5 x 4

A (3d array): 15 x 3 x 5
B (3d array): 15 x 1 x 5
Result (3d array): 15 x 3 x 5

A (3d array): 15 x 3 x 5
B (2d array): 3 x 5
Result (3d array): 15 x 3 x 5

A (3d array): 15 x 3 x 5
B (2d array): 3 x 1
Result (3d array): 15 x 3 x 5

一些反例(不满足 Broadcasting 规则 ):

A (1d array): 3
B (1d array): 4

A (2d array): 2 x 1
B (3d array): 8 x 4 x 3

参考

https://lufficc.com/blog/tensorflow-and-numpy-broadcasting

原文地址:https://www.cnblogs.com/chenhuabin/p/11594239.html

时间: 2024-10-19 00:17:45

TensorFlow2.0(二):数学运算的相关文章

吴裕雄--天生自然TensorFlow2教程:数学运算

import tensorflow as tf b = tf.fill([2, 2], 2.) a = tf.ones([2, 2]) a+b a-b a*b a/b b // a b % a tf.math.log(a) # 只有以e为底的log tf.exp(a) tf.math.log(8.)/tf.math.log(2.) # 以2为底 tf.math.log(100.)/tf.math.log(10.) # 以10为底 tf.pow(b, 3) b**3 tf.sqrt(b) [ema

Shell脚本(二)数学运算

直接上代码. #!/bin/bash no1=4 no2=5 echo "using let ..." let result=no1+no2 echo "result is: ${result}" let result++ echo "result after 1 increment is: ${result}" let result+=6 echo "result after 6 increment is: ${result}&quo

JAVA之旅(二十三)——System,RunTime,Date,Calendar,Math的数学运算

JAVA之旅(二十三)--System,RunTime,Date,Calendar,Math的数学运算 map实在是太难写了,整理得我都晕都转向了,以后看来需要开一个专题来讲这个了,现在我们来时来学习一些新的小东西吧 一.System 翻译过来系统的意思,系统类,里面的方法都是静态的,可以直接调用 我们来演示一下吧,先从获取系统信息开始: package com.lgl.hellojava; import java.util.Properties; public class HelloJJAVA

记录二:tensorflow2.0写MNIST手写体

最近学习神经网络,tensorflow,看了好多视频,查找了好多资料,感觉东西都没有融入自己的思维中.今天用tensorflow2.0写了一个MNIST手写体的版本,记录下学习的过程. 复现手写体识别的基本步骤:准备数据,处理数据,搭建模型,迭代训练模型,使用模型. 一.全连接模型 1.导入数据集(此次编写运行均在notebook) 先引入所需模块,在用tf.keras下载数据 2.分析图片的大小 1)用shape查看数量大小:2)通过指定[0][1]来查看具体图像尺寸,lable存储的是ima

linux学习:特殊符号,数学运算,图像与数组与部分终端命令用法整理

一:特殊符号用法整理 算术比较-eq 等于-ne 不等于-gt 大于-lt 小于-ge 大于或等于-le 小于或等于-a 逻辑与 and &&-o 逻辑或 or ||[ $var -eq 0 ]    #当$var等于0时,返回真[ $var -ne 0 ]    #当$var为非0时,返回真[ $var1 -ne 0 -a $var2 -gt 2 ][ $var1 -ne 0 -o $var2 -gt 2 ] 字符串比较[[ $str1 = $str2 ]]     #当str1等于st

unity Mathf 数学运算汇总

在使用unity 做游戏的过程中难免会遇到这样那样的数学运算,比如简单的正弦,余弦等.其实,在c#的Mathf 函数中 还有很多方便我们开发使用的 数学函数.在此,分享下比较全面的Mathf解析(由网上收集),方便大家参考 使用. Mathf 数学运算 Mathf.Abs绝对值 计算并返回指定参数 f 绝对值. Mathf.Acos反余弦 static function Acos (f : float) : float 以弧度为单位计算并返回参数 f 中指定的数字的反余弦值. Mathf.App

MathExamV2.0四则混合运算计算题生成器

MathExamV2.0四则混合运算计算题生成器----211606360 丁培晖 211606343 杨宇潇 一.预估与实际 PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟) Planning 计划 ? Estimate ? 估计这个任务需要多少时间 60 100 Development 开发 ? Analysis ? 需求分析 (包括学习新技术) 360 440 ? Design Spec ? 生成设计文档 20 20 ? D

Linux编程 22 shell编程(输出和输入重定向,管道,数学运算命令,退出脚本状态码)

1. 输出重定向 最基本的重定向是将命令的输出发送到一个文件中.在bash shell中用大于号(>) ,格式如下:command > inputfile.例如:将date命令的输出内容,保存到指定的输出文件中. 如果文件已存在,重定向操作符会用新的文件数据覆盖已有文件.这种情况下可以用双大于号(>>) 来追加数据.如下图所示: 2. 输入重定向 输入重定向和输出重定向正好相反.输入重定向是将文件的内容重定向到命令,而非将命令的输出重定向到文件. 输入重定向符号是小于号(<)

【tensorflow2.0】张量的结构操作

张量的操作主要包括张量的结构操作和张量的数学运算. 张量结构操作诸如:张量创建,索引切片,维度变换,合并分割. 张量数学运算主要有:标量运算,向量运算,矩阵运算.另外我们会介绍张量运算的广播机制. 本篇我们介绍张量的结构操作. 一,创建张量 张量创建的许多方法和numpy中创建array的方法很像. import tensorflow as tf import numpy as np a = tf.constant([1,2,3],dtype = tf.float32) tf.print(a)

变量/数学运算/子进程/基本操作之类

蛇棒,我总是会忘记蛇棒的写法,记性是越来越差了 #!/bin/bash #!/usr/bin/env bash shell也是一种弱数据类型的语言,申明变量也就是变量名称=变量值,当然shell中所有的变量默认都是字符串 variable_1=1; 使用的话,变量名之前加$符号就可以直接使用了. echo $variable_1; 当需要对shell中的变量进行数学运算的时候,因为所有的变量都是字符串,所以需要借助命令方式才可以进行数学运算,整型运算使用let $[[]] () var_1=1;