雲栖号資訊:【 點選檢視更多行業資訊】
在這裡您可以找到不同行業的第一手的上雲資訊,還在等什麼,快來!
俗話說得好,機器學習要想玩的溜,你可以不會寫Python,但一定不能不會調庫(大霧)。Numpy可以說是Python中最基礎也是最重要的工具庫了,要用Python做機器學習,玩轉各種架構,Numpy是必須要會的。像是TensorFlow、pytorch這些知名架構都是基于Numpy進行計算的,可想而知它的重要性。
Numpy存在的必要性
網上關于Numpy的介紹非常多,但說來說去無非是一個Python中數值計算的非常重要的基礎包,可以用來很友善地做一些矩陣和大資料的運算。
Numpy是做什麼的我們很好了解,但是我們可能更加好奇它更深層次的意義究竟是什麼?關于這個問題我們從淺到深不停地追問,可以得到許多不同的答案。
最淺層的回答很簡單,Numpy很友善,計算速度快,可以很友善地進行矩陣運算。在Andrew的課程當中,他曾經示範過,同樣的矩陣運算,如果我們通過Python中的循環實作速度會比調用Numpy慢上至少上百倍。這個差異顯然是非常可怕的。
但為什麼Numpy會更快呢?
我們追問下去,又會得到一個新的答案。因為Numpy包底層是通過C++實作的,顯然C++運算比Python快得多,是以Numpy自然就更快了。
難道Numpy就隻是因為C++更快這麼簡單嗎?
這個問題已經超越了Numpy本身,我們需要從Python的特性來回答了。Python是一門解釋型語言,也就是說當我們執行Python的時候,其實是執行了一個Python的解釋器。由Python的解釋器來解釋執行Python的每一行代碼。
如果我們把解釋器了解成虛拟機,把Python執行的代碼了解成虛拟機當中的程式。如果我們虛拟機多開的話,是很難保證線程安全的。為了解決這個問題,Python設計了GIL機制,也就是全局解釋器鎖,它保證了同一時刻最多隻有一個解釋器線程在執行。
這個機制保證了線程安全,但是也限制了Python多線程的使用。Python的多線程本質上是僞多線程,因為解釋器隻有一個線程在跑。是以如果我們想要通過多線程并發來加速計算的話,這是不可能的。
而矩陣和向量的一些操作是可以通過多線程并發來加速計算的,而Python本身的特性導緻了Python不能執行這樣的操作。那麼通過Python調用C++實作的計算庫也就是唯一的選擇了。實際上不僅是Numpy,幾乎所有Python的計算庫,都是通過Python調用其他語言實作的。Python本身隻是最上層的調用方。
了解了這點除了對于Python可以有更加清晰的認識之外,也有助于之後學習TensorFlow等其他架構。
Numpy中的n維數組
Numpy之是以好用,是因為我們可以通過Numpy很友善地建立高維的數組和矩陣。
舉個例子,比如在原生Python當中,當我們需要建立一個二維數組的時候,往往需要些很長的定義。比如我們想要一個10 * 10的數組:

但是在Numpy當中就會很友善,隻需要一行。
第一行當中我們引入了numpy,為了編碼友善,我們将它重新命名成了np。這個是業内慣用做法,幾乎所有使用numpy的程式員都會這麼重命名。
在numpy當中,存儲高維數組的對象叫做ndarray,與之對應的是存儲矩陣的mat。其實這兩者差別不大,支援矩陣的運算,ndarray基本上也都支援。我們有這麼一個印象即可,關于mat内容我們會在之後介紹。
我們建立除了ndarray之後,關于擷取ndarray基本資訊的api大概有下面四個。
第一個是通過.ndim檢視ndarray的次元,也就是檢視這是一個幾維的數組:
第二個是通過.shape擷取這個ndarray在各個次元的大小:
第三個是通過.dtype擷取這個ndarray中元素的類型:
最後一個是tolist()方法,可以将一個ndarray轉化成Python原生的list進行傳回。
ndarray
那麼我們怎麼建立numpy中的ndarray呢?
大概也有幾種辦法,首先,既然numpy中的ndarray可以轉換成Python原生的list,同樣Python中原生的list也可以轉換成numpy中的ndarray。
和轉換變量類型的文法很像,我們通過np.array()轉換即可。
除了通過Python中原生的list轉換,我們還可以根據自己的需要建立新的ndarray。numpy建立array的方法有很多,我們先來介紹一下其中比較基礎的幾種。
建立出一個range
np.arange可以生成一個序列,有些類似于Python中原生的range。不過它更加靈活,我們可以之傳入一個整數,它會傳回一個從0開始的序列:
我們也可以指定首尾元素和間隔,numpy會自動幫我們生成一個等差序列:
除此之外,numpy中還提供了ones和zeros兩個api,可以生成全為0和全為1的元素。
我們還可以使用eye或者是identity生成一個N*N的機關矩陣:
除此之外,還有一個full的api可以指定shape和數值,用我們指定的數值填充出一個指定大小的數組來:
但是這個api我們用的不多,因為我們可以用ones生成一個全為1的數組,然後乘上一個我們想要的值,就等價于full。
另外,ones, zeros, full這幾個api還有一個對應的like方法。所謂的like方法就是我們傳入另外一個ndarray代替shape,numpy會根據這個ndarray的形狀生成一個對應形狀的新array。
我們來看個例子吧,首先我們生成一個順序的序列:
然後我們通過zeros_like方法生成一個同樣大小的全為0的矩陣:
它其實等價于:
其他幾個like方法也大同小異,因為可替代性很強,是以我也用的不多。
numpy支援的類型
numpy支援的資料類型很多,除了常用的int和float之外,還支援複數類型的complex,某種程度上來說和golang支援的類型比較接近。
其中int類型一共分為int8,int32,int64和int128,其中每一種又分為帶符号的和不帶符号的。例如int8就是帶符号的8位二進制表示的int,而uint8則是不帶符号位的。浮點數沒有無符号浮點數,一共分為float16,float32,float64和flaot128。
複數也有三種,分别是complex64,complex128和complex256。除此之外還有string_和object以及unicode_這三種類型。
我們可以通過調用astype方法更改ndarray中所有變量的類型:
除了人為轉換之外,我們還可以在建立的時候通過dtype這個參數來表示我們想要建立的資料的類型,這樣可以避免之後轉換的麻煩。
結尾
這篇文章當中我們不僅介紹了Numpy的建立的方法,還聊了Python這門語言的一些特性。正是因為Python本身多線程的限制,導緻它在需要高并發計算的場景下性能很差。才會需要通過Python去調用C++或者是其他語言的底層實作。這也是為什麼Python經常被稱為膠水語言的原因。
Numpy可以認為是Python進行機器學習的基礎,當然除了Numpy之外,像是pandas、matplot以及scikit-learn等庫也是必不可少的。我們會從Numpy開始,一點一點把這些常用的庫都給大家分享一遍。
【雲栖号線上課堂】每天都有産品技術專家分享!
課程位址:
https://yqh.aliyun.com/live立即加入社群,與專家面對面,及時了解課程最新動态!
【雲栖号線上課堂 社群】
https://c.tb.cn/F3.Z8gvnK
原文釋出時間:2020-05-13
本文作者:承志
本文來自:“
掘金”,了解相關資訊可以關注“掘金”