在人工智能的研發中,其本質就是把一切問題轉化爲數學問題,因此數學運算很是重要。不少數學運算採用的都是numpy這個庫,由於它提供了很是多的科學計算的方法,能讓咱們的工做變得很是便利,這一章我將從numpy的基本使用開始,逐漸解決掉那些數學問題,讓Python與數學可以更緊密的結合在一塊兒。python
numpy的本質其實仍是一個多維數組,雖然咱們以前學習過數組對象(Python中的list或者tuple)和numpy的數據看似同樣,可是數組是沒法直接參與數值運算的,而numpy對象卻能夠。算法
import numpy as np arr1 = np.array([1, 2, 3, 4, 5, 6]) arr2 = np.array([[1, 2, 3, 4, ], [5, 6, 7, 8, ]]) print(arr1, arr1.shape, arr1.dtype) print(arr2, arr2.shape, arr1.dtype) # shape獲取數組形狀2行4列,dtype獲取數組中元素類型
若是咱們建立數組時,元素類型不同,numpy會給咱們自動處理成同樣的。數組
arr3 = np.array([1, 2.5, 3]) # 只要數組元素中出現float類型,就會所有處理成float print(arr3, arr3.dtype) arr4 = np.array(['4', 5, 5.6]) # 只要數組元素中出現str,就會所有處理成str print(arr4, arr4.dtype)
numpy的訪問與Python中list或者tuple訪問原理同樣,方法也很是相似,只不過是加了一個緯度的概念。less
# 首先咱們定義了一個二維數組 arr5 = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]) print(arr5[1]) # 第一行 [4 5 6] print(arr5[1][0]) # 第一行第0個 4 print(arr5[:, 2]) # 全部行第2個 [ 3 6 9 12] print(arr5[:2]) # 前2行 [[1 2 3] [4 5 6]] print(arr5[1, :]) # 第1行全部列 [4 5 6] print(arr5[:, 1:2]) # 全部行第2到第3列 [[ 2] [ 5] [ 8] [11]]
對於二維來講,若是有逗號,逗號前是行篩選,逗號後是列篩選。對於n維來講,第一個逗號前是第一維,後面依次是二維三維等。ide
numpy對象有一個shape屬性,在Python基礎中,對於形狀並不敏感,而在科學計算中,形狀卻很重要,在後面的算法模型計算中,咱們會使用地很頻繁。函數
# 定義一個6行3列的numpy數組對象 arr6 = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12], [13, 14, 15], [16, 17, 18]]) print(arr6.shape) # 注意看每次打印的結果 print(arr6.reshape(2, 9)) # 獲得一個新的形狀,原來的對象不變 print(arr6.shape, arr6) print(arr6.resize(2, 9)) # 無返回值,真正修改 print(arr6.shape, arr6)
咱們在這段代碼中,分別使用了reshape和resize兩種方法來對數組進行形狀上的改變。其中reshape只是返回改變形狀後的預覽狀態,或者說若是咱們要使用這個結果只能把結果賦值給一個單獨的變量,而後再進行使用。resize方法的返回結果爲空,可是它卻真正的改變了組數的形狀,仔細看打印結果你就可以發現這兩種形狀操做方法的區別了。學習
降維是人工智能算法中很是經常使用且重要的一個操做,緣由是有時咱們去描述一個事物的特徵時,會有很是多的維度,但過多的維度會給咱們的計算帶來麻煩,這個時候咱們就須要去下降它的維度,而後再進行計算。人工智能
arr7 = np.array([[1, 10, 100], [2, 20, 200], [3, 30, 300]]) # 按照數組的行順序降至一維 print(arr7) print(arr7.ravel()) print(arr7.reshape(-1)) print(arr7.flatten()) # 按照大小順序降至一維 print(arr7.ravel(order="F")) print(arr7.reshape(-1, order="F")) print(arr7.flatten(order="F"))
降維後再進行修改code
print('ravel:{}'.format(arr7.ravel())) arr7.ravel()[1] = 1000 print(arr7) print('reshape: {}'.format(arr7.reshape(-1))) arr7.reshape(-1)[2] = 3000 print(arr7) print('flatten: {}'.format(arr7.flatten())) arr7.flatten()[0] = 2000 print(arr7)
從結果中,咱們看到經過flatten方法實現的降維返回的是複製的操做,若是要用,那麼只能把結果賦值給另外的變量了。它並無影響原來數組的結果。經過ravel和reshape兩個方法,返回的則是視圖,也就是經過對視圖的修改,是會直接影響到原數組中的值的。orm
arr8 = np.array([[1, 10, 100], [2, 20, 200], [3, 30, 300]]) arr9 = np.array([1, 2, 3]) arr10 = np.array([[5], [6], [7]]) # 縱向堆疊 print(np.vstack([arr8, arr9])) print(np.row_stack([arr8, arr9])) # 橫向合併 print(np.hstack([arr8, arr10])) print(np.column_stack([arr8, arr10]))
須要注意的是:多個數組橫向堆疊時,要保證行數相同,縱向合併,則要保證列數相同。
在之前,咱們若是要對兩個同形狀的數組進行對應位置的四則運算時,咱們必需要對兩個數組進行循環處理,代碼量上來講並很多,而且容易出錯。有了NumPy以後,這些運算將會變的很是的簡單。
import numpy as np arr1 = np.array([11, 12, 13]) arr2 = np.array([21, 22, 23]) arr3 = np.array([31, 32, 33]) print(arr1 + arr2) print(arr1 + arr2 + arr3) print(arr1 - arr2) print(arr1 - arr2 - arr3) print(arr1 * arr2) print(arr1 * arr2 * arr3) print(arr1 / arr2) print(arr1 / arr2 / arr3) print(arr1 // arr2) print(arr1 % arr2) print(arr1 ** arr2) print(np.add(arr1, arr2)) print(np.add(np.add(arr1, arr2), arr3)) print(np.subtract(arr1, arr2)) print(np.multiply(arr1, arr2)) print(np.divide(arr1, arr2))
從代碼的運行結果中咱們能夠看到,當咱們使用符號進行四則運算的時候,是能夠連續進行操做的。當咱們使用對象的方法進行四則運算的時候,不能夠連續進行操做,由於這個方法只接收兩個參數。若是咱們想要對多個數組對象進行操做的時候,咱們必須使用方法嵌套的方式來進行操做。除了四則運算,在學習Python基礎時,所學習的取餘數、整除、冪運算等都是支持的。
print(arr1 <= arr2) print(arr1 == arr2) print(arr1 != arr2) print(np.greater(arr1, arr2)) print(np.greater_equal(arr1, arr2)) print(np.less(arr1, arr2)) print(np.less_equal(arr1, arr2)) print(np.equal(arr1, arr2)) print(np.not_equal(arr1, arr2))
從結果上看,運用比較運算符能夠返回布爾類型的值,也就是True和False。那咱們何時會用到這樣的運算呢?第一種狀況是從數組中查詢知足條件的元素,第二種狀況是根據判斷的結果執行不一樣的操做,示例代碼以下:
arr3 = np.array([23, 12, 25]) arr4 = np.array([21, 15, 23]) print(arr3[arr3 > arr4]) # 取出arr3中元素大於arr4的 print(arr3[arr3 > 24]) # 取出arr3中元素大於24的 print(np.where(arr3 > 24, 0, arr3)) # 相似三元表達式,把大於24的修改爲0,其餘不變 print(list(0 if x > 24 else x for x in arr3)) print(np.where(arr4 > 16, 0, arr4))
上面咱們全部的運算都是基於相同形狀的數組,那麼當數組形狀不一樣時,可以讓它們之間進行運算嗎?答案是確定的,可是有相應的規則,不能隨意計算,這種計算就叫作廣播運算。
# 1 廣播運算,末尾的緯度值加上去 arr3 = np.arange(60).reshape(5, 4, 3) arr4 = np.arange(12).reshape(4, 3) print(arr3) print(arr4) print(arr3 + arr4) # 2 緯度值有一個爲1 arr5 = np.arange(60).reshape(5, 4, 3) arr6 = np.arange(4).reshape(4, 1) print(arr5) print(arr6) print(arr5 + arr6) # 3 arr7會自動補齊,相似上面緯度值有一個爲1 arr7 = np.arange(12).reshape(4, 3) arr8 = np.array([1, 2, 3]) print(arr7) print(arr8) print(arr7 + arr8) arr9 = np.arange(60).reshape(5, 4, 3) arr10 = np.arange(8).reshape(4, 2) print(arr9) print(arr10) # print(arr9 + arr10) # 不在上述三種討論範圍內,沒法運算
其實,廣播運算中的廣播就是一對多,它的規律就是二者有類似的地方能夠對應的上就能運算,缺乏的部分,會自動用相同的部分補齊。
numpy提供給咱們一些常見的函數,除了np.pi或者np.e這樣的常量函數,numpy也提供給咱們不少數學函數供咱們直接調用。
import numpy as np arr1 = np.array([1.3, 1.5, -1.8, 2.4, 3.2]) arr2 = np.array([1, 2, 3, 4, 5]) print(np.fabs(arr1)) # 絕對值 print(np.ceil(arr1)) # 向上取整 print(np.floor(arr1)) # 向下取整 print(np.round(arr1)) # 四捨五入 print(np.fmod(arr2, arr1)) # 餘數 print(np.modf(arr1)) # 取小數部分和整數部分 print(np.sqrt(arr2)) # 算法平方根 print(np.square(arr2)) # 平方 print(np.exp(arr2)) # 以e爲底的指數 print(np.power(arr2, 3)) # 各元素的3次方 print(np.log2(arr2)) # 以2爲底的對數 print(np.log10(arr2)) # 以10爲底的對數 print(np.log(arr2)) # 以e爲底的對數
數組對象有幾個維度就有幾個軸,對於咱們常見的二維數組來講,軸0是豎直方向,軸1是水平方向。
import numpy as np arr1 = np.array([[3, 7, 25, 8, 15, 20], [4, 5, 6, 9, 14, 21]]) print(arr1) print(np.max(arr1)) # 全部數組元素最大值 print(np.max(arr1, axis=1)) # 軸1最大值 print(np.max(arr1, axis=0)) # 軸0最大值
numpy提供了不少能夠按照軸方向來計算的函數。
print(np.min(arr1, axis=0)) # 最小值 print(np.min(arr1, axis=1)) print(np.mean(arr1, axis=0)) # 平均值 print(np.median(arr1, axis=0)) # 中位數 print(np.sum(arr1, axis=1)) # 求和