标簽(空格分隔): 王小草機器學習筆記
python的強大之處不但因為簡潔易學高效,還在于她有許多庫,可以友善我們得到想要的計算。比如今天講的numpy庫,為python提供了快速的多元數組的處理能力。有人數,numpy庫的出現使得python可以像matlab一樣去計算了。(matlab是10年前乃至今日仍然大受青睐的草稿本式的程式設計語言)。
1. 導入Numpy庫
要調用numpy庫,我們就要導入這個庫,導入的語句就一句。
as 後面是重命名,也可以說是縮寫,在我們的程式中,我們隻要寫np,自動就代碼numpy。這是約定俗稱的一個簡稱,當其他人閱讀你的代碼的時候,他們也知道np代表的就是Numpy,是以縮寫最好不要自己創新。
2. 使用Aarry建立數組
2.1 通過Array傳遞List
标準Python的清單(list)中,元素本質是對象。
如:L = [1, 2, 3],需要3個指針和三個整數對象,對于數值運算比較浪費記憶體和CPU。
是以,Numpy提供了ndarray(N-dimensional array object)對象:存儲單一資料類型的多元數組。
建立一維數組:
L = [, , , , , ]
print L
a = np.array(L)
print a
列印結果:
[1, 2, 3, 4, 5, 6]
[1 2 3 4 5 6]
建立多元數組:
嵌套多個list
b = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
print b
列印結果:
[[ 1 2 3 4]
[ 5 6 7 8]
[ 9 10 11 12]]
2.2 數組大小
檢視數組大小
print a.shape
print b.shape
列印結果:
a是6行1列,b是3行4列
(6L,)
(3L, 4L)
強制修改數組大小
1.将3*4的數組改成4*3的數組
b.shape = 4, 3
print b
列印結果:
從(3,4)改為(4,3)并不是對數組進行轉置,而隻是改變每個軸的大小,數組元素在記憶體中的位置并沒有改變,還是按照1,2,3,4,5…12這樣的順序來排列的。
[[ 1 2 3]
[ 4 5 6]
[ 7 8 9]
[10 11 12]]
2.當某個軸為-1時,将根據數組元素的個數自動計算此軸的長度
b.shape = 2, -1
print b
列印結果:
行是2行,列為-1的話就表示根據行來定,是以是6列
[[ 1 2 3 4 5 6]
[ 7 8 9 10 11 12]]
修改數組大小後成新數組
使用reshape方法,可以建立改變了尺寸的新數組,原數組的shape保持不變
c = b.reshape((4, -1))
print c
建立的新數組,仍然與老數組共享記憶體,修改任意一個将影響另外一個。
比如修改b數組的第1行第2列的元素為20,再來看b和c兩個數組的變化
2.3 擷取數組的元素類型
檢視資料類型
print a.dtype
print b.dtype
建立指定元素類型的數組
可以通過dtype參數在建立時指定元素類型
d = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]], dtype=np.float)
f = np.array([[1+4j, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]], dtype=np.complex)
print d
print f
列印結果:分别是浮點型與複數型
[[ 1. 2. 3. 4.]
[ 5. 6. 7. 8.]
[ 9. 10. 11. 12.]]
[[ 1.+4.j 2.+0.j 3.+0.j 4.+0.j]
[ 5.+0.j 6.+0.j 7.+0.j 8.+0.j]
[ 9.+0.j 10.+0.j 11.+0.j 12.+0.j]]
更改元素類型
如果更改元素類型,可以使用astype安全的轉換
f = d.astype(np.int)
print f
列印結果:
[[ 1 2 3 4]
[ 5 6 7 8]
[ 9 10 11 12]]
3. 使用函數建立
3.1 arrage
如果生成一定規則的資料,可以使用NumPy提供的專門函數
arange函數類似于python的range函數:指定起始值、終止值和步長來建立數組
和Python的range類似,arange同樣不包括終值;但arange可以生成浮點類型,而range隻能是整數類型
生成1開始,10結束(不包含10),步長為0.5的一個數組
a = np.arange(, , )
print a
列印結果:
[ 1. 1.5 2. 2.5 3. 3.5 4. 4.5 5. 5.5 6. 6.5 7. 7.5 8.
8.5 9. 9.5]
3.2 linespace
linspace函數通過指定起始值、終止值和元素個數來建立數組,預設包括終止值
b = np.linspace(1, 10, 10)
print b
列印結果:生成了一個1到10,步長為1的等差數列,并且時前閉後閉的。
[ 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.]
可以通過endpoint關鍵字指定是否包括終值 ,預設是包括的。
c = np.linspace(, , , endpoint=False)
print c
列印結果:生成了1到9的10個等差數列
[ 1. 1.9 2.8 3.7 4.6 5.5 6.4 7.3 8.2 9.1]
3.3 logspace
和linspace類似,logspace可以建立等比數列
下面函數建立起始值為10^1,終止值為10^2,有20個數的等比數列
d = np.logspace(, , , endpoint=False)
print d
列印結果:
[ 10. 11.22018454 12.58925412 14.12537545 15.84893192
17.7827941 19.95262315 22.38721139 25.11886432 28.18382931
31.6227766 35.48133892 39.81071706 44.66835922 50.11872336
56.23413252 63.09573445 70.79457844 79.43282347 89.12509381]
下面建立起始值為2^0,終止值為2^10(不包括),有10個數的等比數列
f = np.logspace(, , , endpoint=True, base=)
print f
列印結果:
[
]
3.4 frombuffer, fromstring, fromfile
使用 frombuffer, fromstring, fromfile等函數可以從位元組序列建立數組
s = 'ABCDZ'
g = np.fromstring(s, dtype=np.int8)
列印結果:
[65 66 67 68 90]
4. 存取
4.1 正常辦法
數組元素的存取方法和Python的标準方法相同
首先我們使用arange建立一個數組a
[0 1 2 3 4 5 6 7 8 9]
擷取某個元素
print a[]
擷取索引為3的元素
3
擷取一組元素,切片[3,6),左閉右開
print a[:]
[3 4 5]
省略開始下标,表示從0開始
print a[:]
[0 1 2 3 4]
下标為負表示從後向前數
print a[:]
[3 4 5 6 7 8 9]
取索引[1,8)步長為2
print a[::]
[1 3 5 7]
步長為-1,即翻轉
print a[::-]
[9 8 7 6 5 4 3 2 1 0]
切片資料是原數組的一個視圖,與原數組共享内容空間,可以直接修改元素
a[:] = , ,
print a
[ 0 10 20 30 4 5 6 7 8 9]
4.2 整數數組的存取
根據整數數組存取:當使用整數序列對數組元素進行存取時,
将使用整數序列中的每個元素作為下标,整數序列可以是清單(list)或者數組(ndarray)。
使用整數序列作為下标獲得的數組不和原始數組共享資料空間。
//建立兩個數組
a = np.logspace(, , , base=)
print a
i = np.arange(, , )
print i
//利用i取a中的元素
b = a[i]
print b
列印結果
[ 1. 2. 4. 8. 16. 32. 64. 128. 256. 512.]
[0 2 4 6 8]
[ 1. 4. 16. 64. 256.]
//b的元素更改,a中元素不受影響
b[] =
print b
print a
列印結果:b變了,a不變
[ 1. 4. 1.6 64. 256. ]
[ 1. 2. 4. 8. 16. 32. 64. 128. 256. 512.]
4.3 布爾數組的存取
使用布爾數組i作為下标存取數組a中的元素:傳回數組a中所有在數組b中對應下标為True的元素
首先生成10個滿足[0,1)中均勻分布的随機數
a = np.random.rand()
print a
[ 0.84334711 0.54587789 0.41350371 0.73992619 0.00475762 0.0972838
0.0522206 0.6696739 0.33550459 0.64959176]
大于0.5的元素索引
print a >
[ True True False True False False False True False True]
大于0.5的元素,列印出了一組布爾類型的值,符合條件的為true
b = a[a > ]
print b
[ 0.84334711 0.54587789 0.73992619 0.6696739 0.64959176]
将原數組中大于0.5的元素截取成0.5
a[a > ] =
print a
//b不受影響
print b
[ 0.5 0.5 0.41350371 0.5 0.00475762 0.0972838
0.0522206 0.5 0.33550459 0.5 ]
[ 0.84334711 0.54587789 0.73992619 0.6696739 0.64959176]
4.4 二維數組的切片
生成二維數組
若我們想生成以下這樣一個多元數組:
[[ 0 1 2 3 4 5]
[10 11 12 13 14 15]
[20 21 22 23 24 25]
[30 31 32 33 34 35]
[40 41 42 43 44 45]
[50 51 52 53 54 55]]
可以經過以下幾步
先生成行向量,0到60,步長為10的數組。
[ 0 10 20 30 40 50]
将行向量,轉化成列向量
[[ 0]
[10]
[20]
[30]
[40]
[50]]
生成一個0到5,步長為1的行向量
[0 1 2 3 4 5]
将列向量b每一列都c行向量
f = b + c
print f
[[ 0 1 2 3 4 5]
[10 11 12 13 14 15]
[20 21 22 23 24 25]
[30 31 32 33 34 35]
[40 41 42 43 44 45]
将上面所有步驟合起來可以用一句代碼表示:
a = np.arange(, , ).reshape((-, )) + np.arange()
二維數組的切片
//大括号裡,前面的list表示行的索引,後面的list表示列的索引
//比如第一個數提取的是行索引為0列索引為2
print a[(,,,), (,,,)]
//擷取行号從3開始(包括3),列号是0,2,5的元素
print a[:, [, , ]]
//建立布爾類型的數組
i = np.array([True, False, True, False, False, True])
//擷取為true的行
print a[i]
//擷取為true的行的列索引為3的元素
print a[i, ]
列印結果:
[ 2 13 24 35]
[[30 32 35]
[40 42 45]
[50 52 55]]
[[ 0 1 2 3 4 5]
[20 21 22 23 24 25]
[50 51 52 53 54 55]]
[ 3 23 53]
5. 繪圖
5.1 繪制正态分布機率密度函數
mu = //均值
sigma = //标準差
//建立一個50個元素的數組,收尾與均值相差三個标準差
x = np.linspace(mu - * sigma, mu + * sigma, )
//根據正太分布的公式寫出y
y = np.exp(-(x - mu) ** / ( * sigma ** )) / (math.sqrt( * math.pi) * sigma)
//以x,y為橫縱坐标,'r-'表示紅色線,'ro-表示紅色線加原點',linewidth為線的粗細度
#plot.plot(x, y, 'ro-', linewidth=2)
//或者也可以:用'go'表示綠色原點,markersize為原點大小
plot.plot(x, y, 'r-', x, y, 'go', linewidth=, markersize=)
//有灰色格子
plot.grid(True)
//畫出來吧,少年!
plot.show()
圖形如下:
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIn5GcuMDNyIjNxUDM5AjNxAjMFJUJClTJ1UUJBFUJ4gTJ2UUJRF1LcFzb5NXZ3lXb6d3btRXcpxGNmBje1smZw9CXvF2Yn5WY39CXt92Yu8WdsVnY5pnLjlGdhR3cvw1LcpDc0RHaiojIsJye.png)
接下去,我們再來看幾個好玩的畫圖案例
5.2 損失函數:Logistic損失(-1,1)/SVM Hinge損失/ 0/1損失
x = np.linspace(-, , )
y_logit = np.log( + np.exp(-x)) / math.log()
y_01 = x <
y_hinge = - x
y_hinge[y_hinge < ] =
//label表示标記
plot.plot(x, y_logit, 'r-', label='Logistic Loss', linewidth=)
plot.plot(x, y_01, 'g-', label='0/1 Loss', linewidth=)
plot.plot(x, y_hinge, 'b-', label='Hinge Loss', linewidth=)
plot.grid()
//标記的放的位置,這裡是右上角
plot.legend(loc='upper right')
plot.show()
圖形畫出來如下:
5.3 x^x
x = np.linspace(-1.3, 1.3, 101)
y = f(x)
plot.plot(x, y, 'g-', label='x^x', linewidth=2)
plot.grid()
plot.legend(loc='upper right')
plot.show()
5.4 胸型線
(前方高能。。。)
x = np.arange(, , -)
y = (- * x * np.log(x) + np.exp(-( * (x - / np.e)) ** ) / ) /
//設定畫布大小
plot.figure(figsize=(,))
plot.plot(y, x, 'r-', linewidth=)
plot.grid(True)
plot.show()
這個圖太辣眼睛了。。。男生心裡估計已經浮現過ABCDEF了。。
5.5 心形線
t = np.linspace(, , )
x = * np.sin(t) **
y = * np.cos(t) - * np.cos(*t) - * np.cos(*t) - np.cos(*t)
plot.plot(x, y, 'r-', linewidth=)
plot.grid(True)
plot.show()
嗯,這個圖美,願大家有情人終成眷屬
5.6 漸開線
t = np.linspace(, , num=)
x = t*np.sin(t) + np.cos(t)
y = np.sin(t) - t*np.cos(t)
plot.plot(x, y, 'r-', linewidth=)
plot.grid()
plot.show()
關于畫函數圖,總結規律,其實就是,設定一個x的變量,然後根據某種公式用x得到y的分布,然後把x,y用Plot函數套進去,什麼顔色啊,圓點啊,線條粗細啊之類的都可以套模闆寫。棒棒棒!