回答編集履歴
11
修正
answer
CHANGED
@@ -43,7 +43,7 @@
|
|
43
43
|
|
44
44
|

|
45
45
|
|
46
|
-
このままでは線形分離できないので、Φ: (x, y) → (x, y, y^2) という関数で3次元空間に射影します。3次元空間上で
|
46
|
+
このままでは線形分離できないので、Φ: (x, y) → (x, y, y^2) という関数で3次元空間に射影します。3次元空間上に射影したことで線形分離可能になったので、線形 SVM で学習できます。
|
47
47
|
|
48
48
|
```python
|
49
49
|
X_new = np.hstack([X, X[:, 1:] ** 2])
|
10
修正
answer
CHANGED
@@ -43,7 +43,7 @@
|
|
43
43
|
|
44
44
|

|
45
45
|
|
46
|
-
このままでは線形分離できないので、Φ: (
|
46
|
+
このままでは線形分離できないので、Φ: (x, y) → (x, y, y^2) という関数で3次元空間に射影します。3次元空間上では線形分離できるようになるので、線形 SVM で学習できます。
|
47
47
|
|
48
48
|
```python
|
49
49
|
X_new = np.hstack([X, X[:, 1:] ** 2])
|
9
修正
answer
CHANGED
File without changes
|
8
修正
answer
CHANGED
@@ -43,7 +43,7 @@
|
|
43
43
|
|
44
44
|

|
45
45
|
|
46
|
-
このままでは線形分離できないので、Φ: (x1, x2) → (x1, x2, x2^2) という関数で3次元空間に射影します。
|
46
|
+
このままでは線形分離できないので、Φ: (x1, x2) → (x1, x2, x2^2) という関数で3次元空間に射影します。3次元空間上では線形分離できるようになるので、線形 SVM で学習できます。
|
47
47
|
|
48
48
|
```python
|
49
49
|
X_new = np.hstack([X, X[:, 1:] ** 2])
|
7
修正
answer
CHANGED
@@ -105,7 +105,7 @@
|
|
105
105
|
|
106
106
|

|
107
107
|
|
108
|
-
decision_function(x, y, y^2) = 0
|
108
|
+
{(x, y)|decision_function(x, y, y^2) = 0, x, y∈ℝ} が元の2次元空間において、決定境界となります。
|
109
109
|
なので、decision_function(x, y, y^2) = 0 である等高線を contourf() で描画します。
|
110
110
|
|
111
111
|
```python
|
6
修正
answer
CHANGED
File without changes
|
5
修正
answer
CHANGED
@@ -33,19 +33,38 @@
|
|
33
33
|
X, y = make_blobs(centers=4, random_state=8)
|
34
34
|
y = y % 2
|
35
35
|
|
36
|
-
# データを描画する。
|
37
36
|
fig, ax = plt.subplots()
|
38
37
|
class_colors = ListedColormap(["g", "k"])
|
39
38
|
ax.scatter(X[:, 0], X[:, 1], c=y, cmap=class_colors)
|
39
|
+
ax.set_xlabel("Feature 0")
|
40
|
+
ax.set_ylabel("Feature 1")
|
40
41
|
plt.show()
|
41
42
|
```
|
42
43
|
|
43
|
-

|
44
45
|
|
45
46
|
このままでは線形分離できないので、Φ: (x1, x2) → (x1, x2, x2^2) という関数で3次元空間に射影します。
|
46
47
|
|
48
|
+
```python
|
47
|
-
|
49
|
+
X_new = np.hstack([X, X[:, 1:] ** 2])
|
48
50
|
|
51
|
+
fig = plt.figure(figsize=(7, 7))
|
52
|
+
ax = fig.add_subplot(111, projection="3d")
|
53
|
+
ax.scatter(X_new[:, 0], X_new[:, 1], X_new[:, 2], c=y, cmap=class_colors)
|
54
|
+
ax.view_init(30, 30)
|
55
|
+
ax.set_xlabel("Feature 0")
|
56
|
+
ax.set_ylabel("Feature 1")
|
57
|
+
plt.show()
|
58
|
+
```
|
59
|
+
|
60
|
+

|
61
|
+
|
62
|
+
fit() で学習します。
|
63
|
+
|
64
|
+
```python
|
65
|
+
svc = LinearSVC().fit(X_new, y)
|
66
|
+
```
|
67
|
+
|
49
68
|
射影した空間 {(x, y, y^2)|x, y∈ℝ} 上の各点と分類超平面との距離を [decision_function()](https://scikit-learn.org/stable/modules/generated/sklearn.svm.SVC.html#sklearn.svm.SVC.decision_function) で計算します。
|
50
69
|
|
51
70
|
```python
|
@@ -71,20 +90,20 @@
|
|
71
90
|
# 可視化する。
|
72
91
|
fig = plt.figure(figsize=(9, 7))
|
73
92
|
ax = fig.add_subplot(111, projection="3d")
|
74
|
-
# データを可視化する。
|
93
|
+
# 学習データの点を可視化する。
|
75
94
|
ax.scatter(X_new[:, 0], X_new[:, 1], X_new[:, 2], c=y, cmap=class_colors)
|
76
95
|
# 射影した空間上の各点と分類超平面との距離を可視化する。
|
77
96
|
sc = ax.scatter(XX, YY, ZZ, c=dist, cmap="bwr", vmin=-15, vmax=15)
|
78
97
|
# 分類超平面を可視化する。
|
79
98
|
ax.plot_surface(XX, YY, plane, alpha=0.5)
|
80
99
|
ax.view_init(30, 30)
|
81
|
-
ax.set_xlabel("
|
100
|
+
ax.set_xlabel("Feature 0")
|
82
|
-
ax.set_ylabel("
|
101
|
+
ax.set_ylabel("Feature 1")
|
83
102
|
fig.colorbar(sc)
|
84
103
|
plt.show()
|
85
104
|
```
|
86
105
|
|
87
|
-

|
88
107
|
|
89
108
|
decision_function(x, y, y^2) = 0 となる {(x, y)|x, y∈ℝ} が射影前の2次元において、決定境界となります。
|
90
109
|
なので、decision_function(x, y, y^2) = 0 である等高線を contourf() で描画します。
|
4
修正
answer
CHANGED
@@ -2,12 +2,10 @@
|
|
2
2
|
|
3
3
|
`np.c_[XX.ravel(),YY.ravel(),ZZ.ravel()]` ですが、
|
4
4
|
|
5
|
-
1. XX, YY, ZZ はそれぞれ (50, 50) の2次元配列で、`ndarray.ravel()` で
|
5
|
+
1. `XX, YY, ZZ` はそれぞれ (50, 50) の2次元配列であり、`ndarray.ravel()` でそれぞれ (2500,) の1次元配列に変更しています。
|
6
|
-
1. `numpy.c_[XX.ravel(),YY.ravel(),ZZ.ravel()]` で結合しているので、(2500, 3) の2次元配列にな
|
6
|
+
1. `numpy.c_[XX.ravel(),YY.ravel(),ZZ.ravel()]` で3つの1次元配列を横方向に結合しているので、(2500, 3) の2次元配列になります。
|
7
|
+
この (2500, 3) の2次元配列を `decision_function()` に渡しています。
|
7
8
|
|
8
|
-
これを `decision_function()` に渡しています。
|
9
|
-
`decision_function()` は (N, 特徴量の次元数) の2次元配列を渡す必要があるため、このようにしています。
|
10
|
-
|
11
9
|
> また、decision_functionは何をしているのでしょうか。fitと同じように決定境界を学習しているのでしょうか。
|
12
10
|
|
13
11
|
学習自体は fit() で完了しています。
|
@@ -17,72 +15,92 @@
|
|
17
15
|
|
18
16
|
> 以下15行目のコードでXX,YYの右にdec.reshape(XX.shape)が入るのはなぜでしょうか。これは(2500,)のdecを(50,50)にしているようですが、なぜXX,YY,ZZではないのでしょうか。
|
19
17
|
|
20
|
-
dec.reshape(XX.shape) としているのは、contourf() の仕様上、dec の形状 (2500,) を XX, YY に合わせて (50, 50) にしなければいけないためです。
|
18
|
+
`dec.reshape(XX.shape)` としているのは、contourf() の仕様上、`dec` の形状 (2500,) を XX, YY に合わせて (50, 50) にしなければいけないためです。
|
21
19
|
|
22
20
|
## コードの流れ解説
|
23
21
|
|
24
|
-
|
22
|
+
[線形分離](https://ja.wikipedia.org/wiki/%E7%B7%9A%E5%BD%A2%E5%88%86%E9%9B%A2%E5%8F%AF%E8%83%BD)できない2次元のデータが与えられたとします。
|
25
23
|
|
26
24
|
```python
|
27
25
|
import matplotlib.pyplot as plt
|
28
|
-
import mglearn
|
29
26
|
import numpy as np
|
27
|
+
from matplotlib.colors import ListedColormap
|
28
|
+
from mpl_toolkits.mplot3d import Axes3D
|
30
29
|
from sklearn.datasets import make_blobs
|
31
30
|
from sklearn.svm import LinearSVC
|
32
31
|
|
33
|
-
#
|
32
|
+
# 2次元のデータを作成する。
|
34
33
|
X, y = make_blobs(centers=4, random_state=8)
|
35
34
|
y = y % 2
|
36
|
-
X_new = np.hstack([X, X[:, 1:] ** 2])
|
37
35
|
|
38
|
-
#
|
36
|
+
# データを描画する。
|
37
|
+
fig, ax = plt.subplots()
|
39
|
-
|
38
|
+
class_colors = ListedColormap(["g", "k"])
|
39
|
+
ax.scatter(X[:, 0], X[:, 1], c=y, cmap=class_colors)
|
40
|
+
plt.show()
|
40
41
|
```
|
41
42
|
|
42
|
-

|
43
44
|
|
44
|
-
|
45
|
+
このままでは線形分離できないので、Φ: (x1, x2) → (x1, x2, x2^2) という関数で3次元空間に射影します。
|
45
46
|
|
46
|
-
|
47
|
+

|
47
48
|
|
49
|
+
射影した空間 {(x, y, y^2)|x, y∈ℝ} 上の各点と分類超平面との距離を [decision_function()](https://scikit-learn.org/stable/modules/generated/sklearn.svm.SVC.html#sklearn.svm.SVC.decision_function) で計算します。
|
50
|
+
|
48
51
|
```python
|
49
|
-
#
|
52
|
+
# 射影した空間上の点を作成する。
|
53
|
+
xs = np.linspace(X_new[:, 0].min() - 2, X_new[:, 0].max() + 2, 50)
|
54
|
+
ys = np.linspace(X_new[:, 1].min() - 2, X_new[:, 1].max() + 2, 50)
|
50
|
-
|
55
|
+
XX, YY = np.meshgrid(xs, ys)
|
51
|
-
|
56
|
+
ZZ = YY ** 2
|
52
57
|
|
53
|
-
|
58
|
+
# 作成した点と分類超平面との距離を計算する。
|
59
|
+
dist = svc.decision_function(np.c_[XX.ravel(), YY.ravel(), ZZ.ravel()])
|
54
60
|
|
61
|
+
# SVM の超平面を計算する。
|
62
|
+
def hyper_plane(svc, XX, YY):
|
63
|
+
a1, a2, a3 = svc.coef_[0]
|
64
|
+
b = svc.intercept_[0]
|
65
|
+
return (-b - a1 * XX - a2 * YY) / a3
|
66
|
+
|
67
|
+
|
68
|
+
plane = hyper_plane(svc, XX, YY)
|
69
|
+
|
70
|
+
|
55
|
-
|
71
|
+
# 可視化する。
|
72
|
+
fig = plt.figure(figsize=(9, 7))
|
73
|
+
ax = fig.add_subplot(111, projection="3d")
|
74
|
+
# データを可視化する。
|
56
|
-
|
75
|
+
ax.scatter(X_new[:, 0], X_new[:, 1], X_new[:, 2], c=y, cmap=class_colors)
|
76
|
+
# 射影した空間上の各点と分類超平面との距離を可視化する。
|
57
|
-
|
77
|
+
sc = ax.scatter(XX, YY, ZZ, c=dist, cmap="bwr", vmin=-15, vmax=15)
|
78
|
+
# 分類超平面を可視化する。
|
79
|
+
ax.plot_surface(XX, YY, plane, alpha=0.5)
|
58
|
-
|
80
|
+
ax.view_init(30, 30)
|
81
|
+
ax.set_xlabel("x")
|
82
|
+
ax.set_ylabel("y")
|
83
|
+
fig.colorbar(sc)
|
59
|
-
|
84
|
+
plt.show()
|
60
|
-
dec = linear_svm_3d.decision_function(np.c_[XX.ravel(), YY.ravel(), ZZ.ravel()])
|
61
85
|
```
|
62
86
|
|
63
|
-

|
64
|
-
色は分類超平面からの距離を表す
|
65
88
|
|
66
|
-
この図の等高線を描画しているのが以下です。
|
67
|
-
|
89
|
+
decision_function(x, y, y^2) = 0 となる {(x, y)|x, y∈ℝ} が射影前の2次元において、決定境界となります。
|
90
|
+
なので、decision_function(x, y, y^2) = 0 である等高線を contourf() で描画します。
|
68
91
|
|
69
|
-
```
|
92
|
+
```python
|
93
|
+
fig, ax = plt.subplots()
|
94
|
+
class_colors = ListedColormap(["g", "k"])
|
95
|
+
# 決定境界を可視化する。
|
70
|
-
|
96
|
+
ax.contourf(
|
71
|
-
XX,
|
72
|
-
YY,
|
73
|
-
dec.reshape(XX.shape),
|
74
|
-
levels=[
|
97
|
+
XX, YY, dist.reshape(XX.shape), levels=[dist.min(), 0, dist.max()], cmap="Set2"
|
75
|
-
cmap=mglearn.cm2,
|
76
|
-
alpha=0.5,
|
77
98
|
)
|
99
|
+
# データを可視化する。
|
78
|
-
|
100
|
+
ax.scatter(X[:, 0], X[:, 1], c=y, cmap=class_colors)
|
79
101
|
plt.xlabel("Feature 0")
|
80
102
|
plt.ylabel("Feature 1")
|
103
|
+
plt.show()
|
81
104
|
```
|
82
105
|
|
83
|
-

|
84
|
-
|
85
|
-
## コメント
|
86
|
-
|
87
|
-
書籍は持っていないのですが、特徴量の次元が3次元になっているので、決定境界の可視化を学ぶという目的には難解なサンプルだと思います。
|
88
|
-
2次元の特徴量を使って確認したほうが理解しやすいと思います。
|
3
修正
answer
CHANGED
File without changes
|
2
修正
answer
CHANGED
@@ -61,8 +61,10 @@
|
|
61
61
|
```
|
62
62
|
|
63
63
|

|
64
|
+
色は分類超平面からの距離を表す
|
64
65
|
|
65
66
|
この図の等高線を描画しているのが以下です。
|
67
|
+
等高線を引く位置は `dec.min(), 0, dec.max()` の3つにしており、dec==0 の等高線が分離超平面からの距離が0ということなので、つまり、これが分離超平面になります。
|
66
68
|
|
67
69
|
```
|
68
70
|
plt.contourf(
|
1
修正
answer
CHANGED
@@ -17,11 +17,11 @@
|
|
17
17
|
|
18
18
|
> 以下15行目のコードでXX,YYの右にdec.reshape(XX.shape)が入るのはなぜでしょうか。これは(2500,)のdecを(50,50)にしているようですが、なぜXX,YY,ZZではないのでしょうか。
|
19
19
|
|
20
|
-
dec.reshape(XX.shape) としているのは、contourf() の仕様上、dec の形状
|
20
|
+
dec.reshape(XX.shape) としているのは、contourf() の仕様上、dec の形状 (2500,) を XX, YY に合わせて (50, 50) にしなければいけないためです。
|
21
21
|
|
22
22
|
## コードの流れ解説
|
23
23
|
|
24
|
-
|
24
|
+
特徴空間 S = {(x, y, y**2)|x∈ℝ, y∈ℝ} 上のデータについて、今回考えています。特徴空間 S 上から適当な個数のサンプルを以下で生成しています。
|
25
25
|
|
26
26
|
```python
|
27
27
|
import matplotlib.pyplot as plt
|
@@ -41,7 +41,7 @@
|
|
41
41
|
|
42
42
|

|
43
43
|
|
44
|
-
青の曲面が特徴空間、点が生成されたサンプル
|
44
|
+
青の曲面が特徴空間、黄色、黒の点が生成されたサンプル
|
45
45
|
|
46
46
|
SVM の学習は、データ `X_new` とラベル `y` を渡して、以下で行っています。
|
47
47
|
|