TensorFlow核心概念之Tensor(4):张量运算

  TensorFlow中关于张量的运算主要有:数学运算,矢量运算及矩阵运算,另外在实际的张量运算过程中,支也支持与numpy的广播特性,不同维度的张量之间往往存在这低维张量向高维张量进行广播的现象,这也称之为张量的广播机制。本文主要从数学运算、矢量运算、矩阵运算三个方面介绍张量运算相关的内容,最后我们在大致了解以下张量的广播机制。

一、数学运算

  加减乘除、乘方开方、三角函数,指数对数以及逻辑运算等都是TensorFlow中比较常见的数学运算函数,TensorFlow提供了tf.math包来实现这些数学运算,另外大部分数学运算还可以通过运算符重载的方式来实现 。这里我们简单示例几种常见的数学运算操作,同样的,在正式进入代码演示之前,先引入我们依赖的包,代码如下:

import numpy as np
import tensorflow as tf

print("numpy.version:", np.__version__)
print("tensorflow.version:", tf.__version__)

结果如下:

numpy.version: 1.23.5
tensorflow.version: 2.11.0

  下面我们正式展示TensorFlow中的数学运算操作,代码如下

# 定义两个二维张量
a = tf.constant([[1.0, 2], [3, 4]])
b = tf.constant([[1.0, 0], [-1, 0]])
print("a:")
tf.print(a)
print("----------------------------------")
print("b:")
tf.print(b)
print("----------------------------------")

# 加法运算
print("a + b:")
tf.print(a + b)
print("----------------------------------")

# 减法运算
print("a - b:")
tf.print(a - b)
print("----------------------------------")

# 乘法运算
print("a * b:")
tf.print(a * b)
print("----------------------------------")

# 除法运算
print("a / b:")
tf.print(a / b)
print("----------------------------------")

# 乘方
print("b ** 2:")
tf.print(b ** 2)
print("----------------------------------")

# 开方
print("sqrt(a):")
tf.print(tf.sqrt(a))
print("----------------------------------")

# add运算符重载,a + 1等价于tf.math.add
print("a + 1:")
tf.print(a + 1)
print("tf.math.add(a, 1):")
tf.print(tf.math.add(a, 1))
print("----------------------------------")

# 逻辑运算
print("b > 0:")
tf.print(b > 0)
print("b == 0:")
tf.print(b == 0)
print("----------------------------------")

# 最大值
print("tf.maximum(a, b)")
tf.print(tf.maximum(a, b))
print("----------------------------------")

# 最小值
print("tf.minimum(a,b)")
tf.print(tf.minimum(a,b))
print("----------------------------------")

结果如下:

a:
[[1 2]
 [3 4]]
----------------------------------
b:
[[1 0]
 [-1 0]]
----------------------------------
a + b:
[[2 2]
 [2 4]]
----------------------------------
a - b:
[[0 2]
 [4 4]]
----------------------------------
a * b:
[[1 0]
 [-3 0]]
----------------------------------
a / b:
[[1 inf]
 [-3 inf]]
----------------------------------
b ** 2:
[[1 0]
 [1 0]]
----------------------------------
sqrt(a):
[[1 1.41421354]
 [1.73205078 2]]
----------------------------------
a + 1:
[[2 3]
 [4 5]]
tf.math.add(a, 1):
[[2 3]
 [4 5]]
----------------------------------
b > 0:
[[1 0]
 [0 0]]
b == 0:
[[0 1]
 [0 1]]
----------------------------------
tf.maximum(a, b)
[[1 2]
 [3 4]]
----------------------------------
tf.minimum(a,b)
[[1 0]
 [-1 0]]
----------------------------------

二、矢量运算

  矢量运算是指在一个特定轴上进行运算,将一个张量映射到一个标量或者另外一个低维张量。
许多矢量运算都以reduce开头。下面分别从一维张量和多维张量的角度展示矢量运算的用法,代码如下:

#一维张量的矢量运算
a = tf.range(1,6)
print("a:")
tf.print(a)
print("----------------------------------")
#求和
tf.print("reduce_sum:", tf.reduce_sum(a, axis = 0))
#如果只是一维张量,默认可以不指定axis
#求最大值
tf.print("reduce_max:", tf.reduce_max(a)) 
#求最小值
tf.print("reduce_min:", tf.reduce_min(a))
#求最均值
tf.print("reduce_mean:", tf.reduce_mean(a)) 
#求积
tf.print("reduce_prod:", tf.reduce_prod(a))
#按顺序求每个位置累加和,类似于mysql中的窗口函数
tf.print("cumsum:", tf.math.cumsum(a))
#按顺序求每个位置累积
tf.print("cumprod:", tf.math.cumprod(a))
print("----------------------------------")

c = tf.constant([True,True,True])
d = tf.constant([False,False,True])
print("c:")
tf.print(c)
print("----------------------------------")
print("d:")
tf.print(d)
print("----------------------------------")
tf.print("reduce_all(c):", tf.reduce_all(c))
tf.print("reduce_all(d):", tf.reduce_all(d))
tf.print("reduce_any(d):", tf.reduce_any(d))
print("----------------------------------")

#tf.math.top_k可以用于对张量取top k
a = tf.constant([1,3,6,6,4,6])
tf.print("a:",a)
values,indices = tf.math.top_k(a, 3, sorted=True)
print("top 3:")
tf.print("indices", indices, "values", values)
print("----------------------------------")

#多维张量的矢量运算
b = tf.random.uniform(shape=[3, 3, 3], minval=0, maxval=2, dtype=tf.int32)
print("b:")
tf.print(b)
print("----------------------------------")

tf.print("axis=0, reduce_sum:\n", tf.reduce_sum(b, axis=0, keepdims=True))
tf.print("axis=1, reduce_sum:\n", tf.reduce_sum(b, axis=1, keepdims=False))
tf.print("axis=2, reduce_sum:\n", tf.reduce_sum(b, axis=2, keepdims=False))
tf.print("no axis, reduce_sum:", tf.reduce_sum(b))
print("----------------------------------")

结果如下:

a:
[1 2 3 4 5]
----------------------------------
reduce_sum: 15
reduce_max: 5
reduce_min: 1
reduce_mean: 3
reduce_prod: 120
cumsum: [1 3 6 10 15]
cumprod: [1 2 6 24 120]
----------------------------------
c:
[1 1 1]
----------------------------------
d:
[0 0 1]
----------------------------------
reduce_all(c): 1
reduce_all(d): 0
reduce_any(d): 1
----------------------------------
a: [1 3 6 6 4 6]
top 3:
indices [2 3 5] values [6 6 6]
----------------------------------
b:
[[[0 0 1]
  [1 1 0]
  [0 0 0]]

 [[0 1 1]
  [0 0 1]
  [1 1 0]]

 [[1 1 0]
  [0 0 1]
  [0 0 0]]]
----------------------------------
axis=0, reduce_sum:
 [[[1 2 2]
  [1 1 2]
  [1 1 0]]]
axis=1, reduce_sum:
 [[1 1 1]
 [1 2 2]
 [1 1 1]]
axis=2, reduce_sum:
 [[1 2 0]
 [2 1 2]
 [2 1 0]]
no axis, reduce_sum: 11
----------------------------------

三、矩阵运算

  矩阵运算主要是支持一些常规的线性代数中矩阵的计算,TensorFlow提供了tf.linalg包来实现大部分和矩阵有关的运算,包括转置、矩阵乘法、求逆、求迹、范数、行列式、求特征值以及矩阵分解等。下面通过代码来展示常用的矩阵运算,代码如下:

# 定义两个二维张量来表示矩阵 
a = tf.constant([[1, 2], [3, 4]], dtype=tf.float32)
b = tf.constant([[1, 0], [-1, 0]], dtype=tf.float32)
print("a:")
tf.print(a)
print("----------------------------------")
print("b:")
tf.print(b)
print("----------------------------------")

#矩阵转置
tf.print("矩阵转置:\n", tf.transpose(a))
print("----------------------------------")

#矩阵乘法
tf.print("矩阵乘法1:\n", tf.matmul(a, b))
tf.print("矩阵乘法2:\n", a @ b )
print("----------------------------------")

#矩阵求逆
tf.print("矩阵求逆:\n", tf.linalg.inv(a))
print("----------------------------------")

#矩阵求迹
tf.print("矩阵求迹:\n", tf.linalg.trace(a))
print("----------------------------------")

#矩阵特征值
tf.print("矩阵特征值:\n")
print( tf.linalg.eigvals(a))
print("----------------------------------")

#矩阵分解
s,u,v = tf.linalg.svd(a)
print("矩阵分解:\n")
tf.print(u,"\n")
tf.print(s,"\n")
tf.print(v,"\n")
tf.print(u @ tf.linalg.diag(s) @ tf.transpose(v))
print("----------------------------------")

结果如下


a:
[[1 2]
 [3 4]]
----------------------------------
b:
[[1 0]
 [-1 0]]
----------------------------------
矩阵转置:
 [[1 3]
 [2 4]]
----------------------------------
矩阵乘法1:
 [[-1 0]
 [-1 0]]
矩阵乘法2:
 [[-1 0]
 [-1 0]]
----------------------------------
矩阵求逆:
 [[-2.00000024 1.00000012]
 [1.50000012 -0.50000006]]
----------------------------------
矩阵求迹:
 5
----------------------------------
矩阵特征值:

tf.Tensor([-0.37228122+0.j  5.372281  +0.j], shape=(2,), dtype=complex64)
----------------------------------
矩阵分解:

[[0.404553503 -0.914514303]
 [0.914514303 0.404553503]] 

[5.46498537 0.365966141] 

[[0.576048374 0.817415595]
 [0.817415595 -0.576048374]] 

[[0.999999583 1.99999964]
 [2.99999976 4]]
----------------------------------

四、广播机制

  在Numpy中,广播机制(broad casting)指的是通过扩展低维度ndarray的维度来实现不同维度间ndarray的加减乘除等操作的机制。TensorFlow的广播机制来源于Numpy,其针对张量运算的广播规则和Numpy基本是一样的,广播规则如下:

  1. 如果张量的维度不同,对维度小的张量进行升维,直到两个张量的维度一样。
  2. 如果两个张量在某个维度上的长度是相同的,或者其中一个张量在该维度上的长度为1,那么就认为这两个张量在该维度上是相容的。
  3. 如果两个张量在所有维度上均相容,它们之间就能应用广播。
  4. 广播后,每个维度的长度将取两个张量在该维度长度的较大值。
  5. 在任何一个维度上,如果一个张量的长度为1,另一个张量长度大于1,那么在该维度上的广播就是对第一个张量进行复制。
      TensorFlow中实现广播有两种方式,一种是使用tf.broadcast_to显式地讲张量广播至指定维度,还有一种就是在运算过程系统进行隐式的广播。下面进行简单的示例,代码如下:
#定义两个维度不同的张量
a = tf.constant([1, 1, 1])
b = tf.constant([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print("a:")
tf.print(a)
print("----------------------------------")
print("b:")
tf.print(b)
print("----------------------------------")

#显式广播
tf.print("显式广播:\n", tf.broadcast_to(a, b.shape))
print("----------------------------------")

#隐式广播
tf.print("隐式广播:\na + b:\n", a + b) #等价于 tf.broadcast_to(a, b.shape) + b
tf.print("隐式广播:\na + 1:\n", a + 1)#等价于 a + tf.broadcast_to(1, a.shape)
print("----------------------------------")

#计算广播后的shape
tf.print("广播后的shape:", tf.broadcast_static_shape(a.shape, b.shape))
tf.print("广播后的shape:", tf.broadcast_dynamic_shape(a.shape, b.shape))
print("----------------------------------")

结果如下:

a:
[1 1 1]
----------------------------------
b:
[[1 2 3]
 [4 5 6]
 [7 8 9]]
----------------------------------
显式广播:
 [[1 1 1]
 [1 1 1]
 [1 1 1]]
----------------------------------
隐式广播:
a + b:
 [[2 3 4]
 [5 6 7]
 [8 9 10]]
隐式广播:
a + 1:
 [2 2 2]
----------------------------------
广播后的shape: TensorShape([3, 3])
广播后的shape: [3 3]
----------------------------------

  关于张量的运算,就简单介绍到这里。

TensorFlow系列文章:
  1. TensorFlow核心概念之Tensor(1):张量创建
  2. TensorFlow核心概念之Tensor(2):索引切片
  3. TensorFlow核心概念之Tensor(3):变换拆合
  4. TensorFlow核心概念之Tensor(4):张量运算
  5. TensorFlow核心概念之计算图
  6. TensorFlow核心概念之Autograph
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容