熱門文章

2019年2月4日 星期一

Matplotlib 繪圖技巧:三張小圖並列

作者:王一哲
日期:2019/2/4

以下是將在三張小圖並列在同一張圖中的作法,部分內容與〈Matplotlib 繪圖技巧:在同一張圖上繪製兩個函數、兩張圖並列〉相似,但使用兩種不同的作法。這次要畫的圖形是在人工神經網路中常用的激勵函數 (activation function):
$$sigmoid:~~~~~f(x) = \frac{1}{1 + e^{-x}}$$
$$ReLU:~~~~~f(x) = \left\{\begin{matrix}
0 & \mathrm{for}~x < 0\\ x & \mathrm{for}~x \ge 0 \end{matrix}\right.$$ $$tanh:~~~~~f(x) = tanh(x)$$
三種激勵函數圖形





方法1: 用 subplot 切換繪圖位置


import matplotlib.pyplot as plt
import numpy as np

# 產生陣列x, sigmoid, relu, tanh
xmin, xmax, num = -6, 6, 200
x = np.linspace(xmin, xmax, num)

sigmoid = 1 / (1 + np.exp(-x))
# 不能寫成 relu = x, 這樣會改變 x 的數值
relu = x.copy()
relu[np.where(relu < 0)] = 0
tanh = np.tanh(x)

plt.figure(figsize = (12, 3), dpi = 72)
plt.subplots_adjust(left = 0.1, bottom = 0.2, right = 0.9, top = 0.9, wspace = 0.4, hspace = 0.1)

plt.subplot(131)
plt.plot(x, sigmoid, color = 'blue', linestyle = '-', linewidth = 3)
plt.xlabel('x', fontsize = 14)
plt.ylabel('f(x)', fontsize = 14)
plt.xlim(xmin,xmax)
plt.tick_params(axis = 'both', which = 'major', labelsize = 10)
plt.title('Sigmoid', fontsize = 14)
plt.grid('on')

plt.subplot(132)
plt.plot(x, relu, color = 'blue', linestyle = '-', linewidth = 3)
plt.xlabel('x', fontsize = 14)
plt.ylabel('f(x)', fontsize = 14)
plt.xlim(xmin,xmax)
plt.tick_params(axis = 'both', which = 'major', labelsize = 10)
plt.title('ReLU', fontsize = 14)
plt.grid('on')

plt.subplot(133)
plt.plot(x, tanh, color = 'blue', linestyle = '-', linewidth = 3)
plt.xlabel('x', fontsize = 14)
plt.ylabel('f(x)', fontsize = 14)
plt.xlim(xmin,xmax)
plt.tick_params(axis = 'both', which = 'major', labelsize = 10)
plt.title('tanh', fontsize = 14)
plt.grid('on')

plt.savefig('subplots.svg')
plt.savefig('subplots.png')
plt.show()



以下說明程式碼中較特別的部分

  1. 產生陣列 relu 時分為兩個步驟,先用 relu = x.copy() 將 x 的值複製給 relu,如果寫成 relu = x,之後變 relu 的數值時 x 的數值會跟著變化;接著再用 relu[np.where(relu < 0)] = 0 將小於 0 的元素都改成 0。
  2. 使用 plt.subplots_adjust 調整圖片的空間配置。
  3. 使用 plt.subplot 切換繪圖的位置,例如 (132) 代表整張圖中有 1 列、3 欄的小圖,目前繪製第 2 張圖。




方法2: 用 plt.subplots


import matplotlib.pyplot as plt
import numpy as np

# 產生陣列x, sigmoid, relu, tanh
xmin, xmax, num = -6, 6, 200
x = np.linspace(xmin, xmax, num)

sigmoid = 1 / (1 + np.exp(-x))
# 不能寫成 relu = x, 這樣會改變 x 的數值
relu = x.copy()
relu[np.where(relu < 0)] = 0
tanh = np.tanh(x)

fig, (ax1, ax2, ax3) = plt.subplots(1, 3, sharex = True, figsize=(12, 3), dpi = 72)
fig.subplots_adjust(left = 0.1, bottom = 0.2, right = 0.9, top = 0.9, wspace = 0.4, hspace = 0.1)

ax1.plot(x, sigmoid, color = 'blue', linestyle = '-', linewidth = 3)
ax1.set_xlabel('x', fontsize = 14)
ax1.set_ylabel('f(x)', fontsize = 14)
ax1.set_xlim(xmin,xmax)
ax1.tick_params(axis = "both", labelsize = 10)
ax1.set_title('Sigmoid', fontsize = 14)
ax1.grid('on')

ax2.plot(x, relu, color = 'blue', linestyle = '-', linewidth = 3)
ax2.set_xlabel('x', fontsize = 14)
ax2.set_ylabel('f(x)', fontsize = 14)
ax2.tick_params(axis = "both", labelsize = 10)
ax2.set_title('ReLU', fontsize = 14)
ax2.grid('on')

ax3.plot(x, tanh, color = 'blue', linestyle = '-', linewidth = 3)
ax3.set_xlabel('x', fontsize = 14)
ax3.set_ylabel('f(x)', fontsize = 14)
ax3.tick_params(axis = "both", labelsize = 10)
ax3.set_title('tanh', fontsize = 14)
ax3.grid('on')

fig.savefig('subplots.svg')
fig.savefig('subplots.png')
fig.show()

以下說明程式碼中較特別的部分

  1. 使用 fig, (ax1, ax2, ax3) = plt.subplots(1, 3, sharex = True, figsize=(12, 3), dpi = 72) 產生繪圖物件 fig,其中共有 1 列、3 欄的小圖,3 張小圖的名稱依序為 ax1、ax2、ax3,並且 3 張小圖共用相同的 x 軸。
  2. 使用 ax1.plot(x, sigmoid, color = 'blue', linestyle = '-', linewidth = 3) 繪製第 1 張小圖,橫軸為 x,縱軸為 sigmoid,另外兩張小圖的繪圖方法相同,只需要修改縱軸資料即可。




參考資料


  1. plt.subplots_adjust: https://matplotlib.org/api/_as_gen/matplotlib.pyplot.subplots_adjust.html
  2. plt.subplots: https://matplotlib.org/api/_as_gen/matplotlib.pyplot.subplots.html




HackMD 版本連結:https://hackmd.io/s/S1RDRYNNN

2 則留言: