好了,咱們今天終於進入了現階段機器學習領域內最流行的一個框架啦——TensorFlow。對的,這款由谷歌開發的機器學習框架非常的簡單易用並且得到了幾乎所有主流的認可,谷歌為了推廣它的這個框架甚至單獨開辟了免費學習這個框架的視頻教程,可惜這些教程都是基於TensorFlow1.0版本的,一直沒有更新。現在都是TensorFlow2.0版本了,其中的開發的API的變化非常非常大,很多都是不兼容的,非常坑,如果大家還是覺得要跳坑,我不攔着哈。它的應用的官方視頻教程的地址是https://developers.google.com/machine-learning/crash-course/ml-intro ,雖然這個視頻的覆蓋面比較廣,但是它也有幾個最大的缺點:1,就像上面指出來的,它的教程是基於1.0版本的,如果你把它放到最新的TensorFlow中去運行,你會發現一大堆的錯誤;2,它的視頻的內容深度很淺很淺,基本就是隨便講幾個API;所以綜上所述,大家可以參考參考它的視頻,但是一定不要鑽牛角尖,否則你會發現很痛苦的。好了,那么咱們就來進入到咱們今天的主題,那就是TensorFlow中的Tensor和dataset對象。正所謂基礎不牢,地動山搖,而tensor和dataset就是TensorFlow中的基礎中的基礎。大家都知道TensorFlow的主要任務就是處理數據的,而TensorFlow中的數據基本格式就是tensor和dataset,所以咱們肯定得要重視起來。這節內容呢,咱們先講一講TensorFlow操作對象的數據格式,以及TensorFlow中基本的數據對象。
- Tensor
Tensor其實翻譯過來就是張量的意思,這里我不解釋什么是張量,咱們就把它看成一個對象object,然后這個object里面有存儲數據和其他一些屬性,例如shape,dtype等等。為了更加形象的展示一下在TensorFlow中tensor到底長什么樣子,咱們來看一個小例子如下
<tf.Tensor: id=835, shape=(2,), dtype=int32, numpy=array([4, 6])>
從上面咱們可以看出,Tensor對象有一個id屬性;一個shape屬性,它是個tuple;一個dtype屬性;咱們的核心也是重點是在他的numpy屬性,這里也可以看出它是一個ndarray類型的數據。它的形式就是這么的簡單,雖然簡單,但是大家一定要理解它的意思以及本質,不要跟其他的數據類型搞混了,例如numpy中的array,Python中的list, 他們雖然長得很像,很多情況下也相互兼容,但是他們實質上是屬於不同的數據類型。那么既然咱們已經知道了tensor長什么樣子,也知道tensor中的內容含義,那么咱們如何創建一個tensor呢?其實任何一種Python或者numpy中的data,只要是通過TensorFlow中的運算符來計算過,那么就自動轉成並且返回tensor類型了,對的,你沒有聽錯,TensorFlow中也有他自己的加減乘除等運算的api,咱們看看下面幾個簡單的例子
tf.add(1,2)
tf.add([1,2],[3,4]) tf.square(5) tensor = tf.constant([1,2,3,4,5])
上面的返回結果分別是
<tf.Tensor: id=859, shape=(), dtype=int32, numpy=3> <tf.Tensor: id=862, shape=(2,), dtype=int32, numpy=array([4, 6])> <tf.Tensor: id=864, shape=(), dtype=int32, numpy=25> <tf.Tensor: id=865, shape=(5,), dtype=int32, numpy=array([1, 2, 3, 4, 5])>
根據前面對於tensor結構的分析,結合上面的例子,咱們就能更加深入的理解tensor這個數據對象了;那么這里問題又來了,如果咱們有Python的數據或者numpy的數據,我們如何能將他們轉化成tensor,甚至於他們能夠相互轉化呢???這是一個經常遇到的需求,咱們當然有辦法啦,看下面的代碼
"2. converting between Tensor and numpy array"
ndarray = np.ones([3,3]) #2.1 from numpy array to tensor (through tensorflow operations) tensor = tf.multiply(ndarray,1) #2.2 from tensor to numpy array (through explicitly numpy()) tensor_to_numpy = tensor.numpy()
哈哈,是不是超級簡單,從numpy轉成tensor,只需要TensorFlow乘以1就OK啦,相反地,從tensor轉成numpy只需要調用tensor的函數numpy()就行了。是不是so easy. TensorFlow都為咱們想好了。
補充:這里稍微補充一個小知識點,那就是GPU和CPU。在TensorFlow的應用中,或者說機器學習領域,一般都是大數據的處理,一般情況下,GPU對於數據的處理量和處理速度都大於CPU(因為CPU里面有很多非常復雜的邏輯單元和中斷系統等等),所以咱們一般都會將Tensor或者Dataset存儲在GPU中進行運算。那么問題來了,咱們怎么獲取我們機器的這些硬件信息呢?咱們如何把tensor存儲到制定的硬件里面去呢??
print(tf.config.experimental.list_physical_devices())#show the available devices
上面的代碼可以打印出咱們機器里面可用的CPU和GPU, 結果如下
[PhysicalDevice(name='/physical_device:CPU:0', device_type='CPU'), PhysicalDevice(name='/physical_device:GPU:0', device_type='GPU')]
可以看出咱們的機器有一個CPU和一個GPU,分別是CPU:0和GPU:0; 有了這個之后,咱們就可以讓咱們的數據存儲並且運算在指定的硬件上面,咱們可以用下面的方式來指定
#force execuion on CPU
with tf.device("CPU:0"): x = tf.random.uniform([1000,1000]) #assert x.device.endswith("CPU:0") time_matmul(x) #force execution on GPU print("On GPU") with tf.device("GPU:0"): x=tf.random.uniform([1000,1000]) #assert x.device.endswith("GPU:0") time_matmul(x)
從上面咱們可以看出,咱們可以用with這個關鍵字來指定咱們的tensor存儲在哪里。上面代碼的第一部分是指定到CPU,第二部分是指定到GPU。
- Dataset
Dataset顧名思義就是數據集的意思,雖然他的定義比較抽象,但是其實大家可以把它想象成一個裝Tensor的容器,一個dataset可能只來自於一個tensor,也可以是多個Tensor。但是這里的一個小細節需要注意,那就是當一個dataset來自於多個Tensor的時候,那么這些tensors的第一個dimension必須要是相同的,否則會產生incompatible errors錯誤哦。大家需要主要澳。那么咱們先來看看如何創建一個Dataset呢??
tensor1 = tf.multiply([1,2,3,4,5],1)
dataset1 = tf.data.Dataset.from_tensor_slices(tensor1)
咱們從上面可以看出來,第一句代碼是創建一個tensor對象,第二句就是創建dataset的過程,咱們最常用的創建dataset的API就是from_tensor_slicers這個方法,它后面的參數可以是一個tensor也可以是多個tensors. 那么上面是一個最簡單的dataset,接下來咱們看一個堪憂2個tensor的dataset:
c1 = tf.random.uniform([4]) c2= tf.random.uniform([4,10]) dataset2 = tf.data.Dataset.from_tensor_slices(( c1,c2 ))
咱們可以看出來,上面的代碼也是先創建2個tensor,分別是C1, C2。同樣的咱們通過from_tensor_slices這個方法創建dataset對象,但是咱們可以看出它里面的參數是一個tuple,這個tuple里面的元素就是2個tensors。注意:這里2個tensor的第一維(first dimension)是一樣的,記住這個必須一樣,否則必報錯哈。既然咱們已經創建了dataset,那么咱們如何獲取里面的值呢???在以前的TensorFlow版本都是通過創建iterator的方式來獲取dataset里面的element,那么在最新的版本中,這個方法已經被deprecate了,取而代之的是用for-in是方式遍歷了,如下所示,咱們去這個dataset2的第一條數據來演示
for element in dataset2: print(element) break
咱們看看dataset2的第一條數據長成啥樣哈?
(<tf.Tensor: id=67, shape=(), dtype=float32, numpy=0.8284787>, <tf.Tensor: id=68, shape=(10,), dtype=float32, numpy= array([0.46768987, 0.4085338 , 0.06623507, 0.16808486, 0.7843472 , 0.6430875 , 0.94050014, 0.79995286, 0.35672653, 0.97420156], dtype=float32)>)
仔細分析一下,它是一個tuple,這個tuple里面裝有兩個tensor對象。咱們這下應該全明白了tensor和dataset是啥了以及他們之間的關系了吧。
- 總結
那么咱們現在來總結一下哈,本節主要介紹了TensorFlow中基本的數據格式,分別是tensor和dataset。上面分別講述了tensor和dataset的結構,創建過程,內容獲取等方面的知識到。雖然TensorFlow是兼容咱們的numpy數據類型,但是有些情況下還是會有一些問題,所以咱們在后面學習TensorFlow應用的過程中盡量還是將數據轉化成tensor,即使tensor也是基於numpy的。這節的重點是看懂tensor對象的內部參數的意思,以及dataset的結構。這是整個TensorFlow的根基,畢竟TensorFlow就是處理數據的,如果咱們連數據的結構形式都不懂,實在是說不過去嘛。