向量
向量在編程語(yǔ)言中就是最常用的一維數(shù)組(Vector)纳胧。
二維數(shù)組叫做矩陣(Matrix)挂捅,三維以上叫做張量(Tensor)。
向量雖然簡(jiǎn)單护盈,高效挟纱,且容易理解。但是與操作0維的標(biāo)量數(shù)據(jù)畢竟還是不同的腐宋。比如向量經(jīng)常用于表示一個(gè)序列紊服,生成序列像標(biāo)量一樣一個(gè)一個(gè)手工寫就不劃算了。當(dāng)然可以用循環(huán)來寫胸竞。在向量中這樣還好欺嗤,如果是在矩陣或者是張量中就強(qiáng)烈建議不要用循環(huán)來做了。系統(tǒng)提供的函數(shù)一般都是經(jīng)過高度優(yōu)化的卫枝,而且可以使用GPU資源來進(jìn)行加速煎饼。
我們一方面盡可能地多使用系統(tǒng)的函數(shù),另一方面也不要迷信它們校赤,代碼優(yōu)化是一個(gè)實(shí)踐的過程吆玖,可以實(shí)際比較測(cè)量一下。
快速生成向量的方法
range函數(shù)生成等差數(shù)列
tf.range函數(shù)用來快速生成一個(gè)等差數(shù)列马篮。相當(dāng)于之前我們講numpy時(shí)的np.arange函數(shù)容贝。
原型:
tf.range(start, limit, delta=1, dtype=None, name='range')
例:
b11 = tf.range(1,100,1)
print(b11)
print(sess.run(b11))
Tensor("range:0", shape=(99,), dtype=int32)
[ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
97 98 99]
linspace生成浮點(diǎn)等差數(shù)組
tf.linspace與tf.range的區(qū)別在于瞳步,數(shù)據(jù)類型不同蜕便。
tf.lin_space(start, stop, num, name=None)
其中化借,start和stop必須是浮點(diǎn)數(shù)鹅搪,且類型必須相同帚稠。num必須是整數(shù)浇借。
例:
a2 = tf.linspace(1.0,10.0,4)
print(a2)
print(sess.run(a2))
Tensor("LinSpace:0", shape=(4,), dtype=float32)
[ 1. 4. 7. 10.]
拼瓷磚
就是將一段向量重復(fù)若干次螟够。
a10 = tf.range(1,4,1)
print(a10)
print(sess.run(a10))
a11 = tf.tile(a10,[3])
print(a11)
print(sess.run(a11))
Tensor("range_1:0", shape=(3,), dtype=int32)
[1 2 3]
Tensor("Tile:0", shape=(9,), dtype=int32)
[1 2 3 1 2 3 1 2 3]
向量操作
將向量反序
可以使用tf.reverse函數(shù)读慎。
原型:
tf.reverse( tensor, axis, name=None)
tensor是向量漱贱,axis軸對(duì)于向量不重要,給個(gè)[-1]就可以了夭委。折騰軸是張量時(shí)間的事情幅狮,暫時(shí)還用不到。
a2 = tf.linspace(1.0,10.0,4)
print(sess.run(a2))
a3 = tf.reverse(a2,[-1])
print(sess.run(a3))
[ 1. 4. 7. 10.]
[10. 7. 4. 1.]
切片
切片也是向量的常用操作之一,就是取數(shù)組的一部分崇摄。
例:
a5 = tf.linspace(1.0,100.0, 10)
print(sess.run(a5))
a6 = tf.slice(a5, [2],[4])
print(sess.run(a6))
[ 1. 12. 23. 34. 45. 56. 67. 78. 89. 100.]
[23. 34. 45. 56.]
將來處理張量時(shí)擎值,我們從一個(gè)矩陣切一塊,或從一個(gè)張量中切一塊逐抑,就好玩得多了鸠儿。但是原理跟向量上是一樣的。
連接
tf.concat也是需要給定軸信息的厕氨。對(duì)于兩個(gè)線性的向量进每,我們給0或者-1就好。
a20 = tf.linspace(1.0,2.0,10)
print(sess.run(a20))
a21 = tf.linspace(2.0,3.0,5)
print(sess.run(a21))
a23 = tf.concat([a20,a21],-1)
print(sess.run(a23))
[1. 1.1111112 1.2222222 1.3333334 1.4444444 1.5555556 1.6666667
1.7777778 1.8888888 2. ]
[2. 2.25 2.5 2.75 3. ]
[1. 1.1111112 1.2222222 1.3333334 1.4444444 1.5555556 1.6666667
1.7777778 1.8888888 2. 2. 2.25 2.5 2.75 3. ]
向量計(jì)算
向量加減法
同樣長(zhǎng)度的向量之間可以進(jìn)行加減操作命斧。
例:
a40 = tf.constant([1,1])
a41 = tf.constant([2,2])
a42 = a40 + a41
print(sess.run(a42))
a43 = a40 - a41
print(a43)
print(sess.run(a43))
[3 3]
Tensor("sub:0", shape=(2,), dtype=int32)
[-1 -1]
向量乘除標(biāo)量
向量乘除標(biāo)量也非常好理解田晚,就是針對(duì)向量中的每個(gè)數(shù)都做乘除法。
例:
a44 = a40 * 2
print(sess.run(a44))
a45 = a44 / 2
print(sess.run(a45))
print(a44)
print(a45)
[2 2]
[1. 1.]
Tensor("mul:0", shape=(2,), dtype=int32)
Tensor("truediv:0", shape=(2,), dtype=float64)
廣播運(yùn)算
如果針對(duì)向量和標(biāo)量進(jìn)行加減運(yùn)算国葬,也是會(huì)對(duì)向量中的每個(gè)數(shù)進(jìn)行加減運(yùn)算贤徒。這種操作稱為廣播操作。
例:
a46 = a40 + 1
print(sess.run(a46))
print(a46)
[2 2]
Tensor("add_1:0", shape=(2,), dtype=int32)
向量乘法
兩個(gè)向量相乘胃惜,默認(rèn)的運(yùn)算是求元素對(duì)應(yīng)乘積(element-wise product)泞莉,也叫做Hadamard積。
例:
b1 = tf.constant([1, 2])
b2 = tf.constant([2, 1])
b3 = b1 * b2
print(b3)
print(sess.run(b3))
Tensor("mul_1:0", shape=(2,), dtype=int32)
[2 2]
直接調(diào)用tf.multiply也是同樣的效果船殉,例:
b4 = tf.multiply(b1,b2)
print(b4)
print(sess.run(b4))
Tensor("Mul_2:0", shape=(2,), dtype=int32)
[2 2]
如果要計(jì)算點(diǎn)積(dot product)的話鲫趁,我們得提前劇透一下矩陣的內(nèi)容了。
首先利虫,用向量是沒法做矩陣計(jì)算的挨厚。
例:
a21 = tf.constant([2,3])
a22 = tf.constant([4,5])
print(a21)
print(a22)
Tensor("Const_8:0", shape=(2,), dtype=int32)
Tensor("Const_9:0", shape=(2,), dtype=int32)
這樣(2,)的形狀是向量,我們得先把它轉(zhuǎn)換成(2,1)這樣的單行矩陣糠惫,如下:
a31 = tf.constant(sess.run(tf.reshape(a21,[2,1])))
a32 = tf.constant(sess.run(tf.reshape(a22,[2,1])))
print(a31)
print(a32)
Tensor("Const_10:0", shape=(2, 1), dtype=int32)
Tensor("Const_11:0", shape=(2, 1), dtype=int32)
下面我們終于可以計(jì)算點(diǎn)積了疫剃,我們知道點(diǎn)積A.B相當(dāng)于A的轉(zhuǎn)置乘以B,我們可以通過matmul函數(shù)來進(jìn)行矩陣乘法硼讽。
a31 = tf.matmul(a31,a32,transpose_a=True)
print(sess.run(a31)) # 也就是2*4+3*5=23
[[23]]
我們也可以用tf.tensordot函數(shù)來計(jì)算點(diǎn)積巢价。我們剛才為什么沒用呢?答案是tensordot要求是浮點(diǎn)型矩陣固阁。
例:
第一步壤躲,需要浮點(diǎn)數(shù):
f01 = tf.constant([1,1],dtype=tf.float32)
f02 = tf.constant([1,2],dtype=tf.float32)
第二步,reshape成單行矩陣:
f11 = tf.constant(sess.run(tf.reshape(f01,[2,1])))
f12 = tf.constant(sess.run(tf.reshape(f02,[2,1])))
print(f11)
print(f12)
Tensor("Const_14:0", shape=(2, 1), dtype=float32)
Tensor("Const_15:0", shape=(2, 1), dtype=float32)
第三步备燃,調(diào)用tensordot
f13 = tf.tensordot(f11,f12,2)
print(sess.run(f13))
3.0
小結(jié)
從上面我們學(xué)習(xí)的函數(shù)我們可以看到碉克,與普通語(yǔ)言中提供的函數(shù)多是為一維數(shù)組操作不同,Tensorflow中的切片并齐、拼接等操作也是基于張量的漏麦。
當(dāng)我們后面學(xué)到張量遇到困難時(shí)客税,不妨回來看下這一節(jié)。不管后面張量多么復(fù)雜撕贞,其實(shí)也只是從一維向二維和多維推廣而己更耻。