1. 程式人生 > >機器學習-Tensorflow之Tensor和Dataset學習

機器學習-Tensorflow之Tensor和Dataset學習

好了,咱們今天終於進入了現階段機器學習領域內最流行的一個框架啦——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就是處理資料的,如果咱們連資料的結構形式都不懂,實在是說不過去