一、Jupyter Notebook的魔法命令
# 模塊/方法 + ?或者help(模塊/方法):查看模塊/方法的解釋文檔;
1)%run
# 機械學習中主要應用兩個魔法命令:%run、%timeit
# 魔法命令格式:% + 命令
# %run:將模塊引用並在Jupyter Notebook中執行(這是與import的區別),模塊被引用后,其內部的函數可以在Jupyter Notebook中直接被引用;
# 格式:%run + 文件的地址 + 文件名
2)%timeit
- 測試代碼的性能,后面只能接一條語句/代碼塊,得出運行此條語句或代碼塊所用的時間;
- %timeit + 一條語句:測試該條語句運行所用時間;
- %%timeit:表示測試在該單元格內的全部代碼運行時所用時間;
- %timeit、%%timeit,一般是將代碼運行多遍,然后去取執行最快的幾次的平均值;
- 如果%timeit和%%timeit后面的代碼,每次運行的效率不同,則測量的結果又偏差;
- %time,返回只將代碼運行一遍所用時間;但這樣的測試結果不穩定,每次測得結果差異很大,但對於一次測試用時較長的代碼/算法,測試差異可以忽略;
3)其它
- 命令 + ?:查看命令的文檔;
- 可以通過%lsmagic查看素有的魔法命令;
- 機器學習算法中,scikit-learn中的函數封裝的都是接收一個Numpy的矩陣,通常使用Pandas對數據進行預處理,將Pandas數據轉換為Numpy的矩陣,再送給機械學習的算法;
二、numpy.array基礎
1)numpy.array的基礎
- python的list數據非常靈活,運行效率較低,因為系統需要檢測其中所有數據的類型;
- Python中的array模塊,可以限定只存儲一種數據類型:
import array arr = array.array('i', [i for i in range(10)]) # 其中'i'表示數據類型為整數 print(type(arr[5])) # 5 arr[5] = 'a' # 報錯,arr內的數據只能賦值為整數
- Python的array模塊缺陷:1)中沒有將數據看成向量或矩陣,因此也沒有向量和矩陣相關的運算;2)只有一種數據類型,不夠靈活使用;
- numpy模塊的array方法,可以進行向量和矩陣的運算;
- numpy模塊的array方法創建的數據,只能是整數,若將小數賦值給array方法創建的數據時,會自動轉換為整數;
- 機械學習中所操作的大多數數值為浮點數;
2)np.array的創建
A、創建全0數組
- np.zeros(10):默認為float64類型的一維全0數組;
array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])
- np.zeros(10, dtype = int):數據類型為int的一維全0數組;
array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
- np.zeros((3, 5)):默認fioat64類型的3行5列的矩陣;
array([[0., 0., 0., 0., 0.], [0., 0., 0., 0., 0.], [0., 0., 0., 0., 0.]]) - np.zeros(shape = (3, 5), dtype = int)或者np.zeros( dtype = int, shape = (3, 5)):類型為int的3行5列的矩陣;
array([[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]])
B、創建全1的數組
- np.ones(),操作方法同理全0矩陣的創建;
C、創建所有值都相同的數組
- np.full((3, 5), 666)或者np.full(shape = (3, 5), fill_value = 666)或者np.full(fill_value = 666, shape = (3, 5)):默認為int;
array([[666, 666, 666, 666, 666], [666, 666, 666, 666, 666], [666, 666, 666, 666, 666]]) - np.full(10, 666)或者np.full(shape = 10, fill_value = 666)或者np.full(fill_value = 666, shape = 10):
array([666, 666, 666, 666, 666, 666, 666, 666, 666, 666])
D、numpy中arange的用法:參數的用法與python中range的參數用法一樣
- np.arange(0, 10):默認步長為1;
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
- np.arange(10):默認起始值為0,默認步長為1;
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
- np.arange(0, 10, 2):取值間隔為2;
array([0, 2, 4, 6, 8])
- np.arange(0, 1, 0.2):步長可以為小數,0.2,而python中的range的參數,步長不能為小數;
rray([0. , 0.2, 0.4, 0.6, 0.8])
- range()生成列表,np.arange()生成數組;
E、numpy中linspace的用法,與arange類似
- np.linspace(0, 20, 10):將0~20間的數等分10個點,首尾分別是0和20,此處10不是步長,而是將區間等分的點數(包含首尾數值);
array([ 0. , 2.22222222, 4.44444444, 6.66666667, 8.88888889, 11.11111111, 13.33333333, 15.55555556, 17.77777778, 20. ])
F、numpy中random的用法:生產隨機int數random.randint()
- 區間為前閉后開:[m,n);
- 隨機生成的數據給算法時,運行的結果不一致,導致調試困難;
- 計算機中,所有的隨機數都是偽隨機數,都是隨機算法實現的;推動算法生產隨機數的是隨機種子:同一個隨機種子生產的隨機數是一定的,再次調用該種子時可以得到上一次該種子生產的隨機數;
- np.random.randint(0, 10):從0~10間隨機生產一個z
5
- np.random.randint(0, 10, 5):從0~10間隨機生成5個int類型的數;
array([8, 6, 3, 3, 6])
- np.random.randint(4, 8, size = 10):一般標出size = 10,提高代碼可讀性;
array([6, 5, 6, 7, 4, 7, 7, 6, 5, 5])
- np.random.randint(4, 8, size = (3, 5)):從[4, 8)中,隨機生成3行5列的矩陣;
array([[7, 7, 5, 5, 5], [5, 7, 5, 7, 4], [6, 6, 4, 6, 5]]) - 隨機種子的使用
# Jupyter Notebook中實現的代碼 np.random.seed(666) np.random.randint(4, 8, size = (3, 5)) # 設定隨機種子,並生成隨機數據 np.random.seed(666) np.random.randint(4, 8, size = (3, 5)) # 再次調用該種子,並再次生成原來格式的隨機數據,所得到的數據與第一次隨機生成的數據相同;
G、numpy中random的使用:生成隨機float數random.random()
- 生成的float數為0~1的隨機數;
- random.random()的操作格式與random.randint()一樣;
H、numpy中random的使用:隨機生產滿足正態分布的folat數;
# 正態分布:均值為0,方差為1的分布規律;
- np.random.normal():默認為-1~1,默認均值為0方差為1,隨機取一個數;
-0.770927518770882
- np.random.normal(10, 100):默認均值為10方差為100,隨機取一個數;
-213.49687669162455
- np.random.normal(0, 1, (3, 5))或者np.random.normal(0, 1, size = (3, 5)):
array([[ 1.42965241, -0.41407013, -1.32672274, -0.14880188, 0.34771289], [ 0.61030791, -1.17532603, 0.82985368, -0.30236752, -0.04327047], [ 0.06706965, -1.59102817, 0.01705112, -1.87296591, -0.96457904]])
I、創建空矩陣
- np.empty(shape = (m, n), dtype = float):創建一個m行n列,數據類型為float的空矩陣;
3)np.array的元素訪問
- np.aange(15).reshape(3, 5):將一維數組轉換為多維數組;此處必須是3 X 5 = 15,數據總數不變;
array([[ 0, 1, 2, 3, 4], [ 5, 6, 7, 8, 9], [10, 11, 12, 13, 14]])
A、array的基本屬性
# np.arange(15).reshape(3, 5) == np.arange(15).reshape(3, -1)
- array.ndim:返回array的維度;
- array.shape:返回array的行數和列數;
# Jupyter Notebook中的代碼 import numpy as np x = np.arange(15).reshape(3, 5) x.shape # (3, 5)
- array.size:返回數組元素個數;
B、numpy.array的數據訪問
- 訪問一維數組的一個:用 [ ] 進行引索,方式與python中訪問列表元素一樣;
- 訪問一維數組的一段連續的數據:采用切片,方式與python中訪問列表元素一樣;
import numpy as np arr = np.arange(10) print(arr[5:]) # 輸出:array([5, 6, 7, 8, 9]) print(arr[::2]) # 輸出:array([0, 2, 4, 6, 8]) print(arr[::-1]) # 輸出:array([9, 8, 7, 6, 5, 4, 3, 2, 1, 0])
- 訪問多維數組中的一個元素:arr[m, n],訪問數組arr中第m + 1行與第n + 1列所對應的元素;
- 訪問多維數組中的一段連續的元素:
import numpy as np arr = np.arange(15).reshape(3, 5) print(arr[:2, :3]) # 輸出:array([[0, 1, 2], [5, 6, 7]]) print(arr[:2]) # 輸出:array([[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]]) print(arr[:2, ::2]) # 輸出:array([[0, 2, 4], [5, 7, 9]]) print(arr[::-1, ::-1]) # 輸出:array([[14, 13, 12, 11, 10], [ 9, 8, 7, 6, 5], [ 4, 3, 2, 1, 0]])
- 由sub生成的子矩陣,是直接引用的原矩陣,並沒有生成一個真實的矩陣,這樣可提高數據的生成效率;
- 由sub生成的子矩陣更改是,子矩陣所引用(通過引用生成的子矩陣,而不是新建立)的矩陣也跟着更改;相同,更改矩陣后,引用它所生成的子矩陣也相應更改;
arr = np.arange(15).reshape(3, 5) subarr = arr[:2, :3] print(subarr) # 輸出:array([[0, 1, 2], [5, 6, 7]]) subarr[0, 0] = 100 print(arr) # 輸出:array([[100, 1, 2, 3, 4], [ 5, 6, 7, 8, 9], [ 10, 11, 12, 13, 14]]) arr[0, 0] = 20 print(subarr) # 輸出:array([[20, 1, 2], [ 5, 6, 7]])
- 子矩陣.copy():將子矩陣數據在磁盤中真實生成;再更改子矩陣時,對應的原矩陣不再跟着更改;
4)numpy.array的合並
#一維數組和向量都是一行,但向量是二位,可以通過reshape將一維數組轉換為二位向量:arr.reshape(1, n);
A、np.concatenate
- 連接兩個一維數組:np.concatenate([arr1, arr2]),仍然為一維數組;
import numpy as np a = np.array([1, 2, 3]) b = np.array([4, 5, 6]) c = np.concatenate([a, b]) print(c) # 輸出:array([1, 2, 3, 4, 5, 6])
- 連接兩個二維數組:默認axis = 0,增加行數;axis = 1,增加列數; 當列數不相等的兩個數組,只能連接增加列數;
import numpy as np a = np.array([[1, 2, 3], [4, 5, 6]]) b1 = np.concatenate([a, a]) print(b1) #array([[1, 2, 3], [4, 5, 6], [1, 2, 3], [4, 5, 6]]) b2 = np.concatenate([a, a], axis = 1) print(b2) # array([[1, 2, 3, 1, 2, 3], [4, 5, 6, 4, 5, 6]])
- np.vstack([arr1, arr2]),兩數組垂直相加,增加行數;
a = np.arange(15).reshape(5, 3) b = np.arange(3) # 將b矩陣堆疊成和a矩陣行數相等; c = np.vstack([b] * a.shape[0]) # array([[0, 1, 2], [0, 1, 2], [0, 1, 2], [0, 1, 2], [0, 1, 2]])
- np.hstack([arr1, arr2]),兩數組水平相加,增加列數;
import numpy as np # 創建全 1 向量:np.ones((m, n), dtype),(m, n) m 行 n 列,必須用tuple類型,不能用list類型,不然會報類型錯誤:data type not understood x = np.random.random(size=100).reshape(-1, 1) y = np.ones((len(x), 1), dtype = float) z = np.hstack([x, y])
5)numpy.array的分割
A、一維數組分割:分割點是數組中的數據的位號,而且必須為數組格式;
- 分成兩斷:
a = np.arange(10) a1, a2 = np.aplit(a, [5]) print(a1, a2) #array([0, 1, 2, 3, 4]) array([5, 6, 7, 8, 9])
- 分成多段:
a = np.arange(10) a1, a2, a3 = np.aplit(a, [3, 6]) print(a1, a2) #array([0, 1, 2]) array([4, 5, 6]) array([7, 8, 9])
B、分割二位數組:
- 默認垂直分割,即axis = 0:把行數等分,若行數為奇數,第一個數組多一行;
a = np.arange(15).reshape(3, 5) a1, a2 = np.split(a, [2]) print(a1, a2) # array([[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]]) # array([[10, 11, 12, 13, 14]])
- 水平分割,axis = 1:與一維數組分割方式一樣,分割點為第一行數據中的位號(序號);
a = np.arange(15).reshape(3, 5) a1, a2 = np.split(a, [3], axis = 1) print(a1, a2) # array([[ 0, 1, 2], [ 5, 6, 7], [10, 11, 12]]) # array([[ 3, 4], [ 8, 9], [13, 14]])
- 直接垂直分割:np.vsplit();
- 水平分割:np.hsplit(),不用指定axis的值;
- #數據分割的意義:可以將數據集中的特征樣本和標志分離開;
6)numpy.array的具體運算
A、numpy.array的加、減、乘、除法運算,array可以做為除數,也可以作為被除數
#與數組中的每個元素相乘;
#Python中的list直接與數字相乘,是把list中的數據復制對應次數,而不是與list數據中的每個數相乘;
# np.array的運算比Python中的list的運算效率高很多;
B、numpy.array的其它函數運算
- np.abs(array):向量中的所有元素取絕對值
- np.var(array):向量中所有元素的方差
- np.std(array):向量的均方差
- np.linalg.inv(array):矩陣的逆矩陣
- np.sin/cos/tan/cot(array):向量中的所有元素進行三角函數運算;
- np.mean(array):向量的平均值;
- np.exp(array):向量中的所有元素作為e的冪;
- np.power(3, array) == 3 ** array:向量中的所有元素作為3的冪;
- np.log5(array):對向量中的所有元素取5的對數;
- np.log(array):對向量中的所有元素取e的對數;
- len(array):返回矩陣的行數,或者向量的元素個數
C、向量與矩陣之間的運算
- array.T:將矩陣轉置;
- 向量 + 矩陣:
a = np.arange(15).reshape(5, 3) b = np.arange(3) print(a + b) # array([[ 0, 2, 4], [ 3, 5, 7], [ 6, 8, 10], [ 9, 11, 13], [12, 14, 16]])
- 向量 * 矩陣:
a = np.arange(15).reshape(5, 3) b = np.arange(3) print(a + b) # array([[ 0, 1, 4], [ 0, 4, 10], [ 0, 7, 16], [ 0, 10, 22], [ 0, 13, 28]])
- 矩陣與矩陣間的運算:必須滿足矩陣運算的條件,與線性代數規則一樣;格式:arr1.dot(arr2)、arr2.dot(arr1);
- 在numpy模塊中,一維數組,即可以看成一行,也可以看做是一列;
- 求逆矩陣:np.linalg.inv(array);(逆矩陣必須滿足一定的條件)
- 逆矩陣 * 原矩陣、原矩陣 * 逆矩陣 == 單位矩陣;
- 偽逆矩陣:一些沒有逆矩陣的矩陣,可以求其偽逆矩陣:np.linalg.pinv(array),偽逆矩陣 * 原矩陣 == 偽單位矩陣(對角線的數為1,其余數不為0);
7)numpy中的聚合運算
# 聚合:將一組數合並成一個數;
# Python中的sum()函數運算效率,遠低於numpy.sum()方法;
A、向量的聚合
- np.sum(array):將數組中的所有書相加;
- np.min/max(array):求數組中的最小值/最大值;
- 也可以:big_array.sum/min/max(),求值,只是方式不一樣,但一般使用np.min(),增加代碼的可讀性;
B、矩陣的聚合
- np.sum/min/max(array),對整個矩陣進行聚合;
- np.sum/min/max(array, axis = 1):對矩陣各行進行聚合;
x = np.arange(16).reshape(4, 4) y = np.sum(x, axis = 1) print(y) # array([ 6, 22, 38, 54])
- np.sum/min/max(array, axis = 0):對矩陣各列進行聚合;
x = np.arange(16).reshape(4, 4) y = np.sum(x, axis = 1) print(y) # array([24, 28, 32, 36])
- np.prod(array):將矩陣中所有元素相乘;
- np.prod(array + 1):先將矩陣中的所有元素都加1,再講所有元素相乘;
- np.mean(array):求矩陣所有元素的平均值;
- np.median(array):求矩陣所有元素的中位數;
- np.percentile(big_array, q = 30):求百分位點的值,矩陣中30%的值都小於此數;
- np.percentile(big_array, q = 50) == np.median(array)、np.percentile(big_array, q = 100) == np.max(array);
- 一般看一組數的5個百分位點的值,就可大致看出此組數的分布情況:
x = np.random.randint(0, 100, 200) for percent in [0, 25, 50, 75, 100]: print(np.percentile(x, q = percent))
- 求方差:np.var(big_array);
- 求標准差:np.std(big_array);
8)numpy中的arg運算
A、求數據的索引位置
- np.argmin/argmax(array):求矩陣中最小/大值在矩陣中的位置;
B、排序和使用索引
- 出向量進行亂序處理:np.random.shuffle(array),將向量中的數據順序打亂;
- 對向量中的數據進行排序處理:np.sort(array),此方法是返回了一個新的排好序的array,原來的array並沒有改變;
- array.sort():對向量本身進行排序;
- np.sort(array):對矩陣進行排序,默認(axis = 1)每一行為一組數據單獨排序;
- np.sort(array, axis = 0):對矩陣的每一列進行排序;
- np.argsort(array):對向量進行排序,返回一個新的數組,新的數組中為原數組元素排序號的元素序號;
x1 = np.arange(15) np.random.shuffle(x1) x2 = np.argsort(x1) print(x1, x2) # array([ 3, 13, 4, 2, 8, 12, 6, 14, 11, 5, 1, 7, 10, 0, 9]) # array([13, 10, 3, 0, 2, 9, 6, 11, 4, 14, 12, 8, 5, 1, 7], dtype=int64)
- np.partition(array, n):對數組中的數進行排序,小於n的數在左側,大於n的數在右側,左右兩側的數即不按大小順序排列也不在按原來位置排列;一般多用於求數組中比某一值大/小的數;
x1 = np.arange(15) np.random.shuffle(x1) x2 = np.argsort(x1) print(x1, x2) # array([ 4, 9, 10, 8, 11, 7, 13, 2, 5, 3, 6, 1, 0, 12, 14]) # array([ 3, 2, 0, 1, 4, 5, 6, 7, 8, 10, 9, 11, 13, 12, 14])
- np.argpartition(array, n):返回x2數組中各元素在x1數組中的位置,與np.partition(array, n)的功能一樣;
x1 = np.arange(15) np.random.shuffle(x1) x2 = np.argsort(x1) print(x1, x2) # array([ 4, 9, 10, 8, 11, 7, 13, 2, 5, 3, 6, 1, 0, 12, 14]) # array([ 3, 2, 0, 1, 4, 5, 6, 7, 8, 10, 9, 11, 13, 12, 14]) # array([ 9, 7, 12, 11, 0, 8, 10, 5, 3, 2, 1, 4, 6, 13, 14], dtype=int64)
- np.argsort(array, axis = 1):對矩陣進行排序,返回各數據在原矩陣中的位置,axis默認為1,表示按進行排序;
- np.argsort(array, axis = 0):按列進行排序;規則同上;
9)Numpy中的比較和Fancy Indexing
A、索引一維數組中的任意數
- 索引是一維數組:ind = [1, 2, 5, 7, 8]
x = np.arange(16) # 目標數在數組中對應的位置序號 ind = [1, 2, 5, 7, 8] print(x[ind]) # array([1, 2, 5, 7, 8])
- 索引是二維數組,則生成一個二維數組:ind = np.arange(4).reshape(2, 2);
x = np.arange(16) # 目標數在數組中對應的位置序號 ind = np.arange(4, 8).reshape(2, 2) print(x[ind]) # array([[4, 5], [6, 7]])
B、索引二位數組中的任意數
- 只索引其中的某幾行:
import numpy as np X = np.arange(16).reshape(4, -1) # 1)索引一行:X[2] == X[2, :] y1 = X[2] print(y1) # array([ 8, 9, 10, 11]) # 2)索引某幾行 row = np.array([0, 1, 2]) y2 = X[row] print(y2) # array([[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11]])
- 只索引其中的某幾列:
import numpy as np X = np.arange(16).reshape(4, -1) # 1)索引一列:X[:, 2] y1 = X[:, 2] print(y1) # array([ 2, 6, 10, 14]) # 2)索引某幾列:X[:, array] row = np.array([0, 1, 2]) y2 = X[:, row] print(y2) # array([[ 0, 1, 2], [ 4, 5, 6], [ 8, 9, 10], [12, 13, 14]])
- 將目標數據在矩陣中的行號和列號,分別寫在兩個數組中:
X = np.arange(16).reshape(4, -1) row = np.array([0, 1, 2]) col = np.array([1, 2, 3]) # 獲取矩陣中的任意數據 print(X[row, col]) # array([1, 6, 11]) # 獲取矩陣中的某一行內的幾個數據 print(X[0, col]) # array([1, 2, 3]) # 獲取矩陣中前兩行數據中的某些數 print(X[:2, col]) # array([1, 2, 3], [5, 6, 7])
- 使用布爾數組進行引索:
X = np.arange(16).reshape(4, -1) col = array([True, False, True, True]) # 只對數組中為True的列/行進行引索 print(X[1:3, col]) # array([[4, 6, 7], [8, 10, 11]])
C、比較
- array與一個數比較:將array中的所有數據與該數比較,返回布爾數組;
x = np.arange(16) print(x < 5) # array([ True, True, True, True, True, False, False, False, False, False, False, False, False, False, False, False])
- array與array比較:兩數組中的元素個數相等,對應元素進行比較,返回布爾數組;
x1 = np.array([5, 4, 3, 2, 1]) x2 = np.array([1, 2, 3, 4, 5]) print(x1 > x2) # array([ True, True, False, False, False])
- array經過運算后,與一個數或者另一個array比較:規則同理運算前的比較;
- np.sum(array < 5):獲取array中小於5的數的個數;
- np.count_nonzero(array < 5):返回()內的布爾數組中非0元素的個數;
- np.any(array == 0):只要()內的布爾數組中有True,返回True,否則返回False;多用於查看array中是否有0元素;# np.any()的用法;
- np.all(array > 0):只有()內的布爾數組全為True,返回True,只要有一個False,則返回False;# np.all()的用法;
- np.sum(array % 2 == 0):獲取矩陣中偶數的個數;
- np.sum(array % 2 == 0, axis = 1):獲取矩陣每一行中偶數的個數;
- np.sum(array % 2 == 0, axis = 0):獲取矩陣每一列中偶數的個數;
- np.sum((array >3) & (array < 10)):獲取array中大於3且小於10的元素的個數;此處用“&”符號,相當於“and”;
- np.sum((array % 2 == 0) | (array > 10)):獲取array中偶數與大於10的數的個數;此處用“|”符號,相當於“or”;
- np.sum(-(array == 0)):獲取array中非0的數的個數;此處用“-”符號,相當於“not”;
- axis = 0:對矩陣中的每一列進行操作;axis = 1:對矩陣中的每一行進行操作;適用於所有方法;
- 二維矩陣的比較運算規則,與一維數組相同;
