PPP3: 機械学習 Matplotlib scikit-learn
Jupyter上にMatplotlibでグラフを描画するにはまずおまじない
%matplotlib inline
%matplotlib notebook
とすると対話的にグラフを表示するらしいけど
どう操作するのかわからなかった
まあいいや
それで
import matplotlib.pyplot as plt
x = [1,2,3,4]
y = [10,12,15,20]
plt.plot(x, y)
plt.show()
出たでた
from numpy.random import normal
x = normal(size=200)
plt.hist(x, bins=40)
これだけでも出る
ラベルとかを追加
plt.xlabel('x')
plt.ylabel('y (Bin Count)')
plt.title('Histogram Example')
plt.axis([-4,4,0,25])
plt.grid(True)
これは同じセルに入れないといけない
いまだにどう動いてるのかモデルが見えない
plt.show()
これでグラフが表示されるそうなんだけどなくても表示されてた
次は散布図
x = np.arange(20)
y = 2*x + 1
えーとこれは
y
---
array([ 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33,
35, 37, 39])
そういうことね
[2*xk + 1 for xk in x]
みたいに理解すればいいのかな
線形回帰
polyってついてるから線形だけじゃないんだろうけど
deg=1
で1次式で近似するよう指定してるってことかな
m, b = np.polyfit(x, y, deg=1)
結果
m, b
(2.0000000000000004, 1.0000000000000009)
グラフを表示
plt.scatter(x, y)
plt.plot(x, m*x+b, 'r-')
plt.show()
scatter()
が散布図で、plot
はなんていうんだろうとにかく折れ線を書くものかな
ここまでは単に数値計算のライブラリだよね
かろうじてpolyfit
だけ予測っぽいけど
いよいよ機械学習っぽいところへ
サンプル用のデータがある
これはありがたいね
from sklearn import datasets
diabetes = datasets.load_diabetes()
どれどれ
diabetes
{'data': array([[ 0.03807591, 0.05068012, 0.06169621, ..., -0.00259226,
0.01990842, -0.01764613],
...,
'target': array([151., 75., 141., 206., 135., 97., 138., 63., 110., 310., 101.,
...,
'DESCR': '.. _diabetes_dataset:\n\n ...',
'feature_names': ['age', ...,
'data_filename': '/home/takahiro/study/PPP3-mac/mlprj/venv/lib/python3.6/site-packages/sklearn/datasets/data/diabetes_data.csv.gz',
'target_filename': '/home/takahiro/study/PPP3-mac/mlprj/venv/lib/python3.6/site-packages/sklearn/datasets/data/diabetes_target.csv.gz'} ...
入った
DataFrameに入れる
df = pd.DataFrame(diabetes.data, columns=("age", "sex", "bmi", "map", "tc", "ldl", "hdl", "tch", "ltg", "glu"))
df['target'] = diabetes.target
df.head()
target
ってなんなん
1年後の疾患進行状況を数値で表したデータ
これか
これを予測するからターゲットになるってことだなたぶん
bmi列とtarget列にどのような関係があるかを線形回帰モデルを利用して学習させます。
ん
ここでも線形回帰か
ディープラーニングとかじゃないんですか!(偏見
まずはbmiだけ取り出す
diabetes_X = diabetes.data[:, np.newaxis, 2]
diabetes_X
array([[ 0.06169621],
[-0.05147406],
[ 0.04445121],
[-0.01159501],
...
取り出せたみたいだけどdiabetes.data[:, np.newaxis, 2]
って何やってんの
リストのスライスと、
np.newaxis
ってなんだ 新しい軸?
2っていうのは(0から数え始めて)2番目のデータを持ってこいってことかな
そもそも添字部分にカンマ区切りで何書いてるんだ
そんなのpythonにあったっけ・・・
普通のlistじゃなくてNumpy特有の書き方なのかな
type(diabetes.data)
numpy.ndarray
なるほどNumPyのクラスらしい
print
でarray(...)
って表示されるやつはみんなこれ?
順番に見ていくか
diabetes.data[:]
から
diabetes.data[:]
array([[ 0.03807591, 0.05068012, 0.06169621, ..., -0.00259226,
0.01990842, -0.01764613],
...,
[-0.04547248, -0.04464164, -0.0730303 , ..., -0.03949338,
-0.00421986, 0.00306441]])
diabetes.data
と同じだな
これは予想通り
newaxis
を追加
diabetes.data[:, np.newaxis]
array([[[ 0.03807591, 0.05068012, 0.06169621, ..., -0.00259226,
0.01990842, -0.01764613]],
...,
[[-0.04547248, -0.04464164, -0.0730303 , ..., -0.03949338,
-0.00421986, 0.00306441]]])
えーと?
ひとつ入れ子が深くなった?
1次元増えたということになるのか・・・?
diabetes.data[:, np.newaxis].shape
(442, 1, 10)
ということになってるみたい
だから何?
さらに2を追加すると2番目の項目が取り出されるっぽい
diabetes.data[:, np.newaxis, 2]
array([[ 0.06169621],
...,
[-0.0730303 ]])
どうもピンとこない気がする
2って書いたら2番目を取り出してるってことはわかるけど
np.newaxis
って書くと入れ子が深くなって
2って書くと2番目を取り出すっていうのはどういうことなん
そもそもdiabetes.data[:, 2]
じゃダメなの
diabetes.data[:, 2]
array([ 0.06169621, -0.05147406, 0.04445121, -0.01159501, -0.03638469,
...,
0.03906215, -0.0730303 ])
なるほどそうなるからか
ちょっとピンと来た
次元が減らないようにとりあえず次元を足しておくってことか
array([[ 0.06169621], ..., [-0.0730303 ]])
より
array([ 0.06169621, ..., -0.0730303 ])
の方が自然な気もするけどね!
他の関数とのやりとりするには上の形のほうが都合いいってことだろうな
公式見よ
ここだな
まずなによりこれ
Unlike lists and tuples, numpy arrays support multidimensional indexing for multidimensional arrays.
普通のリストやタプルと違って、x[1,3]
という形で書ける
これがとまどいのかなりの部分を占めた
Note that if one indexes a multidimensional array with fewer indices than dimensions, one gets a subdimensional array.
3次元のarrayで2次元だけ指定すれば1次元のarrayが返される
The slicing and striding works exactly the same way it does for lists and tuples except that they can be applied to multiple dimensions as well.
スライスやストライドはリストやタプルで使うのと同じように使える
Note that slices of arrays do not copy the internal array data but only produce new views of the original data.
arrayのスライスはコピーを作るのではなくて元のデータの見方を変えるだけ
そうなんだ
ということは[:]
っていうのは「そのままなにもしない」っていうことになるんだな
the np.newaxis object can be used within array indices to add new dimensions with a size of 1
np.newaxis
を使うとサイズ1で次元を追加できる
これくらいでいいだろう
話を元にもどす
与えられたデータとターゲットをを学習用とテスト用に分ける
diabetes_X_train =diabetes_X[:-20]
diabetes_X_test =diabetes_X[-20:]
diabetes_y_train =diabetes.target[:-20]
diabetes_y_test =diabetes.target[-20:]
いよいよ予測
from sklearn import linear_model
regr = linear_model.LinearRegression()
regr.fit(diabetes_X_train, diabetes_y_train)
diabetes_y_pred = regr.predict(diabetes_X_test)
できたかな
diabetes_y_pred
array([225.9732401 , 115.74763374, 163.27610621, 114.73638965,
120.80385422, 158.21988574, 236.08568105, 121.81509832,
99.56772822, 123.83758651, 204.73711411, 96.53399594,
154.17490936, 130.91629517, 83.3878227 , 171.36605897,
137.99500384, 137.99500384, 189.56845268, 84.3990668 ])
できてる
本当の値は
diabetes_y_test
array([233., 91., 111., 152., 120., 67., 310., 94., 183., 66., 173.,
72., 49., 64., 48., 178., 104., 132., 220., 57.])
・・・ちょっとなんとも言えない
決定係数を見る
from sklearn.metrics import r2_score
print(f'r^2 score {r2_score(diabetes_y_test, diabetes_y_pred):.02f}')
r^2 score 0.47
0.47っていうのはどうなのか
低そう
グラフにする
plt.scatter(diabetes_X_test, diabetes_y_test, color='black')
plt.plot(diabetes_X_test, diabetes_y_pred, color='blue', linewidth = 3)
...
これはモデルがよくなかったってことみたい
じゃあ次のPDCA行くよ(行かない
大量のデータを扱うにはNumPyの行列計算に落とし込むとか
メモリーを使い切るとか特有のテクニックがある
終わり!