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

回答編集履歴

6

d

2020/02/11 07:19

投稿

tiitoi
tiitoi

スコア21960

answer CHANGED
@@ -158,4 +158,75 @@
158
158
  「カーネル密度推定の確率密度関数 (オレンジ)」は「真の確率密度関数」と一致して重なっている。
159
159
  「正規化されたヒストグラム(緑)」も「真の確率密度関数」とほぼ一致している。
160
160
 
161
- ![イメージ説明](54f7b2ad4dee3ed965e7a2a3d54b8dc1.png)
161
+ ![イメージ説明](54f7b2ad4dee3ed965e7a2a3d54b8dc1.png)
162
+
163
+ ## 追記 distplot の仕様確認
164
+
165
+ 引数の優先度としては、norm_hist < kde < hist_kws のようですので、
166
+ 正規化したくない場合は、`kde=False` または `hist_kws={"density": False}` を指定するのがよさそうです。
167
+
168
+ | kde | density | ヒストグラム |
169
+ | --- | --- | --- |
170
+ | False | False | 正規化されない |
171
+ | False | True | 正規化される |
172
+ | True | False | 正規化されない |
173
+ | True | True | 正規化される |
174
+
175
+ ```python
176
+ import matplotlib.pyplot as plt
177
+ import numpy as np
178
+ import seaborn as sns
179
+
180
+ sns.set()
181
+ np.random.seed(0)
182
+
183
+ x = np.random.randn(1000)
184
+
185
+ fig, axes = plt.subplots(2, 2, figsize=(8, 8))
186
+ axes = axes.ravel()
187
+
188
+ axes[0].set_title("kde=False, density=False")
189
+ sns.distplot(x, kde=False, hist_kws={"density": False}, ax=axes[0])
190
+ axes[1].set_title("kde=False, density=True")
191
+ sns.distplot(x, kde=False, hist_kws={"density": True}, ax=axes[1])
192
+ axes[2].set_title("kde=True, density=False")
193
+ sns.distplot(x, kde=True, hist_kws={"density": False}, ax=axes[2])
194
+ axes[3].set_title("kde=True, density=True")
195
+ sns.distplot(x, kde=True, hist_kws={"density": True}, ax=axes[3])
196
+ plt.show()
197
+ ```
198
+
199
+ ![イメージ説明](d73de753672cc8c90ac87d8c90e118bd.png)
200
+
201
+ | kde | norm_hist | ヒストグラム |
202
+ | --- | --- | --- |
203
+ | False | False | 正規化されない |
204
+ | False | True | 正規化される |
205
+ | True | False | 正規化される |
206
+ | True | True | 正規化される |
207
+
208
+ ```
209
+ import matplotlib.pyplot as plt
210
+ import numpy as np
211
+ import seaborn as sns
212
+
213
+ sns.set()
214
+ np.random.seed(0)
215
+
216
+ x = np.random.randn(1000)
217
+
218
+ fig, axes = plt.subplots(2, 2, figsize=(8, 8))
219
+ axes = axes.ravel()
220
+
221
+ axes[0].set_title("kde=False, norm_hist=False")
222
+ sns.distplot(x, kde=False, norm_hist=False, ax=axes[0])
223
+ axes[1].set_title("kde=False, norm_hist=True")
224
+ sns.distplot(x, kde=False, norm_hist=True, ax=axes[1])
225
+ axes[2].set_title("kde=True, norm_hist=False")
226
+ sns.distplot(x, kde=True, norm_hist=False, ax=axes[2])
227
+ axes[3].set_title("kde=True, norm_hist=True")
228
+ sns.distplot(x, kde=True, norm_hist=True, ax=axes[3])
229
+ plt.show()
230
+ ```
231
+
232
+ ![イメージ説明](58f7efa143a579814f417d172a8034c8.png)

5

d

2020/02/11 07:19

投稿

tiitoi
tiitoi

スコア21960

answer CHANGED
@@ -155,7 +155,7 @@
155
155
  plt.show()
156
156
  ```
157
157
 
158
- 「カーネル密度推定の確率密度関数」は「真の確率密度関数」と一致して重なっている。
158
+ 「カーネル密度推定の確率密度関数 (オレンジ)」は「真の確率密度関数」と一致して重なっている。
159
- ヒストグラムも「真の確率密度関数」とほぼ一致している。
159
+ 「正規化されたヒストグラム(緑)」も「真の確率密度関数」とほぼ一致している。
160
160
 
161
161
  ![イメージ説明](54f7b2ad4dee3ed965e7a2a3d54b8dc1.png)

4

d

2020/02/10 16:06

投稿

tiitoi
tiitoi

スコア21960

answer CHANGED
@@ -120,9 +120,10 @@
120
120
  ## 補足
121
121
 
122
122
  正規化されたヒストグラム、カーネル密度推定で推定した確率密度関数ですが、どちらも(不明な)真の確率密度関数を近似するのが目的です。
123
- 非常に沢山のデータがあり、ビンの幅を小さくした正規化されたヒストグラムを作成すれば、それで真の確率密度関数を近似できます。
124
- 曲線とx軸の間の面積を求めるのに、x 軸を細かい区間で分割して、長方形を敷き詰めて、メ面積を計算するというのが、リーマン積分の考え方なので、大量のデータを用意して、ビンの幅を小さくしたヒストグラムを作成するということは、まさに同じことをやっています。
125
123
 
124
+ 曲線とx軸の間の面積を求めるのに、x 軸を細かい区間で分割して、長方形を敷き詰めて、面積を計算するというのが、リーマン積分の考え方です。
125
+ なので、大量のデータを用意して、ビンの幅を小さくした正規化されたヒストグラムを作成すれば、それで真の確率密度関数を近似できます。
126
+
126
127
  ![イメージ説明](1272ef9914eb2cf3a76697924a3ff623.png)
127
128
  リーマン積分の考え方
128
129
 

3

d

2020/02/10 16:05

投稿

tiitoi
tiitoi

スコア21960

answer CHANGED
@@ -86,4 +86,75 @@
86
86
  plt.show()
87
87
  ```
88
88
 
89
- ![イメージ説明](f7ca8495379de0e9ea5450376c2e4894.png)
89
+ ![イメージ説明](f7ca8495379de0e9ea5450376c2e4894.png)
90
+
91
+ ## 追記
92
+
93
+ > 2つのグラフで「y」の値が、一方は少数、一方は整数となっておりますが、これは何故かがわかりません。
94
+
95
+ グラフの目盛りがすべて整数なら整数、小数が含まれるなら小数で表示するという matplotlib の仕様によるものなので、整数か小数かはグラフの表示上の問題であり、重要ではありません。
96
+ 注目するべきは、y 軸のスケールが左と右で大きく違うことでしょう。
97
+ これは、他の回答者様のコメント欄で hayataka2049 さんがご指摘されていますが、ヒストグラムの正規化 (デフォルトで有効) によるものです。
98
+ 通常、ヒストグラムは y 軸は各ビンに属するデータ数 (頻度値) ですが、この正規化が有効の場合、棒の面積の合計が1となるように棒の高さが調整されます。
99
+
100
+ 数式で表すと、n 個のビンの幅が w1, w2, ..., wn、頻度値が f1, f2, ..., fn としたとき、
101
+ w1 * f1 + w2 * f2 + ... + wn + fn = 1
102
+ となるように f1, f2, ..., fn の値を正規化します。
103
+
104
+ 左のほうが右より棒の高さが高いのは、左の方はビンの幅が小さいので、棒の面積の合計が1にするためには棒の高さをその分高くする必要があるからです。
105
+ 棒の高さをそのビンに属するデータ数として解釈したい場合は distplot() で norm_hist=False を指定してください。
106
+
107
+ この正規化の仕様は、内部でヒストグラム作成に使用している [numpy.histogram](https://docs.scipy.org/doc/numpy/reference/generated/numpy.histogram.html) から来ています。
108
+
109
+ > また、can110さんのご回答で、「描かれた曲線とx軸とを囲む領域の面積がデータ値の出現個数の総数になるように補正、正規化された値だということのようです。」とあるのですが、
110
+ > 仮に左側の画像の総面積を求めてみますと、x軸が「0.0 ~ 0.3」の為、「0.3」y軸を大体ではありますが「6」と考えた場合、「0.3 × 6 ÷ 2」 = 「0.9」となります。
111
+ > こちらのデータ値の出現個数の総数が「0.9」であるという意味がいまいち分からない為、ご助言頂けましたら幸いです...
112
+
113
+ 曲線のほうは、先の回答の通り、推定した確率密度関数です。
114
+ 「描かれた曲線とx軸とを囲む領域の面積」とは、確率密度関数を (-∞, +∞) の区間で積分すると求められ、これは1になります。
115
+
116
+ ![イメージ説明](d830ee93683ef32890091eaed0eabaa9.gif)
117
+
118
+ この計算の解釈は、確率変数 X は実数の値をとるので、(-∞, +∞) の間の値をとる確率は100%であるということを言っています。
119
+
120
+ ## 補足
121
+
122
+ 正規化されたヒストグラム、カーネル密度推定で推定した確率密度関数ですが、どちらも(不明な)真の確率密度関数を近似するのが目的です。
123
+ 非常に沢山のデータがあり、ビンの幅を小さくした正規化されたヒストグラムを作成すれば、それで真の確率密度関数を近似できます。
124
+ 曲線とx軸の間の面積を求めるのに、x 軸を細かい区間で分割して、長方形を敷き詰めて、メ面積を計算するというのが、リーマン積分の考え方なので、大量のデータを用意して、ビンの幅を小さくしたヒストグラムを作成するということは、まさに同じことをやっています。
125
+
126
+ ![イメージ説明](1272ef9914eb2cf3a76697924a3ff623.png)
127
+ リーマン積分の考え方
128
+
129
+ ```python
130
+ from scipy.stats import norm, gaussian_kde
131
+ import numpy as np
132
+ import matplotlib.pyplot as plt
133
+
134
+ # 平均0、分散1の1変量正規分布に従う確率変数
135
+ rv = norm(loc=0, scale=1)
136
+
137
+ # 大量の標本を生成する。
138
+ samples = rv.rvs(300000)
139
+
140
+ # この得られた標本から元となる確率密度関数を推定する。
141
+ kernel = gaussian_kde(samples)
142
+
143
+ fig, ax = plt.subplots()
144
+
145
+ # 確率密度関数を描画する。
146
+ xs = np.linspace(-5, 5, 1000)
147
+ ax.plot(xs, rv.pdf(xs), label="確率密度関数")
148
+ ax.plot(xs, kernel(xs), label="KDE で推定した確率密度関数")
149
+
150
+ # ヒストグラムを描画する。
151
+ bins = np.linspace(-5, 5, 1000)
152
+ ax.hist(samples, bins, density=True)
153
+ ax.legend(loc="upper left")
154
+ plt.show()
155
+ ```
156
+
157
+ 「カーネル密度推定の確率密度関数」は「真の確率密度関数」と一致して重なっている。
158
+ ヒストグラムも「真の確率密度関数」とほぼ一致している。
159
+
160
+ ![イメージ説明](54f7b2ad4dee3ed965e7a2a3d54b8dc1.png)

2

d

2020/02/10 15:50

投稿

tiitoi
tiitoi

スコア21960

answer CHANGED
@@ -23,4 +23,67 @@
23
23
 
24
24
  確率密度関数の見方としては、**確率密度関数 f(x) の値が大きいところは、そのあたりの x の値が現れる可能性が高い**という理解でいいと思います。
25
25
 
26
- 体系的に理解したい場合は [統計学](https://www.amazon.co.jp/s?k=%E6%95%B0%E7%90%86%E7%B5%B1%E8%A8%88%E5%AD%A6&__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&ref=nb_sb_noss_1) の教科書を当たると、最初のほうで必ず紹介されていると思うので、それを参照してください。
26
+ 体系的に理解したい場合は [統計学](https://www.amazon.co.jp/s?k=%E6%95%B0%E7%90%86%E7%B5%B1%E8%A8%88%E5%AD%A6&__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&ref=nb_sb_noss_1) の教科書を当たると、最初のほうで必ず紹介されていると思うので、それを参照してください。
27
+
28
+ ## 追記
29
+
30
+ ストーリーとしては、以下のようになります。
31
+
32
+ いくつかのデータが得られた
33
+
34
+ データが得られた背景となる確率分布があるけど、それはわからない
35
+
36
+ データから確率分布を推定する
37
+
38
+ ----
39
+
40
+ 統計学の考え方としては、まずなんらかの真の確率分布があり (現実ではこれはわからない)、データはその確率分布から得られた標本 (値の例) であると考えます。
41
+
42
+ 以下、例として、標準正規分布としておきます。
43
+
44
+ ```python
45
+ from scipy.stats import norm, gaussian_kde
46
+ import numpy as np
47
+ import matplotlib.pyplot as plt
48
+
49
+ # 平均0、分散1の1変量正規分布に従う確率変数
50
+ rv = norm(loc=0, scale=1)
51
+
52
+ fig, ax = plt.subplots()
53
+ ax.plot(xs, rv.pdf(xs), label="確率密度関数")
54
+ ax.legend(loc="upper left")
55
+ ax.set_xlim(-5, 5)
56
+ plt.show()
57
+ ```
58
+
59
+ ![イメージ説明](2a6bddf542a6b022c309d37e1752241f.png)
60
+
61
+ このような分布があって、そこから1000 個の値が得られたとします。
62
+ ヒストグラムを描画すると以下のようになります。
63
+
64
+ ![イメージ説明](822bcb6ec0b60af5ad05c049af7017ce.png)
65
+
66
+ 現実では、いくつかのデータが得られたとして、真の確率分布というのはわからないわけです。
67
+ 例えば、100人に身長を聞いて、[168, 172, 180, ...] と100人分のデータが得られたとして、その元となった真の確率分布というのはわかりません。
68
+
69
+ わからないので、それを今持っているデータから推定するというのが、統計学の1つの目的になります。
70
+ カーネル密度推定はその手法の1つです。
71
+ カーネル密度推定を使って推定すると、以下のようになります。
72
+ 元の分布 (青) がわからなくても、データからある程度それに近い分布 (オレンジ) が得られました。
73
+
74
+ ```python
75
+ # この得られた標本から元となる確率密度関数を推定する。
76
+ kernel = gaussian_kde(samples)
77
+
78
+ # 確率密度関数を描画する。
79
+ xs = np.linspace(-5, 5, 1000)
80
+
81
+ fig, ax = plt.subplots()
82
+ ax.plot(xs, rv.pdf(xs), label="確率密度関数")
83
+ ax.plot(xs, kernel(xs), label="推定した確率密度関数")
84
+ ax.legend(loc="upper left")
85
+ ax.set_xlim(-5, 5)
86
+ plt.show()
87
+ ```
88
+
89
+ ![イメージ説明](f7ca8495379de0e9ea5450376c2e4894.png)

1

d

2020/02/09 12:11

投稿

tiitoi
tiitoi

スコア21960

answer CHANGED
@@ -23,4 +23,4 @@
23
23
 
24
24
  確率密度関数の見方としては、**確率密度関数 f(x) の値が大きいところは、そのあたりの x の値が現れる可能性が高い**という理解でいいと思います。
25
25
 
26
- きちんと理解したい場合は [統計学](https://www.amazon.co.jp/s?k=%E6%95%B0%E7%90%86%E7%B5%B1%E8%A8%88%E5%AD%A6&__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&ref=nb_sb_noss_1) の教科書を当たると、最初のほうで必ず紹介されていると思うので、それを参照してください。
26
+ 体系的に理解したい場合は [統計学](https://www.amazon.co.jp/s?k=%E6%95%B0%E7%90%86%E7%B5%B1%E8%A8%88%E5%AD%A6&__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&ref=nb_sb_noss_1) の教科書を当たると、最初のほうで必ず紹介されていると思うので、それを参照してください。