%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
記得上次我們做了個鳶尾花分類器。
from sklearn.externals import joblib
clf = joblib.load("iris_clf_01.pkl")
真的可以用了嗎?
clf.predict([[2,3]])
array([2])
可以! 太棒了!
我們用一下之前的方式, 畫出我們想要看到我們可愛的 SVM 是怎麼以花萼長度、花萼寬度來分類的。上次我們用了 Python 所謂 "list comprehension" 的作法 (本質上是 for
迴圈), 現在我們換個方式看來比較「高級」的方式。
xt, yt = np.meshgrid(np.arange(-2,2,0.5), np.arange(-1,1,0.5))
xt
array([[-2. , -1.5, -1. , -0.5, 0. , 0.5, 1. , 1.5], [-2. , -1.5, -1. , -0.5, 0. , 0.5, 1. , 1.5], [-2. , -1.5, -1. , -0.5, 0. , 0.5, 1. , 1.5], [-2. , -1.5, -1. , -0.5, 0. , 0.5, 1. , 1.5]])
yt
array([[-1. , -1. , -1. , -1. , -1. , -1. , -1. , -1. ], [-0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5, -0.5], [ 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. ], [ 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5]])
看得出來 meshgrid
做了什麼呢? 基本上它就是說我們在 x, y 兩個指定範圍的長方型當中, 依我們指定的間隔找出格點。這些格點的座標分成 x 座標一個 array, y 座標一個。x 或 y 座標的 array, 的座標是一列一列標記的。
要是你覺得這樣的表示法很討厭, 我們也可以讓它變一長串的向量。
xt.ravel()
array([-2. , -1.5, -1. , -0.5, 0. , 0.5, 1. , 1.5, -2. , -1.5, -1. , -0.5, 0. , 0.5, 1. , 1.5, -2. , -1.5, -1. , -0.5, 0. , 0.5, 1. , 1.5, -2. , -1.5, -1. , -0.5, 0. , 0.5, 1. , 1.5])
注意這其實原來的 xt
並沒有變哦。
xt
array([[-2. , -1.5, -1. , -0.5, 0. , 0.5, 1. , 1.5], [-2. , -1.5, -1. , -0.5, 0. , 0.5, 1. , 1.5], [-2. , -1.5, -1. , -0.5, 0. , 0.5, 1. , 1.5], [-2. , -1.5, -1. , -0.5, 0. , 0.5, 1. , 1.5]])
我們可以把 (x,y) 一點一點的座標收集起來嗎?
np.c_[xt.ravel(), yt.ravel()]
array([[-2. , -1. ], [-1.5, -1. ], [-1. , -1. ], [-0.5, -1. ], [ 0. , -1. ], [ 0.5, -1. ], [ 1. , -1. ], [ 1.5, -1. ], [-2. , -0.5], [-1.5, -0.5], [-1. , -0.5], [-0.5, -0.5], [ 0. , -0.5], [ 0.5, -0.5], [ 1. , -0.5], [ 1.5, -0.5], [-2. , 0. ], [-1.5, 0. ], [-1. , 0. ], [-0.5, 0. ], [ 0. , 0. ], [ 0.5, 0. ], [ 1. , 0. ], [ 1.5, 0. ], [-2. , 0.5], [-1.5, 0.5], [-1. , 0.5], [-0.5, 0.5], [ 0. , 0.5], [ 0.5, 0.5], [ 1. , 0.5], [ 1.5, 0.5]])
把資料的型式這樣變來變去會是數據分析非常非常常做的事情。
我們經這麼多廢話後終於可以來做正事。
xx, yy = np.meshgrid(np.arange(3, 8.5, 0.2), np.arange(1.5, 5.0, 0.2))
Z = clf.predict(np.c_[xx.ravel(), yy.ravel()])
plt.scatter(xx.ravel(), yy.ravel(), s=50, c=Z)
<matplotlib.collections.PathCollection at 0x1156bfcf8>
雖然看來我們用了比較多白痴的方法做出一樣的事, 不過一些技巧之後也可以常常使用。
plt.scatter(xx.ravel(), yy.ravel(), s=50, c=Z, cmap=plt.cm.coolwarm, alpha=0.8)
<matplotlib.collections.PathCollection at 0x1159307f0>
plt.scatter(xx.ravel(), yy.ravel(), s=50, c=Z, cmap=plt.cm.prism, alpha=0.8)
<matplotlib.collections.PathCollection at 0x115ae0048>
from sklearn.datasets import load_iris
iris = load_iris()
x = iris.data[:, :2]
y = iris.target
我們來畫畫比較。
plt.subplot(121)
plt.scatter(x[:,0], x[:,1], s=50, c=y)
plt.subplot(122)
plt.scatter(x[:,0], x[:,1], s=50, c=clf.predict(x))
<matplotlib.collections.PathCollection at 0x115dd5630>
左邊的是訓練資料, 右邊是用我們 SVM 分類器分出來的。你有看出差異嗎? 是不是很難看出? 我們來用用另一個方式。
xx, yy = np.meshgrid(np.arange(3, 8.5, 0.02), np.arange(1.5, 5.0, 0.02))
Z = clf.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)
plt.contourf(xx, yy, Z, cmap=plt.cm.coolwarm, alpha=0.8)
<matplotlib.contour.QuadContourSet at 0x115f7bdd8>
Z = Z.reshape(xx.shape)
plt.contourf(xx, yy, Z, cmap=plt.cm.coolwarm, alpha=0.8)
plt.scatter(x[:,0], x[:,1], s=50, c=y, cmap=plt.cm.coolwarm)
<matplotlib.collections.PathCollection at 0x1164b59e8>