1. 程式人生 > >numpy基礎學習大集合(一)

numpy基礎學習大集合(一)

前言

機器學習,深度學習必備知識。不懂簡直懵逼,這裡列舉了常用的以自己複習和入門。

安裝

pip安裝

pip install numpy 

anaconda

自行選擇。(備註:python將於2020年停止python 2的更新,建議選擇學習py3)

由來

numpy的誕生就是為了更好做矩陣和陣列的相關計算。“更好” 就說明python 的List 可能不是太好。

python LIst的特點

python List支援表示式生成列表(這也是python的建議方式)

L=[i for i in range(10)]
print(L)

image.png

python的列表是支援多型別元素的

,這與C語言和 Java不同。在C語言和Java的陣列中只允許一種型別的元素。而python允許不同型別的元素存在一個數組中。
image.png

這可以說是一個優點也可以是一個缺點。這增大了python 陣列的多樣性,但是在遍歷的時候就會出大問題。python的團隊不是傻子,就創造了另外一個array的包。只需要impory array即可使用。

import array
arr=array.array('i',[i for i in range(10)])  #指定了陣列的型別“i”為整型
arr

輸出

array('i', [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

不要看這個陣列長的奇怪,它與我們普通陣列一樣訪問,一樣遍歷。

arr[5]
out: 5

但是現在就不能改變這個陣列的型別了。

arr[7]=‘d’
----------------------------------------
TypeErrorTraceback (most recent call last)
<ipython-input-16-d628dcc0f656> in <module>()
----> 1 arr[7]='d'

TypeError: an integer is required (got type str)

這樣真是好不容易解決了衝突問題,但是實用性還是很差,學過線性代數的都知道矩陣有很多計算,然而這個array並沒有提供很多。於是一個重量級的numpy.array閃亮登場。

numpy登場

numpy是一個非常強大的包,因為強大里面的東西也很多,很難記憶。這裡簡單分了個累把常用的列舉出來。

初見

numpy自帶型別轉換。
跟array包裡面一樣,生成一個numpy的array只需要呼叫numpy.array即可。

import numpy as np
nparr=np.array([i for i in range(10)])
nparr

out: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

可以檢視一下nparr的型別

nparr.dtype

out: dtype('int64')

可以看出這是一個整型的陣列。說明numpy自動幫我們識別了元素的型別。
再試試

nparr2=np.array([1,2,3.0])
nparr2.dtype

dtype('float64')

numpy自動識別了陣列中有float型的,於是由變數的隱式轉換規則,把整個陣列變成了float陣列。是不是很酷。

容錯性

如果我們是一個整數陣列,改變其中的元素為其他型別會怎麼樣呢?

import numpy as np
nparr=np.array([i for i in range(10)])
nparr
out: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

nparr[5]='3'
nparr
out : array([0, 1, 2, 3, 4, 3, 6, 7, 8, 9])

我們發現它可以把字元型別的數字直接轉換為int,這一切都是自動的。不需要手動的進行ch-‘0’這種操作。

nparr[5]=3.4
nparr

out: array([0, 1, 2, 3, 4, 3, 6, 7, 8, 9])

numpy自動完成了float->int的強制轉換(就是把小數截斷了)。
其實這所做的一切都是為了保證一個array中只有一個型別,跟array.array一樣的。如果我們把其中一個元素變成一個字串,就會報錯。

nparr[5]='dd'
nparr

----------------------------------------
ValueErrorTraceback (most recent call last)
<ipython-input-29-f3bd68497947> in <module>()
----> 1 nparr[5]='dd'
      2 nparr

ValueError: invalid literal for int() with base 10: 'dd'

numpy.array的各種初始化

全0

np.zero

#zeros(shape, dtype=float, order='C')

#Return a new array of given shape and type, filled with zeros.

由文件可以看出zeros有三個引數shape 就是形狀。dtype是型別可選引數,預設為float型別,order是一個可選引數,一般不用管它。‘C’的意思就是按照行優先。

np.zeros(10)

array([ 0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.])

最簡單的創造全0陣列的方式,只需要指定形狀就可以了。型別和排列方式都系統自定了。
注意這裡預設是float型別的。
如果要為別的型別需要強制指定。(備註:實際中大多數使用float型)

np.zeros(10,dtype=int)

array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0])

形狀可以通過元祖或者列表直接指定。[行,列] 或者 (行,列)。

a=np.zeros(shape=(3,4),dtype='float')
a

array([[ 0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.],
       [ 0.,  0.,  0.,  0.]])

單位陣(全1)

np.ones

跟全零是一個樣的。不贅述了。

np.ones(shape=(2,3))
array([[ 1.,  1.,  1.],
       [ 1.,  1.,  1.]])

填充陣(全‘X’)

要不就是全0 要不就是全1很沒意思,那要指定填充物呢,也是可以的。

np.full(shape=(3,4),fill_value=666,dtype='float64')

array([[ 666.,  666.,  666.,  666.],
       [ 666.,  666.,  666.,  666.],
       [ 666.,  666.,  666.,  666.]])

arange

arange可以指定起點、終點、步長進行陣列的建立。
注意 前包後不包
例如:

np.arange(0,20,step=2)

array([ 0,  2,  4,  6,  8, 10, 12, 14, 16, 18])

前包後不包的意思就是包括起始的位置,終點不包括。步長是2.
當然步長可以是整數,也可以是小數。

linspace

這個直接指定開始、結束,然後個數進行建立。

注意 前包後也包

np.linspace(start=0,stop=20,num=10) #終點預設是包含的

array([  0.        ,   2.22222222,   4.44444444,   6.66666667,
         8.88888889,  11.11111111,  13.33333333,  15.55555556,
        17.77777778,  20.        ])

也可以讓終點不包含

np.linspace(start=0,stop=20,num=10,endpoint=False) 

array([  0.,   2.,   4.,   6.,   8.,  10.,  12.,  14.,  16.,  18.])

random

np.random是一個包,這個包裡面有很多方法。

randint

產生隨機數,範圍是(low,high)

randint(low, high=None, size=None, dtype='l')

Return random integers from `low` (inclusive) to `high` (exclusive).

Return random integers from the "discrete uniform" distribution of
the specified dtype in the "half-open" interval [`low`, `high`). If
`high` is None (the default), then results are from [0, `low`).

這裡說的是,high是可選引數,如果沒有的話就產生(0,low)的隨機數。如果有high的話就產生(low,high)的隨機數。size是個數。dtype只能指定是int8,int16 還是int64 .(l就是int64)

我們知道隨機數是通過隨機種子計算出來的。
如果我們每次想產生想同的隨機數只需要種下一樣的種子就可以了。

np.random.seed(666)

random

這是random模組的一個函式random。產生0到1的隨機數(不包含1)/

random_sample(size=None)

Return random floats in the half-open interval [0.0, 1.0).
np.random.random()
0.2811684913927954

np.random.random(10)
array([ 0.46284169,  0.23340091,  0.76706421,  0.81995656,  0.39747625,
        0.31644109,  0.15551206,  0.73460987,  0.73159555,  0.8578588 ])

normal

這個比較重要,產生服從高斯分佈的隨機數,一般使用者深度學習權重向量的初始化。

normal(loc=0.0, scale=1.0, size=None)

Draw random samples from a normal (Gaussian) distribution.

loc是均值。
scale是方差

np.random.normal(10,100,size=10)
array([  92.1013692 ,   46.7125916 ,  175.39958581,   23.94647258,
       -111.71535503,  -89.49473667, -146.44858645, -152.87900441,
        133.17486561,  -81.36003361])

numpy.array的基本操作

檢視屬性

因為跟矩陣掛鉤,檢視屬性也很有必要。np.array這個類提供兩個基本屬性檢視。

import numpy as np
X=np.arange(15).reshape(3,5)
X

array([[ 0,  1,  2,  3,  4],
       [ 5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14]])
X.ndim #檢視維度個數

2
X.shape #檢視形狀

(3, 5)

資料訪問

numpy中的array跟python中的array訪問是一樣的。
可以通過下標的方式去訪問X[1]

也可以X[1][1]這樣去訪問,但是不建議。直接X[1,1]就可以了。
這是普通的訪問,當然也支援python的切片。

切片

切片其實很簡單。
首先看一維的:

x=np.arange(10)

array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

x[0:5]
#產生一個前閉後閉的陣列
array([0, 1, 2, 3, 4])
x[::2] #以2為步長對陣列進行切分

array([0, 2, 4, 6, 8])

多維的也很簡單,我們用逗號隔開每個維度,在每個維度上面會有不同的操作。

X[:2,:3]
array([[0, 1, 2],
       [5, 6, 7]])

取子序列

這個用 切片就可以,

subX=X[:2,:3]
subX

array([[0, 1, 2],
       [5, 6, 7]])

這是最簡單的取子序列。但是numpy中為了效率 這個subX只是X 的引用。這意味著subX 中的值改變了。X的值也改變了。

subX[0,0]=100
X
array([[100,   1,   2,   3,   4],
       [  5,   6,   7,   8,   9],
       [ 10,  11,  12,  13,  14]])

只需要使用array這個類帶的copy()函式即可。

subX=X[:2,:3].copy()

改變形狀

使用的是numpy中array類函式reshape

a.reshape(shape, order='C')

Returns an array containing the same data with a new shape.

意思就是返回一個值相同但是形狀不一樣的新陣列。

x.reshape(2,5)
array([[0, 1, 2, 3, 4],
       [5, 6, 7, 8, 9]])

這是我們知道形狀,但是有時候知道一個維度的大小。另外一個維度,我們希望系統能夠幫我們計算出來。這也是可以的。

x
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

x.reshape(2,-1)
array([[0, 1, 2, 3, 4],
       [5, 6, 7, 8, 9]])

數組合並

預備

x=np.array([1,2,3])
y=np.array([3,2,1])
z=np.array([666,666,666])
array([666, 666, 666])

A = np.array([[1,2,3],[4,5,6]])
array([[1, 2, 3],
       [4, 5, 6]])

concatenate

concatenate((a1, a2, ...), axis=0)

Join a sequence of arrays along an existing axis.

這個函式可以把陣列拼接起來,預設是沿著第一個維度 (axis就是指定維度,0就是行)

np.concatenate([A,A])

array([[1, 2, 3],
       [4, 5, 6],
       [1, 2, 3],
       [4, 5, 6]])

np.concatenate([A,A],axis=1)
array([[1, 2, 3, 1, 2, 3],
       [4, 5, 6, 4, 5, 6]])

這個方法看起來很完善,行也可以列也可以,但是也存在一個很大的麻煩。
我們看

z=np.array([666,666,666])
array([666, 666, 666])

A = np.array([[1,2,3],[4,5,6]])
array([[1, 2, 3],
       [4, 5, 6]])

這裡直接

np.concatenate([A,z])
----------------------------------------
ValueErrorTraceback (most recent call last)
<ipython-input-59-be375e0592ac> in <module>()
----> 1 np.concatenate([A,z])

ValueError: all the input arrays must have same number of dimensions

因為維度不一樣,A是一個二維的矩陣,z是一個一維的向量。雖然看起來“列”都一樣,但是不能想當然的去合併,那麼我們只能把z變成一個二維的。

np.concatenate([A,z.reshape(1,-1)])
array([[  1,   2,   3],
       [  4,   5,   6],
       [666, 666, 666]])

如果遇到這種情況就很煩了,還要考慮維度,還要手動的進行升維。能不能再傻瓜一點呢?答案是ok的。

vstack

在垂直方向進行堆疊

np.vstack([A,z])

array([[  1,   2,   3],
       [  4,   5,   6],
       [666, 666, 666]])

這就很奇怪,為啥維度不一樣還能進行堆疊?答案是很神奇。猜測就是隻要水平維度相同就能堆疊。

B=np.full((2,2),100)

array([[100, 100],
       [100, 100]])

np.hstack([A,B])
array([[  1,   2,   3, 100, 100],
       [  4,   5,   6, 100, 100]])

分割

x=np.arange(10)
x

np.split
Signature: np.split(ary, indices_or_sections, axis=0)
Docstring:
Split an array into multiple sub-arrays.

這裡說了這裡的返回值是多個子陣列。

>>> x = np.arange(9.0)
>>> np.split(x, 3)
[array([ 0.,  1.,  2.]), array([ 3.,  4.,  5.]), array([ 6.,  7.,  8.])]

這裡也可以切分二維陣列

vsplit

A=np.arange(16).reshape((4,4))
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11],
       [12, 13, 14, 15]])

upper,lower=np.vsplit(A,[2])
upper
array([[0, 1, 2, 3],
       [4, 5, 6, 7]])

lower

lower
lower
Out[81]:
array([[ 8,  9, 10, 11],
       [12, 13, 14, 15]])

hsplit

left,right=np.hsplit(A,[2])
array([[ 0,  1],
       [ 4,  5],
       [ 8,  9],
       [12, 13]])