diff --git "a/3-3,\351\253\230\351\230\266API\347\244\272\350\214\203.md" "b/3-3,\351\253\230\351\230\266API\347\244\272\350\214\203.md" index 096f2205..1986ee84 100644 --- "a/3-3,\351\253\230\351\230\266API\347\244\272\350\214\203.md" +++ "b/3-3,\351\253\230\351\230\266API\347\244\272\350\214\203.md" @@ -18,9 +18,6 @@ TensorFlow的高阶API主要为tf.keras.models提供的模型的类接口。 import tensorflow as tf from tensorflow.keras import models,layers,optimizers -``` - -```python #样本数量 n = 800 diff --git "a/4-1,\345\274\240\351\207\217\347\232\204\347\273\223\346\236\204\346\223\215\344\275\234.md" "b/4-1,\345\274\240\351\207\217\347\232\204\347\273\223\346\236\204\346\223\215\344\275\234.md" index 4a280c8c..55e5e087 100644 --- "a/4-1,\345\274\240\351\207\217\347\232\204\347\273\223\346\236\204\346\223\215\344\275\234.md" +++ "b/4-1,\345\274\240\351\207\217\347\232\204\347\273\223\346\236\204\346\223\215\344\275\234.md" @@ -1,2 +1,758 @@ # 4-1,张量的结构操作 + + +张量的操作主要包括张量的结构操作和张量的数学运算。 + +张量结构操作诸如:张量创建,索引切片,维度变换,合并分割。 + +张量数学运算主要有:标量运算,向量运算,矩阵运算。另外我们会介绍张量运算的广播机制。 + +本篇我们将介绍张量的结构操作。 + + +### 一,创建张量 + + +张量创建的许多方法和numpy中创建array的方法很像。 + +```python +import tensorflow as tf +import numpy as np +``` + +```python +a = tf.constant([1,2,3],dtype = tf.float32) +tf.print(a) +``` + +``` +[1 2 3] +``` + +```python +b = tf.range(1,10,delta = 2) +tf.print(b) +``` + +``` +[1 3 5 7 9] +``` + +```python +c = tf.linspace(0.0,2*3.14,100) +tf.print(c) +``` + +``` +[0 0.0634343475 0.126868695 ... 6.15313148 6.21656609 6.28] +``` + +```python +d = tf.zeros([3,3]) +tf.print(d) +``` + +``` +[[0 0 0] + [0 0 0] + [0 0 0]] + ``` + +```python +a = tf.ones([3,3]) +b = tf.zeros_like(a,dtype= tf.float32) +tf.print(a) +tf.print(b) +``` + +``` +[[1 1 1] + [1 1 1] + [1 1 1]] +[[0 0 0] + [0 0 0] + [0 0 0]] +``` + +```python +b = tf.fill([3,2],5) +tf.print(b) +``` + +``` +[[5 5] + [5 5] + [5 5]] +``` + +```python +#均匀分布随机 +tf.random.set_seed(1.0) +a = tf.random.uniform([5],minval=0,maxval=10) +tf.print(a) +``` + +``` +[1.65130854 9.01481247 6.30974197 4.34546089 2.9193902] +``` + +```python +#正态分布随机 +b = tf.random.normal([3,3],mean=0.0,stddev=1.0) +tf.print(b) +``` + +``` +[[0.403087884 -1.0880208 -0.0630953535] + [1.33655667 0.711760104 -0.489286453] + [-0.764221311 -1.03724861 -1.25193381]] +``` + +```python +#正态分布随机,剔除2倍方差以外数据重新生成 +c = tf.random.truncated_normal((5,5), mean=0.0, stddev=1.0, dtype=tf.float32) +tf.print(c) +``` + +``` +[[-0.457012236 -0.406867266 0.728577733 -0.892977774 -0.369404584] + [0.323488563 1.19383323 0.888299048 1.25985599 -1.95951891] + [-0.202244401 0.294496894 -0.468728036 1.29494202 1.48142183] + [0.0810953453 1.63843894 0.556645 0.977199793 -1.17777884] + [1.67368948 0.0647980496 -0.705142677 -0.281972528 0.126546144]] +``` + +```python +# 特殊矩阵 +I = tf.eye(3,3) #单位矩阵 +tf.print(I) +tf.print(" ") +t = tf.linalg.diag([1,2,3]) #对角阵 +tf.print(t) +``` + +``` +[[1 0 0] + [0 1 0] + [0 0 1]] + +[[1 0 0] + [0 2 0] + [0 0 3]] + ``` + +```python + +``` + +### 二 ,索引切片 + + +张量的索引切片方式和numpy几乎是一样的。切片时支持缺省参数和省略号。 + +对于tf.Variable,可以通过索引和切片对部分元素进行修改。 + +对于提取张量的连续子区域,也可以使用tf.slice. + +此外,对于不规则的切片提取,可以使用tf.gather,tf.gather_nd,tf.boolean_mask。 + +tf.boolean_mask功能最为强大,它可以实现tf.gather,tf.gather_nd的功能,并且tf.boolean_mask还可以实现布尔索引。 + +如果要通过修改张量的某些元素得到新的张量,可以使用tf.where,tf.scatter_nd。 + +```python +tf.random.set_seed(3) +t = tf.random.uniform([5,5],minval=0,maxval=10,dtype=tf.int32) +tf.print(t) +``` + +``` +[[4 7 4 2 9] + [9 1 2 4 7] + [7 2 7 4 0] + [9 6 9 7 2] + [3 7 0 0 3]] +``` + +```python +#第0行 +tf.print(t[0]) +``` + +``` +[4 7 4 2 9] +``` + +```python +#倒数第一行 +tf.print(t[-1]) +``` + +``` +[3 7 0 0 3] +``` + +```python +#第1行第3列 +tf.print(t[1,3]) +tf.print(t[1][3]) +``` + +``` +4 +4 +``` + +```python +#第1行至第3行 +tf.print(t[1:4,:]) +tf.print(tf.slice(t,[1,0],[3,5])) #tf.slice(input,begin_vector,size_vector) +``` + +``` +[[9 1 2 4 7] + [7 2 7 4 0] + [9 6 9 7 2]] +[[9 1 2 4 7] + [7 2 7 4 0] + [9 6 9 7 2]] +``` + +```python +#第1行至最后一行,第0列到最后一列每隔两列取一列 +tf.print(t[1:4,:4:2]) +``` + +``` +[[9 2] + [7 7] + [9 9]] +``` + +```python +#对变量来说,还可以使用索引和切片修改部分元素 +x = tf.Variable([[1,2],[3,4]],dtype = tf.float32) +x[1,:].assign(tf.constant([0.0,0.0])) +tf.print(x) +``` + +``` +[[1 2] + [0 0]] +``` + +```python +a = tf.random.uniform([3,3,3],minval=0,maxval=10,dtype=tf.int32) +tf.print(a) +``` + +``` +[[[7 3 9] + [9 0 7] + [9 6 7]] + + [[1 3 3] + [0 8 1] + [3 1 0]] + + [[4 0 6] + [6 2 2] + [7 9 5]]] +``` + +```python +#省略号可以表示多个冒号 +tf.print(a[...,1]) +``` + +``` +[[3 0 6] + [3 8 1] + [0 2 9]] +``` + + +以上切片方式相对规则,对于不规则的切片提取,可以使用tf.gather,tf.gather_nd,tf.boolean_mask。 + +考虑班级成绩册的例子,有4个班级,每个班级10个学生,每个学生7门科目成绩。可以用一个4*10*7的张量来表示。 + +```python +scores = tf.random.uniform((4,10,7),minval=0,maxval=100,dtype=tf.int32) +tf.print(scores) +``` + +``` +[[[52 82 66 ... 17 86 14] + [8 36 94 ... 13 78 41] + [77 53 51 ... 22 91 56] + ... + [11 19 26 ... 89 86 68] + [60 72 0 ... 11 26 15] + [24 99 38 ... 97 44 74]] + + [[79 73 73 ... 35 3 81] + [83 36 31 ... 75 38 85] + [54 26 67 ... 60 68 98] + ... + [20 5 18 ... 32 45 3] + [72 52 81 ... 88 41 20] + [0 21 89 ... 53 10 90]] + + [[52 80 22 ... 29 25 60] + [78 71 54 ... 43 98 81] + [21 66 53 ... 97 75 77] + ... + [6 74 3 ... 53 65 43] + [98 36 72 ... 33 36 81] + [61 78 70 ... 7 59 21]] + + [[56 57 45 ... 23 15 3] + [35 8 82 ... 11 59 97] + [44 6 99 ... 81 60 27] + ... + [76 26 35 ... 51 8 17] + [33 52 53 ... 78 37 31] + [71 27 44 ... 0 52 16]]] +``` + +```python +#抽取每个班级第0个学生,第5个学生,第9个学生的全部成绩 +p = tf.gather(scores,[0,5,9],axis=1) +tf.print(p) +``` + +``` +[[[52 82 66 ... 17 86 14] + [24 80 70 ... 72 63 96] + [24 99 38 ... 97 44 74]] + + [[79 73 73 ... 35 3 81] + [46 10 94 ... 23 18 92] + [0 21 89 ... 53 10 90]] + + [[52 80 22 ... 29 25 60] + [19 12 23 ... 87 86 25] + [61 78 70 ... 7 59 21]] + + [[56 57 45 ... 23 15 3] + [6 41 79 ... 97 43 13] + [71 27 44 ... 0 52 16]]] +``` + +```python +#抽取每个班级第0个学生,第5个学生,第9个学生的第1门课程,第3门课程,第6门课程成绩 +q = tf.gather(tf.gather(scores,[0,5,9],axis=1),[1,3,6],axis=2) +tf.print(q) +``` + +``` +[[[82 55 14] + [80 46 96] + [99 58 74]] + + [[73 48 81] + [10 38 92] + [21 86 90]] + + [[80 57 60] + [12 34 25] + [78 71 21]] + + [[57 75 3] + [41 47 13] + [27 96 16]]] +``` + +```python +# 抽取第0个班级第0个学生,第2个班级的第4个学生,第3个班级的第6个学生的全部成绩 +#indices的长度为采样样本的个数,每个元素为采样位置的坐标 +s = tf.gather_nd(scores,indices = [(0,0),(2,4),(3,6)]) +s +``` + +``` + +``` + + +以上tf.gather和tf.gather_nd的功能也可以用tf.boolean_mask来实现。 + +```python +#抽取每个班级第0个学生,第5个学生,第9个学生的全部成绩 +p = tf.boolean_mask(scores,[True,False,False,False,False,True,False,False,False,True],axis=1) +tf.print(p) +``` + +``` +[[[52 82 66 ... 17 86 14] + [24 80 70 ... 72 63 96] + [24 99 38 ... 97 44 74]] + + [[79 73 73 ... 35 3 81] + [46 10 94 ... 23 18 92] + [0 21 89 ... 53 10 90]] + + [[52 80 22 ... 29 25 60] + [19 12 23 ... 87 86 25] + [61 78 70 ... 7 59 21]] + + [[56 57 45 ... 23 15 3] + [6 41 79 ... 97 43 13] + [71 27 44 ... 0 52 16]]] +``` + +```python +#抽取第0个班级第0个学生,第2个班级的第4个学生,第3个班级的第6个学生的全部成绩 +s = tf.boolean_mask(scores, + [[True,False,False,False,False,False,False,False,False,False], + [False,False,False,False,False,False,False,False,False,False], + [False,False,False,False,True,False,False,False,False,False], + [False,False,False,False,False,False,True,False,False,False]]) +tf.print(s) +``` + +``` +[[52 82 66 ... 17 86 14] + [99 94 46 ... 1 63 41] + [46 83 70 ... 90 85 17]] +``` + +```python +#利用tf.boolean_mask可以实现布尔索引 + +#找到矩阵中小于0的元素 +c = tf.constant([[-1,1,-1],[2,2,-2],[3,-3,3]],dtype=tf.float32) +tf.print(c,"\n") + +tf.print(tf.boolean_mask(c,c<0),"\n") +tf.print(c[c<0]) #布尔索引,为boolean_mask的语法糖形式 +``` + +``` +[[-1 1 -1] + [2 2 -2] + [3 -3 3]] + +[-1 -1 -2 -3] + +[-1 -1 -2 -3] +``` + +```python + +``` + +以上这些方法仅能提取张量的部分元素值,但不能更改张量的部分元素值得到新的张量。 + +如果要通过修改张量的部分元素值得到新的张量,可以使用tf.where和tf.scatter_nd。 + +tf.where可以理解为if的张量版本,此外它还可以用于找到满足条件的所有元素的位置坐标。 + +tf.scatter_nd的作用和tf.gather_nd有些相反,tf.gather_nd用于收集张量的给定位置的元素, + +而tf.scatter_nd可以将某些值插入到一个给定shape的全0的张量的指定位置处。 + +```python +#找到张量中小于0的元素,将其换成np.nan得到新的张量 + +c = tf.constant([[-1,1,-1],[2,2,-2],[3,-3,3]],dtype=tf.float32) +d = tf.where(c<0,tf.fill(c.shape,np.nan),c) #tf.where和np.where作用类似,可以理解为if的张量版本 +d +``` + +```python +#如果where只有一个参数,将返回所有满足条件的位置坐标 +indices = tf.where(c<0) +indices +``` + +```python +#将张量的第[0,0]和[2,1]两个位置元素替换为0得到新的张量 +d = c - tf.scatter_nd([[0,0],[2,1]],[c[0,0],c[2,1]],c.shape) +d +``` + +```python +#scatter_nd的作用和gather_nd有些相反,可以将某些值插入到一个给定shape的全0的张量的指定位置处。 +indices = tf.where(c<0) +tf.scatter_nd(indices,tf.gather_nd(c,indices),c.shape) +``` + +```python + +``` + +```python + +``` + +### 三,维度变换 + + +维度变换相关函数主要有 tf.reshape, tf.squeeze, tf.expand_dims, tf.transpose. + +tf.reshape 可以改变张量的形状。 + +tf.squeeze 可以减少维度。 + +tf.expand_dims 可以增加维度。 + +tf.transpose 可以交换维度。 + + +```python +a = tf.random.uniform(shape=[1,3,3,2],minval=0,maxval=255,dtype=tf.int32) +tf.print(a.shape) +tf.print(a) +``` + +``` +TensorShape([1, 3, 3, 2]) +[[[[135 178] + [26 116] + [29 224]] + + [[179 219] + [153 209] + [111 215]] + + [[39 7] + [138 129] + [59 205]]]] +``` + +```python +# 改成 (3,6)形状的张量 +b = tf.reshape(a,[3,6]) +tf.print(b.shape) +tf.print(b) +``` + +``` +TensorShape([3, 6]) +[[135 178 26 116 29 224] + [179 219 153 209 111 215] + [39 7 138 129 59 205]] +``` + +```python + +``` + +reshape可以改变张量的形状,但是其本质上不会改变张量元素的存储顺序,所以,该操作实际上非常迅速,并且是可逆的。 + +```python +# 改回成 [1,3,3,2] 形状的张量 +c = tf.reshape(b,[1,3,3,2]) +tf.print(c) +``` + +``` +[[[[135 178] + [26 116] + [29 224]] + + [[179 219] + [153 209] + [111 215]] + + [[39 7] + [138 129] + [59 205]]]] +``` + +```python + +``` + +如果张量在某个维度上只有一个元素,利用tf.squeeze可以消除这个维度。 +和tf.reshape相似,它本质上不会改变张量元素的存储顺序。 + +张量的各个元素在内存中是线性存储的,其一般规律是,同一层级中的相邻元素的物理地址也相邻。 + +```python +s = tf.squeeze(a) +tf.print(s.shape) +tf.print(s) +``` + +``` +TensorShape([3, 3, 2]) +[[[135 178] + [26 116] + [29 224]] + + [[179 219] + [153 209] + [111 215]] + + [[39 7] + [138 129] + [59 205]]] +``` + +```python +d = tf.expand_dims(s,axis=0) #在第0维插入长度为1的一个维度 +d +``` + +``` + +``` + + +tf.transpose可以交换张量的维度,与tf.reshape不同,它会改变张量元素的存储顺序。 + +tf.transpose常用于图片存储格式的变换上。 + +```python +# Batch,Height,Width,Channel +a = tf.random.uniform(shape=[100,600,600,4],minval=0,maxval=255,dtype=tf.int32) +tf.print(a.shape) + +# 转换成 Channel,Height,Width,Batch +s= tf.transpose(a,perm=[3,1,2,0]) +tf.print(s.shape) +``` + +``` +TensorShape([100, 600, 600, 4]) +TensorShape([4, 600, 600, 100]) + +``` + +```python + +``` + +### 四,合并分割 + + +和numpy类似,可以用tf.concat和tf.stack方法对多个张量进行合并,可以用tf.split方法把一个张量分割成多个张量。 + +tf.concat和tf.stack有略微的区别,tf.concat是连接,不会增加维度,而tf.stack是堆叠,会增加维度。 + +```python +a = tf.constant([[1.0,2.0],[3.0,4.0]]) +b = tf.constant([[5.0,6.0],[7.0,8.0]]) +c = tf.constant([[9.0,10.0],[11.0,12.0]]) + +tf.concat([a,b,c],axis = 0) +``` + +``` + +``` + +```python +tf.concat([a,b,c],axis = 1) +``` + +``` + +``` + +```python +tf.stack([a,b,c]) +``` + +``` + +``` + +```python +tf.stack([a,b,c],axis=1) +``` + +``` + +``` + +```python +a = tf.constant([[1.0,2.0],[3.0,4.0]]) +b = tf.constant([[5.0,6.0],[7.0,8.0]]) +c = tf.constant([[9.0,10.0],[11.0,12.0]]) + +c = tf.concat([a,b,c],axis = 0) +``` + +tf.split是tf.concat的逆运算,可以指定分割份数平均分割,也可以通过指定每份的记录数量进行分割。 + +```python +#tf.split(value,num_or_size_splits,axis) +tf.split(c,3,axis = 0) #指定分割份数,平均分割 +``` + +``` +[, + , + ] +``` + +```python +tf.split(c,[2,2,2],axis = 0) #指定每份的记录数量 +``` + +``` +[, + , + ] +``` + +```python + +``` + +如果对本书内容理解上有需要进一步和作者交流的地方,欢迎在公众号"Python与算法之美"下留言。作者时间和精力有限,会酌情予以回复。 + +![image.png](./data/Python与算法之美logo.jpg) diff --git "a/4-2,\345\274\240\351\207\217\347\232\204\346\225\260\345\255\246\350\277\220\347\256\227.md" "b/4-2,\345\274\240\351\207\217\347\232\204\346\225\260\345\255\246\350\277\220\347\256\227.md" index fb2b43aa..6ffc7286 100644 --- "a/4-2,\345\274\240\351\207\217\347\232\204\346\225\260\345\255\246\350\277\220\347\256\227.md" +++ "b/4-2,\345\274\240\351\207\217\347\232\204\346\225\260\345\255\246\350\277\220\347\256\227.md" @@ -1,2 +1,507 @@ # 4-2,张量的数学运算 + + +张量的操作主要包括张量的结构操作和张量的数学运算。 + +张量结构操作诸如:张量创建,索引切片,维度变换,合并分割。 + +张量数学运算主要有:标量运算,向量运算,矩阵运算。另外我们会介绍张量运算的广播机制。 + +本篇我们介绍张量的数学运算。 + +```python + +``` + +### 一,标量运算 + + +张量的数学运算符可以分为标量运算符、向量运算符、以及矩阵运算符。 + +加减乘除乘方,以及三角函数,指数,对数等常见函数,逻辑比较运算符等都是标量运算符。 + +标量运算符的特点是对张量实施逐元素运算。 + +有些标量运算符对常用的数学运算符进行了重载。并且支持类似numpy的广播特性。 + +许多标量运算符都在 tf.math模块下。 + +```python +import tensorflow as tf +import numpy as np +``` + +```python +a = tf.constant([[1.0,2],[-3,4]]) +b = tf.constant([[5.0,6],[7.0,8.0]]) +a+b #运算符重载 +``` + +``` + +``` + +```python +a-b +``` + +``` + +``` + +```python +a*b +``` + +``` + +``` + +```python +a/b +``` + +``` + +``` + +```python +a**2 +``` + +``` + +``` + +```python +a**(0.5) +``` + +``` + +``` + +```python +m = tf.math.mod(a,3) #mod的运算符重载 +a%3 +``` + +``` + +``` + +```python +a//3 #地板除法,等价于tf.floor(a/3.0) +``` + +``` + +``` + +```python +(a>=2) +``` + +``` + +``` + +```python +(a>=2)&(a<=3) +``` + +``` + +``` + +```python +(a>=2)|(a<=3) +``` + +``` + +``` + +```python +a==5 #tf.equal(a,5) +``` + +``` + +``` + +```python +tf.sqrt(a) +``` + +``` + +``` + +```python +a = tf.constant([1.0,8.0]) +b = tf.constant([5.0,6.0]) +c = tf.constant([6.0,7.0]) +tf.add_n([a,b,c]) +``` + +``` + +``` + +```python +tf.print(tf.maximum(a,b)) +``` + +``` +[5 8] +``` + +```python +tf.print(tf.minimum(a,b)) +``` + +``` +[1 6] +``` + +```python + +``` + +### 二,向量运算 + + +向量运算符只在一个特定轴上运算,将一个向量映射到一个标量或者另外一个向量。 +许多向量运算符都以reduce开头。 + +```python +#向量reduce +a = tf.range(1,10) +tf.print(tf.reduce_sum(a)) +tf.print(tf.reduce_mean(a)) +tf.print(tf.reduce_max(a)) +tf.print(tf.reduce_min(a)) +tf.print(tf.reduce_prod(a)) +``` + +``` +45 +5 +9 +1 +362880 +``` + +```python +#张量指定维度进行reduce +b = tf.reshape(a,(3,3)) +tf.print(tf.reduce_sum(b, axis=1, keepdims=True)) +tf.print(tf.reduce_sum(b, axis=0, keepdims=True)) +``` + +``` +[[6] + [15] + [24]] +[[12 15 18]] +``` + +```python +#bool类型的reduce +p = tf.constant([True,False,False]) +q = tf.constant([False,False,True]) +tf.print(tf.reduce_all(p)) +tf.print(tf.reduce_any(q)) +``` + +``` +0 +1 +``` + +```python +#利用tf.foldr实现tf.reduce_sum +s = tf.foldr(lambda a,b:a+b,tf.range(10)) +tf.print(s) +``` + +``` +45 +``` + +```python +#cum扫描累积 +a = tf.range(1,10) +tf.print(tf.math.cumsum(a)) +tf.print(tf.math.cumprod(a)) +``` + +``` +[1 3 6 ... 28 36 45] +[1 2 6 ... 5040 40320 362880] +``` + +```python +#arg最大最小值索引 +a = tf.range(1,10) +tf.print(tf.argmax(a)) +tf.print(tf.argmin(a)) +``` + +``` +8 +0 +``` + +```python +#tf.math.top_k可以用于对张量排序 +a = tf.constant([1,3,7,5,4,8]) + +values,indices = tf.math.top_k(a,3,sorted=True) +tf.print(values) +tf.print(indices) + +#利用tf.math.top_k可以在TensorFlow中实现KNN算法 +``` + +``` +[8 7 5] +[5 2 3] +``` + +```python + +``` + +### 三,矩阵运算 + + +矩阵必须是二维的。类似tf.constant([1,2,3])这样的不是矩阵。 + +矩阵运算包括:矩阵乘法,矩阵转置,矩阵逆,矩阵求迹,矩阵范数,矩阵行列式,矩阵求特征值,矩阵分解等运算。 + +除了一些常用的运算外,大部分和矩阵有关的运算都在tf.linalg子包中。 + +```python +#矩阵乘法 +a = tf.constant([[1,2],[3,4]]) +b = tf.constant([[2,0],[0,2]]) +a@b #等价于tf.matmul(a,b) +``` + +``` + +``` + +```python +#矩阵转置 +a = tf.constant([[1.0,2],[3,4]]) +tf.transpose(a) +``` + +``` + +``` + +```python +#矩阵逆,必须为tf.float32或tf.double类型 +a = tf.constant([[1.0,2],[3.0,4]],dtype = tf.float32) +tf.linalg.inv(a) +``` + +``` + +``` + +```python +#矩阵求trace +a = tf.constant([[1.0,2],[3,4]]) +tf.linalg.trace(a) +``` + +``` +#矩阵求trace +a = tf.constant([[1.0,2],[3,4]]) +tf.linalg.trace(a) +``` + +```python +#矩阵求范数 +a = tf.constant([[1.0,2],[3,4]]) +tf.linalg.norm(a) +``` + +``` + +``` + +```python +#矩阵行列式 +a = tf.constant([[1.0,2],[3,4]]) +tf.linalg.det(a) +``` + +``` + +``` + +```python +#矩阵特征值 +tf.linalg.eigvalsh(a) +``` + +``` + +``` + +```python +#矩阵qr分解 +a = tf.constant([[1.0,2.0],[3.0,4.0]],dtype = tf.float32) +q,r = tf.linalg.qr(a) +tf.print(q) +tf.print(r) +tf.print(q@r) +``` + +``` +[[-0.316227794 -0.948683321] + [-0.948683321 0.316227734]] +[[-3.1622777 -4.4271884] + [0 -0.632455349]] +[[1.00000012 1.99999976] + [3 4]] +``` + +```python +#矩阵svd分解 +a = tf.constant([[1.0,2.0],[3.0,4.0]],dtype = tf.float32) +v,s,d = tf.linalg.svd(a) +tf.matmul(tf.matmul(s,tf.linalg.diag(v)),d) + +#利用svd分解可以在TensorFlow中实现主成分分析降维 + +``` + +``` + +``` + +```python + +``` + +```python + +``` + +### 四,广播机制 + + +TensorFlow的广播规则和numpy是一样的: + +* 1、如果张量的维度不同,将维度较小的张量进行扩展,直到两个张量的维度都一样。 +* 2、如果两个张量在某个维度上的长度是相同的,或者其中一个张量在该维度上的长度为1,那么我们就说这两个张量在该维度上是相容的。 +* 3、如果两个张量在所有维度上都是相容的,它们就能使用广播。 +* 4、广播之后,每个维度的长度将取两个张量在该维度长度的较大值。 +* 5、在任何一个维度上,如果一个张量的长度为1,另一个张量长度大于1,那么在该维度上,就好像是对第一个张量进行了复制。 + +tf.broadcast_to 以显式的方式按照广播机制扩展张量的维度。 + +```python +a = tf.constant([1,2,3]) +b = tf.constant([[0,0,0],[1,1,1],[2,2,2]]) +b + a #等价于 b + tf.broadcast_to(a,b.shape) +``` + +``` + +``` + +```python +tf.broadcast_to(a,b.shape) +``` + +``` + +``` + +```python +#计算广播后计算结果的形状,静态形状,TensorShape类型参数 +tf.broadcast_static_shape(a.shape,b.shape) +``` + +``` +TensorShape([3, 3]) +``` + +```python +#计算广播后计算结果的形状,动态形状,Tensor类型参数 +c = tf.constant([1,2,3]) +d = tf.constant([[1],[2],[3]]) +tf.broadcast_dynamic_shape(tf.shape(c),tf.shape(d)) +``` + +``` + +``` + +```python +#广播效果 +c+d #等价于 tf.broadcast_to(c,[3,3]) + tf.broadcast_to(d,[3,3]) +``` + +``` + +``` + +```python + +``` + +如果对本书内容理解上有需要进一步和作者交流的地方,欢迎在公众号"Python与算法之美"下留言。作者时间和精力有限,会酌情予以回复。 + +![image.png](./data/Python与算法之美logo.jpg) + +```python + +``` diff --git "a/data/Tensorflow\345\261\202\346\254\241\347\273\223\346\236\204.jpg" "b/data/Tensorflow\345\261\202\346\254\241\347\273\223\346\236\204.jpg" new file mode 100644 index 00000000..6ad58e19 Binary files /dev/null and "b/data/Tensorflow\345\261\202\346\254\241\347\273\223\346\236\204.jpg" differ diff --git a/push-to-github.md b/push-to-github.md index daba2d2e..ff62b1eb 100644 --- a/push-to-github.md +++ b/push-to-github.md @@ -33,7 +33,7 @@ ``` ```python -!git pull origin master +#!git pull origin master ``` ```python diff --git "a/\344\270\211\343\200\201TensorFlow\347\232\204\345\261\202\346\254\241\347\273\223\346\236\204.md" "b/\344\270\211\343\200\201TensorFlow\347\232\204\345\261\202\346\254\241\347\273\223\346\236\204.md" index 917b91d7..5a332645 100644 --- "a/\344\270\211\343\200\201TensorFlow\347\232\204\345\261\202\346\254\241\347\273\223\346\236\204.md" +++ "b/\344\270\211\343\200\201TensorFlow\347\232\204\345\261\202\346\254\241\347\273\223\346\236\204.md" @@ -20,5 +20,5 @@ TensorFlow的层次结构从低到高可以分成如下五层。 第五层为Python实现的模型成品,一般为按照OOP方式封装的高级API,主要为tf.keras.models提供的模型的类接口。 如果把模型比作一个房子,那么第五层API就是模型本身,即【模型之屋】。 -![](./data/TensorFlow层次结构呀.jpg) +![](./data/TensorFlow层次结构.jpg) diff --git "a/\345\233\233\343\200\201TensorFlow\347\232\204\344\275\216\351\230\266API.md" "b/\345\233\233\343\200\201TensorFlow\347\232\204\344\275\216\351\230\266API.md" index a1f4ff84..53d0951a 100644 --- "a/\345\233\233\343\200\201TensorFlow\347\232\204\344\275\216\351\230\266API.md" +++ "b/\345\233\233\343\200\201TensorFlow\347\232\204\344\275\216\351\230\266API.md" @@ -1,2 +1,24 @@ # 四、TensorFlow的低阶API + + +TensorFlow的低阶API主要包括张量操作,计算图和自动微分。 + +如果把模型比作一个房子,那么低阶API就是【模型之砖】。 + +在低阶API层次上,可以把TensorFlow当做一个增强版的numpy来使用。 + +TensorFlow提供的方法比numpy更全面,运算速度更快,如果需要的话,还可以使用GPU进行加速。 + +前面几章我们对低阶API已经有了一个整体的认识,本章我们将重点详细介绍张量操作和AutoGraph计算图。 + + +张量的操作主要包括张量的结构操作和张量的数学运算。 + +张量结构操作诸如:张量创建,索引切片,维度变换,合并分割。 + +张量数学运算主要有:标量运算,向量运算,矩阵运算。另外我们会介绍张量运算的广播机制。 + + +AutoGraph计算图我们将介绍使用Autograph的规范建议,Autograph的机制原理,Autograph和tf.Module. +