teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

11

修正

2020/05/23 16:32

投稿

tiitoi
tiitoi

スコア21960

answer CHANGED
@@ -43,7 +43,7 @@
43
43
 
44
44
  ![イメージ説明](036baed9ee38ee684f918844f06a15b0.jpeg)
45
45
 
46
- このままでは線形分離できないので、Φ: (x, y) → (x, y, y^2) という関数で3次元空間に射影します。3次元空間上で線形分離できるようになので、線形 SVM で学習できます。
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

修正

2020/05/23 16:32

投稿

tiitoi
tiitoi

スコア21960

answer CHANGED
@@ -43,7 +43,7 @@
43
43
 
44
44
  ![イメージ説明](036baed9ee38ee684f918844f06a15b0.jpeg)
45
45
 
46
- このままでは線形分離できないので、Φ: (x1, x2) → (x1, x2, x2^2) という関数で3次元空間に射影します。3次元空間上では線形分離できるようになるので、線形 SVM で学習できます。
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

修正

2020/05/23 16:29

投稿

tiitoi
tiitoi

スコア21960

answer CHANGED
File without changes

8

修正

2020/05/23 16:27

投稿

tiitoi
tiitoi

スコア21960

answer CHANGED
@@ -43,7 +43,7 @@
43
43
 
44
44
  ![イメージ説明](036baed9ee38ee684f918844f06a15b0.jpeg)
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

修正

2020/05/23 16:27

投稿

tiitoi
tiitoi

スコア21960

answer CHANGED
@@ -105,7 +105,7 @@
105
105
 
106
106
  ![イメージ説明](526a7253e975e19285e63902f7bc8f48.jpeg)
107
107
 
108
- decision_function(x, y, y^2) = 0 となる {(x, y)|x, y∈ℝ} が射影前の2次元において、決定境界となります。
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

修正

2020/05/23 16:26

投稿

tiitoi
tiitoi

スコア21960

answer CHANGED
File without changes

5

修正

2020/05/23 16:24

投稿

tiitoi
tiitoi

スコア21960

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
- ![イメージ説明](4ba616b7f87151122b6dfbcbbfc85e08.jpeg)
44
+ ![イメージ説明](036baed9ee38ee684f918844f06a15b0.jpeg)
44
45
 
45
46
  このままでは線形分離できないので、Φ: (x1, x2) → (x1, x2, x2^2) という関数で3次元空間に射影します。
46
47
 
48
+ ```python
47
- ![イメージ説明](13ecab51534b9fcaeb76fa57ab549d4c.jpeg)
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
+ ![イメージ説明](3ec79079b60dfa0ce697e2f8735932b2.jpeg)
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("x")
100
+ ax.set_xlabel("Feature 0")
82
- ax.set_ylabel("y")
101
+ ax.set_ylabel("Feature 1")
83
102
  fig.colorbar(sc)
84
103
  plt.show()
85
104
  ```
86
105
 
87
- ![イメージ説明](6f9fd69905ad5c7069e81b6187125654.jpeg)
106
+ ![イメージ説明](526a7253e975e19285e63902f7bc8f48.jpeg)
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

修正

2020/05/23 16:24

投稿

tiitoi
tiitoi

スコア21960

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()` で1次元配列につぶしているので、それぞれ (2500,) の1次元配列になる
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
- 特徴空間 S = {(x, y, y**2)|x∈ℝ, y∈ℝ} 上のデータについて、今回考ています。特徴空間 S 上か適当な個数のサンプルを以下で生成ています。
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
- # (N, 3) のデータと (N,) のラベルを作成
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
- linear_svm_3d = LinearSVC().fit(X_new, y)
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
- ![イメージ説明](360d395eb04a70afec407c4e1556821d.jpeg)
43
+ ![イメージ説明](4ba616b7f87151122b6dfbcbbfc85e08.jpeg)
43
44
 
44
- 曲面が特徴空間、黄色、黒の点が生成されたサンプル
45
+ ままでは線形分離できないので、Φ: (x1, x2) → (x1, x2, x2^2) という関数で3次元空間に射影します。
45
46
 
46
- SVM の学習は、デタ `X_new` とラベル `y` を渡して、以下で行っています。
47
+ ![イメジ説明](13ecab51534b9fcaeb76fa57ab549d4c.jpeg)
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
- linear_svm_3d = LinearSVC().fit(X_new, y)
55
+ XX, YY = np.meshgrid(xs, ys)
51
- ```
56
+ ZZ = YY ** 2
52
57
 
53
- 特徴空間 S 上に点を沢山作成して、各超平面からの距離を計算します。
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
- ```python
71
+ # 可視化する。
72
+ fig = plt.figure(figsize=(9, 7))
73
+ ax = fig.add_subplot(111, projection="3d")
74
+ # データを可視化する。
56
- xx = np.linspace(X_new[:, 0].min() - 2, X_new[:, 0].max() + 2, 50)
75
+ ax.scatter(X_new[:, 0], X_new[:, 1], X_new[:, 2], c=y, cmap=class_colors)
76
+ # 射影した空間上の各点と分類超平面との距離を可視化する。
57
- yy = np.linspace(X_new[:, 1].min() - 2, X_new[:, 1].max() + 2, 50)
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
- XX, YY = np.meshgrid(xx, yy)
80
+ ax.view_init(30, 30)
81
+ ax.set_xlabel("x")
82
+ ax.set_ylabel("y")
83
+ fig.colorbar(sc)
59
- ZZ = YY ** 2
84
+ plt.show()
60
- dec = linear_svm_3d.decision_function(np.c_[XX.ravel(), YY.ravel(), ZZ.ravel()])
61
85
  ```
62
86
 
63
- ![イメージ説明](f3d3d3b5222c36db5aaebdabc0a12709.jpeg)
87
+ ![イメージ説明](6f9fd69905ad5c7069e81b6187125654.jpeg)
64
- 色は分類超平面からの距離を表す
65
88
 
66
- この図の等高線を描画しているのが以下です。
67
- 等高線を引く位置は `dec.min(), 0, dec.max()` の3つにしており、dec==0 の等高線分離超平面から距離が0とうことなので、つま、これが分離超平面になります。
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
- plt.contourf(
96
+ ax.contourf(
71
- XX,
72
- YY,
73
- dec.reshape(XX.shape),
74
- levels=[dec.min(), 0, dec.max()],
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
- mglearn.discrete_scatter(X[:, 0], X[:, 1], y)
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
- ![イメージ説明](53e7836ba3d1d009aa428e22d7a586b5.jpeg)
106
+ ![イメージ説明](ee23606b23b8d2debce89dce1f583732.jpeg)
84
-
85
- ## コメント
86
-
87
- 書籍は持っていないのですが、特徴量の次元が3次元になっているので、決定境界の可視化を学ぶという目的には難解なサンプルだと思います。
88
- 2次元の特徴量を使って確認したほうが理解しやすいと思います。

3

修正

2020/05/23 16:17

投稿

tiitoi
tiitoi

スコア21960

answer CHANGED
File without changes

2

修正

2020/05/23 13:00

投稿

tiitoi
tiitoi

スコア21960

answer CHANGED
@@ -61,8 +61,10 @@
61
61
  ```
62
62
 
63
63
  ![イメージ説明](f3d3d3b5222c36db5aaebdabc0a12709.jpeg)
64
+ 色は分類超平面からの距離を表す
64
65
 
65
66
  この図の等高線を描画しているのが以下です。
67
+ 等高線を引く位置は `dec.min(), 0, dec.max()` の3つにしており、dec==0 の等高線が分離超平面からの距離が0ということなので、つまり、これが分離超平面になります。
66
68
 
67
69
  ```
68
70
  plt.contourf(

1

修正

2020/05/23 13:00

投稿

tiitoi
tiitoi

スコア21960

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 の形状 (2500,) を XX, YY に合わせて (50, 50) にしなければいけないためです。
20
+ dec.reshape(XX.shape) としているのは、contourf() の仕様上、dec の形状 (2500,) を XX, YY に合わせて (50, 50) にしなければいけないためです。
21
21
 
22
22
  ## コードの流れ解説
23
23
 
24
- x, y を実数としたとき、特徴空間 S = (x, y, y**2) 上のデータについて、今回考えています。特徴空間 S 上から適当な個数のサンプルを以下で生成しています。
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
  ![イメージ説明](360d395eb04a70afec407c4e1556821d.jpeg)
43
43
 
44
- 青の曲面が特徴空間、点が生成されたサンプル
44
+ 青の曲面が特徴空間、黄色、黒の点が生成されたサンプル
45
45
 
46
46
  SVM の学習は、データ `X_new` とラベル `y` を渡して、以下で行っています。
47
47