在昨天的文章中介紹完如何繪製基本的圖形之後,今天來看看一些特別的應用
還記得我們在 [Day 8] 梯度下降法 當中有提到等高線圖嗎?
現在我們就來看看怎麼在 Matplotlib 上面畫出類似的圖形吧!
在等高線圖上,x 與 y 軸分別代表著兩個維度的位置,而在這個二維平面上的顏色,就代表著高度。假設平面上每一個點的高度,是 x 與 y 的函數,因此可以寫成
height = f(x, y)
這裡我們先隨便產生一個函數
f(x, y) = (1 - x / 2 + y / 10 + x**2 + 3 * y**2)
到底畫出來會長什麼樣子我也不知道,不過我們就先繼續往下走
為了要讓 Matplotlib 知道要呈現哪個範圍的圖形,因此我們要產生出兩組陣列,分別代表 x 軸與 y 軸的範圍。這裡我們用 NumPy 中的一個方法 .linspace
,他能夠幫我們在指定的範圍內產生出等差數列。
譬如我們想要在 1 到 100 這個範圍內(包含頭尾)產生出擁有 10 個數的等差數列,因此可以將 1
, 100
, 10
帶入
x = np.linspace(1, 100, 10)
會得到結果
[ 1. 12. 23. 34. 45. 56. 67. 78. 89. 100.]
這裡我們一口氣在 x 正負 50,與 y 正負 50 之間創造分別創造數量為 1000 的等差數列(可以想像圖上就會有密密麻麻的資料點)
n = 1000
x = np.linspace(-50, 50, n)
y = np.linspace(-50, 50, n)
這裡我們使用 NumPy 中的 .meshgrid
來幫我們建立網格,先舉格簡單的例子來示範,假設我們分別有個 x 與 y 的陣列如下
x = np.array([0,1,2,3,4,5])
y = np.array([0,2,4,6,8,10])
接著我們可以利用 np.meshgrid()
分別產生 X, Y 網格
X,Y = np.meshgrid(x, y)
如果分別印出 X 與 Y 的話,會長得像下面這樣
#X
[[0 1 2 3 4 5]
[0 1 2 3 4 5]
[0 1 2 3 4 5]
[0 1 2 3 4 5]
[0 1 2 3 4 5]
[0 1 2 3 4 5]]
#Y
[[ 0 0 0 0 0 0]
[ 2 2 2 2 2 2]
[ 4 4 4 4 4 4]
[ 6 6 6 6 6 6]
[ 8 8 8 8 8 8]
[10 10 10 10 10 10]]
看到這裡可能你還看不出個所以然,如果把 X 和 Y 放入昨天提到的 .plot()
當中,應該就會比較有感覺一點
plt.plot(X, Y, marker="o", color="red", linestyle="none")
plt.show()
結果如下:
最後,讓我們把所有東西都組裝在一起,然後用 plt.contourf()
來繪製等高線圖
#載入套件
import numpy as np
import matplotlib.pyplot as plt
#高度函數
def f(x,y):
return (1 - x / 2 + y / 10 + x**2 + 3 * y**2)
#建立網格
n = 1000
x = np.linspace(-50, 50, n)
y = np.linspace(-50, 50, n)
X,Y = np.meshgrid(x, y)
#繪製等高線圖
plt.contourf(X, Y, f(X, Y), 10, alpha=.6, cmap=plt.cm.jet)
plt.show()
plt.contourf
前面的三個參數 X
, Y
, f(X, Y)
分別是 x 軸的網格、y 軸的網格、以及網格上的點的值(高度)。
第四個參數 10
決定了這張圖上要有幾層的等高線,數字越大,圖面上等高線的密度就會越高。第五個參數 alpha 決定顏色的透明度。第六參數 cmap
,也就是 colormap,決定了等高線圖的顏色組成
結果如下:
如果我們把剛剛的第四個參數改成 50
,就會變成下面這樣(看了讓人頭有點暈呢)
如果我們把剛剛的第六個參數 cmap=plt.cm.jet
改成 cmap=plt.cm.hot
,就會變成下面這樣
你可以在這裡 找到更多的顏色組合
讓我們為這張等高線圖再加點料吧!首先用 plt.contour
(注意這裡不是 plt.contourf
喔)來真正畫出等高線,待會你會發現剛剛的顏色只是代表著某兩個等高線中間的區間而已。
C = plt.contour(X, Y, f(X, Y), 8, colors='black')
接著在等高線上加上 label,也就是該等高線的值
plt.clabel(C, inline=True, fontsize=10)
就會得到下面的結果!
Matplotlib 幫助我們將資料視覺化呈現,也讓我們對於手上正在處理的數據更有感覺。過去我們在談到「梯度下降法」時有提到等高線圖,未來我們也將有機會看到我們的程式是如何跟著等高線圖上的梯度,慢慢的下降,抵達理想中的終點。
當然程式不是真的看著「地圖(等高線圖)」下去走的,而是透過我們寫好的程式與參數逐步前進。
我們明天就會開始嘗試用 Python 寫一個程式,讓機器利用梯度下降法,來找到損失函數最低的地方!明天見囉!