# Matplotlib 繪圖技巧:三張小圖並列
> 作者:王一哲
> 日期:2019/2/3
以下是將在三張小圖並列在同一張圖中的作法,部分內容與〈[Matplotlib 繪圖技巧:在同一張圖上繪製兩個函數、兩張圖並列](https://hackmd.io/s/Bkd0EMyCm)〉相似,但使用兩種不同的作法。這次要畫的圖形是在人工神經網路中常用的激勵函數 (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)$$
<img height="100%" width="100%" src="https://i.imgur.com/LsiGJpy.png" style="display: block; margin-left: auto; margin-right: auto;"/>
<div style="text-align:center">三種激勵函數圖形</div>
</br>
## 方法1: 用 subplot 切換繪圖位置
```python=
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()
```
</br>
以下說明程式碼中較特別的部分
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 張圖。
</br>
## 方法2: 用 plt.subplots
```python=
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()
```
</br>
以下說明程式碼中較特別的部分
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,另外兩張小圖的繪圖方法相同,只需要修改縱軸資料即可。
</br>
## 參考資料
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
---
###### tags:`Python`