Tensorflow快餐教程(2) - 標量運算

Tensorflow的Tensor意爲張量。通常若是是0維的數組,就是一個數據,咱們稱之爲標是Scalar;1維的數組,稱爲向量Vector;2維的數組,稱爲矩陣Matrics;3維及以上的數組,稱爲張量Tensor。
在機器學習中,用途最普遍的是向量和矩陣的運算。這也是咱們學習中的第一個難關。
不過,這一節咱們先打標量的基礎。python

上節咱們學過,Tensorflow的運行須要一個Session對象。下面代碼中所用的sess都是經過算法

sess = tf.Session()

獲取的Session對象,如下就都省略不寫了。數組

標量Scalar

標量是指只有一個數字的結構。
咱們嘗試將一個整數賦給一個Tensorflow的常量,看看是什麼效果:app

>>> a10 = 1
   >>> b10 = tf.constant(a10)
   >>> print(b10) Tensor("Const_6:0", shape=(), dtype=int32)
   >>> sess.run(b10) 1

咱們能夠看到,tf.constant(a10)生成了一個shape爲空的,類型爲int32的張量。機器學習

Tensorflow是一個通過數據類型優化的高性能系統,因此對於數據類型的要求比較高。
好比咱們想對上面的標量b10進行求正弦值的運算,就會獲得下面的錯誤,sin運算只支持浮點數和複數類型:函數

>>> b11 = tf.sin(b10)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.6/site-packages/tensorflow/python/ops/gen_math_ops.py", line 6862, in sin
    "Sin", x=x, name=name)
  File "/usr/lib/python3.6/site-packages/tensorflow/python/framework/op_def_library.py", line 609, in _apply_op_helper
    param_name=input_name)
  File "/usr/lib/python3.6/site-packages/tensorflow/python/framework/op_def_library.py", line 60, in _SatisfiesTypeConstraint
    ", ".join(dtypes.as_dtype(x).name for x in allowed_list)))
TypeError: Value passed to parameter 'x' has DataType int32 not in list of allowed values:

後面咱們還會屢次遇到數據類型不符合要求,以致於沒法運算的錯誤。
因此咱們首先要學習下Tensorflow的數據類型。性能

Tensorflow的數據類型

Tensorflow主要支持如下數據類型學習

  • 整型:

tf.int8: 8位帶符號整數
tf.uint8: 8位無符號整數
tf.int16: 16位帶符號整數
tf.int32: 32位帶符號整數
tf.int64: 64位帶符號整數優化

  • 浮點型:

tf.float32: 32位浮點數
tf.float64: 64位浮點數ui

  • 複數:

tf.complex64: 64位複數
tf.complex128: 128位複數
在Tensorflow的不少運算中,都支持經過dtype=的方式來指定數據類型。
例:

>>> b01 = tf.constant(1,dtype=tf.uint8)
>>> print(b01)
Tensor("Const_7:0", shape=(), dtype=uint8)
>>> b02 = tf.constant(1,dtype=tf.float64)
>>> print(b02)
Tensor("Const_8:0", shape=(), dtype=float64)
>>> sess.run(b01)
1
>>> sess.run(b02)
1.0

Tensor到某類型數據的轉換

經過tf.constant函數,咱們能夠將數據轉換成Tensor。一樣,Tensorflow也提供了Tensor到各類數據類型的轉換函數。
例,將Tensor轉換成tf.int32:

>>> b03 = tf.to_int32(b02)
>>> print(b03)
Tensor("ToInt32:0", shape=(), dtype=int32)
>>> sess.run(b03)
1
>>> b04 = sess.run(b03)
>>> print(b04)
1

從上面代碼能夠看到,b03 run的結果就是一個整數,不是Tensor.
相似的函數還有tf.to_int64, tf.to_float, tf.to_double等。

定義這麼多函數太麻煩了,還有一個通用的轉換函數tf.cast. 格式爲:tf.cast(Tensor, 類型名)。
例:

>>> b05 = tf.cast(b02, tf.complex128)
>>> sess.run(b05)
(1+0j)

飽和轉換

若是是將大類型如int64轉成小類型int16,tf.cast轉換可能會產生溢出。這在機器學習的計算中是件可怕的事情。在這種狀況下,咱們就須要使用飽和類型轉換saturate_cast來保駕護航。

好比咱們要把65536轉換成tf.int8類型:

>>> b06 = tf.constant(65536,dtype=tf.int64)
>>> print(b06)
Tensor("Const_9:0", shape=(), dtype=int64)
>>> sess.run(b06)
65536
>>> b07 = tf.saturate_cast(b06,tf.int8)
>>> sess.run(b07)
127

標量算術運算

標量Tensor常量能夠進行算術運算。本質上是調用tf.add, tf.sub, tf.mul, tf.truediv, tf.mod等重載函數。

例:

>>> d01 = tf.constant(1)
>>> d02 = tf.constant(2)
>>> d_add = d01 + d02
>>> print(d_add)
Tensor("add:0", shape=(), dtype=int32)
>>> d_sub = d01 - d02
>>> print(d_sub)
Tensor("sub:0", shape=(), dtype=int32)
>>> d_mul = d01 * d02
>>> print(d_mul)
Tensor("mul:0", shape=(), dtype=int32)
>>> d_div = d01 / d02
>>> print(d_div)
Tensor("truediv:0", shape=(), dtype=float64)
>>> d_mod = d01 % d02
>>> print(d_mod)
Tensor("mod:0", shape=(), dtype=int32)
>>> d_minus = -d01
>>> print(d_minus)
Tensor("Neg:0", shape=(), dtype=int32)

對於除法多說兩句,Tensor有兩種除法,一種是"/",另外一種是"//"。"/"是浮點除法,對應的是tf.truediv,而"//"是計算整除,對應tf.floordiv。

>>> d_div = d01 / d02
>>> print(d_div)
Tensor("truediv:0", shape=(), dtype=float64)
>>> d_div2 = d01 // d02
>>> print(d_div2)
Tensor("floordiv:0", shape=(), dtype=int32)

標量邏輯運算

對於>, <, >=, <=等關係,都會生成一個須要Session來運算的Tensor對象。只有==是例外,它會當即返回這兩個Tensor是不是同一對象的結果。

>>> d11 = d01 > d02
>>> d12 = d01 < d02
>>> d13 = d01 == d02
>>> d14 = d01 >= d02
>>> d15 = d01 <= d02
>>> print(d11)
Tensor("Greater_1:0", shape=(), dtype=bool)
>>> print(d12)
Tensor("Less:0", shape=(), dtype=bool)
>>> print(d13)
False
>>> print(d14)
Tensor("GreaterEqual:0", shape=(), dtype=bool)
>>> print(d15)
Tensor("LessEqual:0", shape=(), dtype=bool)
>>> d11 = d01 > d02

經常使用標量數學函數

首先仍是強調一下注意類型,好比整形,必定要先轉換成浮點型才能進行sqrt,sin等數學函數計算。
例:

>>> d31 = tf.constant(100, dtype=tf.float64)
>>> d32 = tf.sqrt(d31)
>>> sess.run(d32)
10.0

另外不要忘了,像sin, cos, tan這些函數是支持複數的哦。
例:

>>> d40 = tf.constant(1+2j)
>>> d41 = tf.sin(d40)
>>> sess.run(d41)

(3.165778513216168+1.9596010414216063j)
中間結果也能夠不用Tensor保存,直接用當即數,例:

>>> d42 = tf.cos(0.5+0.3j)
>>> sess.run(d42)
(0.917370851271881-0.14599480570180629j)

常量、佔位符和變量

前面咱們主要使用當即數和常量。常量是經過tf.constant定義的,一旦定義就不能改變值的Tensor。若是要想改變Tensor的值,有兩種變法:一種是根本就不賦值,先放個佔位符;另外一種是初始化成一個帶值的變量,未來再改變值。
下面簡單介紹一下佔位符和變量。

placeholder佔位符
在算法計算時,有不少公式須要的數值是須要從外部拿到的,隨時替換的。這時候咱們就能夠用一個佔位符來寫Tensor,須要計算時再把真數據經過feed_dict給填充進去就能夠。
咱們來看個例子:

>>> d50 = tf.placeholder(tf.float32, name ="input1")
>>> d51 = tf.sin(d50)
>>> sess.run(d51, feed_dict={d50: 0.2})
0.19866933

d50開始只用個placeholder,這樣的話是沒有辦法經過以前不加feed_dict參數的sess.run來運行的。經過指定feed_dict={d50: 0.2},咱們就用數據替換掉了placeholder,就能夠正常運行了。

變量

變量與佔位符不一樣的一點是,變量在使用以前須要作初始化。
初始化不但要在變量定義時寫,還要調用相應的函數在使用前執行才能夠。
咱們仍是舉例說明:

>>> d60 = tf.Variable(1, dtype=tf.float32, name='number1')
>>> d61 = tf.tan(d60)
>>> init_op = tf.global_variables_initializer()
>>> sess.run(init_op)
>>> sess.run(d61)
1.5574077

在使用變量以前,咱們能夠一次性調用tf.global_variables_initializer函數去初始化全部變量,而且經過Session去執行。在此以後才能使用變量。

變量初始化以後,就能夠經過assign函數來賦新值,例:

>>> d62 = d60.assign(d60 * 2)
    >>> sess.run(d62)
    2.0
    >>> sess.run(d61)
    -2.1850398

小結

小結一下,這節主要介紹了數據類型,標量經常使用的計算函數,還有使用佔位符和變量的方法。
下一節咱們正式開始線性代數之旅,走進向量、矩陣和張量。

詳情請閱讀原文

相關文章
相關標籤/搜索