Mais conteúdo relacionado Semelhante a Python 機械学習プログラミング データ分析ライブラリー解説編 (20) Mais de Etsuji Nakai (20) Python 機械学習プログラミング データ分析ライブラリー解説編1. Machine Learning for Everyone Else
Python 機械学習プログラミング
データ分析ライブラリー解説編
ver2.3 2017/01/12
中井悦司 (Twitter @enakai00)
5. 5
Python機械学習プログラミング
NumPy, pandas, matplotlib について
■
この資料では、主に下記のライブラリーを説明します。
- NumPy : ベクトルや行列の演算の他、主要な数学関数や乱数機能を提供します。
- pandas : Rに類似のデータフレーム(スプレッドシートのように、行/列に属性が付
いたデータ構造)を提供します。
- matplotlib : グラフを描画します。
■
この資料の説明は、Jupyter Notebook上での実行を前提とします。
- はじめに下記のコマンドを実行して、必要なモジュールをインポートしてあるもの
とします。
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from pandas import Series, DataFrame
11. 11
Python機械学習プログラミング
散布図と折れ線グラフ
In [13]: data_x = [0.0, -0.95, -0.59, 0.59, 0.95]
data_y = [1.0, 0.31, -0.81, -0.81, 0.31]
plt.scatter(data_x,data_y)
- 散布図は、対象データの「x座標のリスト」と「y座標のリス
ト」を用意して、plt.scatter()に渡します。「座標(x,y)のリ
スト」を渡すわけではないので注意してください。
- 折れ線グラフは、対象データの「x座標のリスト」と「y座標
のリスト」を用意して、plt.plot()に渡します。
- グラフの見栄えを綺麗にする方法は、後ほど説明します。
In [14]: data_x = [0,1,2,3,4,5]
data_y = [0,1,4,9,16,25]
plt.plot(data_x,data_y)
■
matplotlibを用いて、散布図と折れ線グラフを表示してみます。
15. 15
Python機械学習プログラミング
行列とベクトルの計算
■
行列/ベクトルは、NumPyのarrayオブジェクトで表現します。
- 2次元リストをnp.array()に渡すと、対応するarrayオブジェクトが得られます。
●
入力セルの最後に変数のみを記載すると、変数の内容が表示されます。
- 通常の2次元リストではできない、行列の積や逆行列などの演算が用意されています。行列の積
と逆行列は、それぞれ、np.dot()、np.linalg.inv()で計算します。
- 転置行列は、T属性を用います。
In [2]: theta = np.pi / 3
m = np.array([[np.cos(theta),-np.sin(theta)],
[np.sin(theta),np.cos(theta)]])
m
Out[2]: array([[ 0.5 , -0.8660254],
[ 0.8660254, 0.5 ]])
In [3]: np.dot(m, m)
Out[3]: array([[-0.5 , -0.8660254],
[ 0.8660254, -0.5 ]])
In [4]: np.linalg.inv(m)
Out[4]: array([[ 0.5 , 0.8660254],
[-0.8660254, 0.5 ]])
In [5]: m.T
Out[5]: array([[ 0.5 , 0.8660254],
[-0.8660254, 0.5 ]])
※ 回転行列について、一般に次の性質が成り立ちます。
16. 16
Python機械学習プログラミング
行列とベクトルの計算
- ベクトルは、 行列として定義することで、行列との積や内積/外積が計算できます。
- ベクトルの内積とクロス積は次のように計算できます。
※ ベクトルを1次元リストとして定義した場合の演算ルールについては後ほど説明します。
In [6]: x = np.array([[1],[0]])
x
Out[6]: array([[1],
[0]])
In [7]: n = np.dot(m,x)
n
Out[7]: array([[ 0.5 ],
[ 0.8660254]])
In [8]: a = np.array([[-1],[0],[1]])
b = np.array([[2],[3],[5]])
np.dot(a.T, b)
Out[8]: array([[3]])
In [9]: np.dot(a, b.T)
Out[9]:
array([[-2, -3, -5],
[ 0, 0, 0],
[ 2, 3, 5]])
In [10]: np.dot(a.T, b)[0][0]
Out[10]: 3
成分指定でスカラー
として取り出す場合
17. 17
Python機械学習プログラミング
ブロードキャストルール
■
スカラー演算をarrayに適用すると、各成分に対する演算が行われます。これをブロー
ドキャストルールと呼びます。
- 行列/ベクトルのスカラー倍は、ブロードキャストルールとして自然に計算されます。
- 次は、数学の演算としては不自然ですが、ブロードキャストルールが適用される例になります。
In [11]: m = np.array([[1,2],[3,4]])
m
Out[11]: array([[1, 2],
[3, 4]])
In [12]: 2*m
Out[12]: array([[2, 4],
[6, 8]])
In [13]: m*2
Out[13]: array([[2, 4],
[6, 8]])
In [14]: m**2
Out[14]: array([[ 1, 4],
[ 9, 16]])
In [15]: m+10
Out[15]: array([[11, 12],
[13, 14]])
In [16]: [1,2,3] * 2
Out[16]: [1, 2, 3, 1, 2, 3]
In [17]: np.array([1,2,3]) * 2
Out[17]: array([2, 4, 6])
※次の計算は、リストとarrayで結果が異なるので
注意してください。
18. 18
Python機械学習プログラミング
ブロードキャストルール
- ブロードキャストルールを活用すると、リスト/arrayに対して、arrayを返す関数が簡単に作れ
ます。
- 上の例では、リストをarrayに変換していますが、引数は常にarrayで渡すことがわかっている場
合、この処理は省略しても構いません。
In [18]: def square(x):
if isinstance(x, list):
x = np.array(x)
return x**2
In [19]: square(3)
Out[19]: 9
In [20]: square([1,2,3])
Out[20]: array([1, 4, 9])
In [21]: square(np.array([1,2,3]))
Out[21]: array([1, 4, 9])
In [22]: def square(x):
return x**2
square(np.array([1,2,3]))
Out[22]: array([1, 4, 9])
19. 19
Python機械学習プログラミング
ブロードキャストルール
■
同じサイズのarray同士のスカラー演算は、対応する成分同士の演算になります。
- 行列の和/差は、自然に計算されます。
- 次のような演算も可能です。
※ サイズの異なるarray同士のスカラー演算にも、一定の法則でブロードキャストルールが適用されますが、
直感的にわかりにくい結果になるので、なるべく使用しない方がよいでしょう。
In [23]: a = np.array([[10,20],[30,40]])
a
Out[23]: array([[10, 20],
[30, 40]])
In [24]: b = np.array([[1,2],[3,4]])
b
Out[24]: array([[1, 2],
[3, 4]])
In [27]: a**b
Out[27]: array([[ 10, 400],
[ 27000, 2560000]])
In [25]: a+b
Out[25]: array([[11, 22],
[33, 44]])
In [26]: a-b
Out[27]: array([[ 9, 18],
[27, 36]])
20. 20
Python機械学習プログラミング
arrayオブジェクトの生成と変形
■
arrayオブジェクト生成/変形の定番パターンには、次のようなものがあります。
- np.zeros()、np.ones()を用いると、全成分が0、もしくは、1のarrayが得られます。行列サイズ
を表すタプル (y, x) を引数として渡します。np.eye()は単位行列を生成します。
- 既存のarrayオブジェクトは、reshape()メソッドで縦横のサイズを変更できます。現在のサイズ
は、shape属性で参照できます。
In [28]: np.zeros((3,3))
Out[28]: array([[ 0., 0., 0.],
[ 0., 0., 0.],
[ 0., 0., 0.]])
In [29]: np.ones((2,3))
Out[29]: array([[ 1., 1., 1.],
[ 1., 1., 1.]])
In [31]: a = np.array([1,2,3,4,5,6])
a
Out[31]: array([1, 2, 3, 4, 5, 6])
In [32]: b = a.reshape((2,3))
b
Out[32]: array([[1, 2, 3],
[4, 5, 6]])
In [33]: c = b.reshape((3,2))
c
Out[33]: array([[1, 2],
[3, 4],
[5, 6]])
In [34]: b.shape
Out[34]: (2, 3)
In [35]: c.shape
Out[35]: (3, 2)
In [30]: np.eye(4)
Out[30]: array([[ 1., 0., 0., 0.],
[ 0., 1., 0., 0.],
[ 0., 0., 1., 0.],
[ 0., 0., 0., 1.]])
21. 21
Python機械学習プログラミング
arrayオブジェクトの生成と変形
- reshape()を用いると、1次元リストを2次元配列としてのベクトルに変換できます。
※ この変換は次の方法でも可能です。
- 等差数列のarrayは、np.arange()で生成します。np.arange(x, y, s) とした場合、x から y の範囲
で公差 s の数列を生成します。終点 y は、数列に含まれない点に注意が必要です。
In [36]: x = [1,2,3,4]
np.array(x).reshape(len(x),1)
Out[36]: array([[1],
[2],
[3],
[4]])
In [39]: np.arange(0, 1, 0.1)
Out[39]: array([ 0. , 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9])
In [37]: np.array([x])
Out[37]: array([[1, 2, 3, 4]])
In [38]: np.array([x]).T
Out[38]: array([[1],
[2],
[3],
[4]])
22. 22
Python機械学習プログラミング
(参考)arrayオブジェクトの生成と変形
- np.vstack()とnp.hstack()は、それぞれ、2つの配列を縦、または、横に結合します。
In [40]: a = np.ones(9).reshape((3,3))
a
Out[40]: array([[ 1., 1., 1.],
[ 1., 1., 1.],
[ 1., 1., 1.]])
In [41]: b = a*2
b
Out[41]: array([[ 2., 2., 2.],
[ 2., 2., 2.],
[ 2., 2., 2.]])
In [42]: np.vstack((a,b))
Out[42]: array([[ 1., 1., 1.],
[ 1., 1., 1.],
[ 1., 1., 1.],
[ 2., 2., 2.],
[ 2., 2., 2.],
[ 2., 2., 2.]])
In [43]: np.hstack((a,b))
Out[43]: array([[ 1., 1., 1., 2., 2., 2.],
[ 1., 1., 1., 2., 2., 2.],
[ 1., 1., 1., 2., 2., 2.]])
23. 23
Python機械学習プログラミング
(参考)1次元のarrayに対するnp.dot()の計算
■
np.dot()に1次元のarrayを代入した場合は、文脈に合わせて縦ベクトル/横ベクトルの
解釈が行われます。
- 1次元arrayどうしは内積になります。
- 2次元arrayと1次元arrayは、行列としての積になります。
※ 上記以外の組み合わせパターンの場合は、結果が直感とあわない場合もありますので、あまり使用しない方
がよいでしょう。
In [44]: a = np.array([-1, 0, 1])
b = np.array([ 1, 2, 3])
np.dot(a, b)
Out[44]: 2
In [45]: m = np.array([1,1,1,2,2,2,3,3,3]).reshape(3,3)
m
Out[45]: array([[1, 1, 1],
[2, 2, 2],
[3, 3, 3]])
In [46]: np.dot(m,a)
Out[46]: array([0, 0, 0])
In [47]: np.dot(a,m)
Out[47]: array([2, 2, 2])
26. 26
Python機械学習プログラミング
一様分布からの乱数の取得
■
rand() (numpy.randomモジュールが提供)、および、randint()を用いると、指定範
囲の一様な乱数が得られます。また、一度に多数の乱数を生成することができます。
- rand()は、 の範囲(1は含まない)の実数値の乱数を指定の個数だけ生成します。指
定サイズのarrayとして値を返します。
- 同様に、randint()は指定範囲の整数値の乱数を指定の個数だけ生成します。次は、1〜6の範囲
(7は含まない点に注意)の乱数を生成する例です。
In [2]: from numpy.random import rand
rand()
Out[2]: 0.19644145945572267
In [3]: rand(5)
Out[3]: array([ 0.64765831, 0.41288461, 0.21530768, 0.3225688 , 0.55119995])
In [4]: rand(2,3)
Out[4]: array([[ 0.63193604, 0.48647432, 0.06980617],
[ 0.32513886, 0.29350987, 0.58432974]])
In [5]: from numpy.random import randint
randint(1,7)
Out[5]: 1
In [6]: randint(1,7,10)
Out[6]: array([2, 4, 3, 6, 4, 6, 1, 6, 2, 3])
In [7]: randint(1,7,(3,5))
Out[7]:
array([[3, 1, 3, 1, 5],
[2, 5, 5, 1, 1],
[1, 3, 6, 5, 2]])
27. 27
Python機械学習プログラミング
正規分布からの乱数の取得
■
numpy.randomモジュールの normal() を用いると、正規分布からの乱数が得られます。
- 次のように、loc(平均)、scale(標準偏差)、size(arrayのサイズ)を指定します。最後の例
のように、パラメータ名を省略しても構いません。
- 1000個の乱数を発生して、ヒストグラムを表示します。
In [8]: from numpy.random import normal
normal(loc=0,scale=3,size=10)
Out[8]: array([-0.45405421, 1.03407066, -6.06638636, -1.47014096, 2.4127684 ,
-0.60084586, -2.20008908, -2.49174201, -5.53419474, -2.99053036])
In [9]: normal(loc=0,scale=3,size=(3,2))
Out[9]: array([[ 4.94332685, -2.65134418],
[-5.97073959, -0.94864428],
[-1.04192588, 2.29266043]])
In [10]: normal(0,3,(3,2))
Out[10]: array([[ 4.55288412, -3.28343893],
[ 2.981074 , -2.05497678],
[ 0.08205987, 0.77338863]])
In [5]: val = normal(10,3,size=1000)
In [6]: plt.hist(val, bins=20)
28. 28
Python機械学習プログラミング
正規分布からの乱数の取得
■
numpy.randomモジュールの multivariate_normal() を用いると、多次元の正規分布か
らの乱数が得られます。
- 次のように、mean(平均)、cov(分散共分散行列)、size(arrayのサイズ)を指定します。
パラメータ名は省略しても構いません。
- 200個の乱数を発生して、散布図を表示します。
In [11]: from numpy.random import multivariate_normal
c = np.array([[3,2],[2,3]])
c
Out[11]: array([[3, 2],
[2, 3]])
In [12]: multivariate_normal(mean=[50,10],cov=c,size=4)
Out[12]: array([[ 52.09847888, 11.7263966 ],
[ 50.72997909, 9.15308538],
[ 51.75341106, 11.19224385],
[ 48.61627847, 9.09737349]])
In [13]: vals = multivariate_normal([50,10],c,200)
data_x = [x for (x,y) in vals]
data_y = [y for (x,y) in vals]
plt.scatter(data_x, data_y)
32. 32
Python機械学習プログラミング
複数グラフの描画
■
次は、描画ウィンドウを分割して、複数のグラフを並べる際の定番パターンです。
- fig.add_subplot(y, x, c) で取得した描画位置を示すオブジェクト(サブプロット)に対して、
scatter()、plot()などのメソッドを適用します。(描画位置は左上が「1」で、はじめに右に進
みます。)
- 次は、サブプロットに対して、タイトル、x軸/y軸の描画範囲、x軸/y軸のタイトルを指定する
例です。
fig = plt.figure(figsize=(14,4))
subplot = fig.add_subplot(2,3,1)
subplot.plot(data1_x, data1_y)
subplot = fig.add_subplot(2,3,2)
subplot.scatter(data2_x, data2_y)
...
fig.show()
描画ウィンドウのオブジェクトを取得
描画ウィンドウを縦2 x 横3 に分割した1つ目の描画位置
描画ウィンドウを縦2 x 横3 に分割した2つ目の描画位置
1
4
2
5
3
6
描画ウィンドウを表示
subplot.set_title('ROC graph')
subplot.set_xlim([0, 1])
subplot.set_ylim([0, 1])
subplot.set_xlabel("False positive rate")
subplot.set_ylabel("True positive rate")
35. 35
Python機械学習プログラミング
乱数データの生成とグラフ表示
■
次の条件で乱数データを生成してグラフに表示します。
- の範囲を n 等分したそれぞれの点 x について、正弦関数 の値に平均 0、標
準偏差 0.3 の正規分布ノイズを加えた値 y を生成します。
- 次は、繰り返し処理を用いた、素朴な実装例です。
- 次はブロードキャストルールを利用した実装例です。
from numpy.random import normal
def generate_data01(n):
data_x = []
data_y = []
for i in range(n):
x = float(i) / float(n-1) # [0, 1]をn等分したi番目の値
y = np.sin(2*np.pi*x) + normal(0, 0.3)
data_x.append(x)
data_y.append(y)
return data_x, data_y
from numpy.random import normal
def generate_data02(n):
data_x = np.linspace(0,1,n) # [0, 1]をn等分した値のリスト
data_y = np.sin(2*np.pi*data_x) + normal(0, 0.3, n)
return data_x, data_y
36. 36
Python機械学習プログラミング
乱数データの生成とグラフ表示
■
次のコードを実行すると以下のグラフ表示されます。
- サブプロットオブジェクトに複数のグラフ描画メソッドを適用するとグラフを重ねて表示するこ
とができます。
- labelオプションでグラフに付与したラベルは、legend()メソッドで凡例として表示されます。凡
例の表示位置(locオプション)については、下記を参照。
●
http://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.legend
fig = plt.figure()
data_x, data_y = generate_data01(10)
#data_x, data_y = generate_data02(10)
subplot = fig.add_subplot(1,1,1)
subplot.set_xlabel('Observation point')
subplot.set_ylabel('Value')
subplot.set_xlim(-0.05,1.05)
# 生成したデータを表示
subplot.scatter(data_x, data_y,
marker='o', color='blue',
label='Observed value')
# 三角関数の曲線を表示
linex = np.linspace(0,1,100)
liney = np.sin(2*np.pi*linex)
subplot.plot(linex, liney,
linestyle='--', color='green',
label='Theoretical curve')
# 凡例を表示
subplot.legend(loc=1)
42. 42
Python機械学習プログラミング
arrayをDataFrameに変換する方法
■
次は、2次元のarrayをDataFrameに変換する例です。
- columnsオプションで、各列のcolumn名を指定します。
In [2]: from numpy.random import randint
dices = randint(1,7,(5,2))
dices
Out[2]: array([[6, 6],
[2, 2],
[2, 2],
[1, 5],
[6, 2]])
In [3]: diceroll = DataFrame(dices, columns=['dice1','dice2'])
Diceroll
Out[3]:
43. 43
Python機械学習プログラミング
Seriesオブジェクトをまとめる方法
■
次は、SeriesオブジェクトからDataframeを作成する例です。
- はじめに、各列のデータに対応するSeriesオブジェクトを作成します。Seriesオブジェクトは、
nameオプションでデータの名前が付与できます。
In [4]: city = Series(['Tokyo','Osaka','Nagoya','Okinawa'], name='City')
city
Out[4]:
0 Tokyo
1 Osaka
2 Nagoya
3 Okinawa
Name: City, dtype: object
In [5]: temp = Series([25.0,28.2,27.3,30.9], name='Temperature')
temp
Out[5]:
0 25.0
1 28.2
2 27.3
3 30.9
Name: Temperature, dtype: float64
In [6]: humid = Series([44,42,np.nan,62], name='Humidity')
humid
Out[6]:
0 44
1 42
2 NaN
3 62
Name: Humidity, dtype: float64
np.nanは欠損値を表す
ダミーデータです。
44. 44
Python機械学習プログラミング
Seriesオブジェクトをまとめる方法
- 各列のcolumn名と対応するSeriesオブジェクトのディクショナリを与えて、DataFrameを生成し
ます。
- Seriesオブジェクトの代わりに、リストを用いてもDataFrameを生成することができます。
In [7]: cities = DataFrame({'City':city, 'Temperature':temp, 'Humidity':humid})
cities
Out[7]:
In [8]: data = {'City': ['Tokyo','Osaka','Nagoya','Okinawa'],
'Temperature': [25.0,28.2,27.3,30.9],
'Humidity': [44,42,np.nan,62]}
cities = DataFrame(data)
Out[8]:
47. 47
Python機械学習プログラミング
DataFrameを結合する方法
■
DataFrameのappend()メソッドは、2つのDataFrameを結合する際にも利用できます。
- ignore_index=Trueを指定すると、indexは通し番号になるように再割当てが行われます。指定
がない場合、元のDataFrameのindexが保存されます。
In [16]: diceroll3 = diceroll1.append(diceroll2)
diceroll3
Out[16]:
In [17]: diceroll4 = diceroll1.append(diceroll2,
ignore_index=True)
diceroll4
Out[17]:
In [14]: diceroll1 = DataFrame(randint(1,7,(5,2)),
columns=['dice1','dice2'])
diceroll1
Out[14]:
In [15]: diceroll2 = DataFrame(randint(1,7,(3,2)),
columns=['dice1','dice2'])
diceroll2
indexを通し番号で
採番しなおす。
48. 48
Python機械学習プログラミング
DataFrameに列を追加する方法
■
次は、DataFrameに列を追加する例です。
- 配列のindex記法でcolumn名を指定して追加します。(属性で指定する方法は使えません。)
- pd.concat()関数で複数のSeriesを列として結合したり、既存のDataFrameにSeriesを列として追
加することもできます。
※ DataFrameの結合方法の全体像については、次のドキュメントを参照
http://pandas.pydata.org/pandas-docs/stable/merging.html
In [18]: diceroll = DataFrame()
diceroll['dice1'] = randint(1,7,5)
diceroll
Out[18]:
In [19]: diceroll['dice2'] = randint(1,7,5)
diceroll
Out[19]:
In [20]: dice1 = Series(randint(1,7,5),name='dice1')
dice2 = Series(randint(1,7,5),name='dice2')
diceroll = pd.concat([dice1, dice2], axis=1)
diceroll
Out[20]:
In [21]: dice3 = Series(randint(1,7,5),name='dice3')
diceroll = pd.concat([diceroll, dice3], axis=1)
diceroll
Out[21]:
列方向での結合
52. 52
Python機械学習プログラミング
列の取り出し
■
複数の列をDataFrameとして取り出すこともできます。
- 配列のindexに複数のcolumn名のリストを指定します。
- 単一の列をSeriesではなく、DataFrameとして取り出す際は次のようにします。
In [5]: data = {'City': ['Tokyo','Osaka','Nagoya','Okinawa'],
'Temperature': [25.0,28.2,27.3,30.9],
'Humidity': [44,42,np.nan,62]}
cities = DataFrame(data)
cities
Out[5]:
In [6]: cities[['City', 'Humidity']]
Out[6]:
cities['City', 'Humidity']
ではないので注意
In [7]: cities[['City']]
Out[7]:
In [8]: cities['City']
Out[8]:
0 Tokyo
1 Osaka
2 Nagoya
3 Okinawa
Name: City, dtype: object
DataFrameとして
取り出し
Seriesとして
取り出し
61. 61
Python機械学習プログラミング
DataFrame/Seriesのarrayへの変換
■
DataFrame/Seriesをarrayに変換する方法です。
- as_matrix()メソッドを使用します。
※arrayを引数とする関数では、DataFrame/Seriesを代入すると自動的にarrayへの変換が
行われます。
In [2]: data = {'City': ['Tokyo','Osaka','Nagoya','Okinawa'],
'Temperature': [25.0,28.2,27.3,30.9],
'Humidity': [44,42,np.nan,62]}
cities = DataFrame(data)
cities
Out[2]:
In [3]: cities.as_matrix()
Out[3]:
array([['Tokyo', 44.0, 25.0],
['Osaka', 42.0, 28.2],
['Nagoya', nan, 27.3],
['Okinawa', 62.0, 30.9]], dtype=object)
In [4]: cities['City'].as_matrix()
Out[4]: array(['Tokyo', 'Osaka', 'Nagoya', 'Okinawa'], dtype=object)
62. 62
Python機械学習プログラミング
行のシャッフル
■
トランプのカードを集めたDataFrameで、カードのシャッフルを行います。
- トランプのカードを集めたDataFrameを定義します。
- permutation()関数は、arrayの要素の順番をランダム入れ替えます。下記は、index属性で取り
出したindexの順番をシャッフルしています。
In [5]: face = ['king','queen','jack','ten','nine','eight',
'seven','six','five','four','three','two','ace']
suit = ['spades', 'clubs', 'diamonds', 'hearts']
value = range(13,0,-1)
deck = DataFrame({'face': np.tile(face,4),
'suit': np.repeat(suit,13),
'value': np.tile(value,4)})
deck.head()
Out[5]:
In [6]: np.random.permutation(deck.index)
Out[6]: array([48, 33, 6, 49, 10, 28, 41, 18, 32, 36, 19, 14, 25, 46, 30, 51, 2,
31, 12, 5, 42, 4, 9, 40, 43, 13, 16, 35, 8, 1, 50, 20, 17, 22,
24, 11, 26, 47, 37, 27, 45, 29, 0, 3, 44, 34, 38, 39, 15, 21, 7,
23])
先頭部分のデータだけを
取り出すメソッド
64. 64
Python機械学習プログラミング
In [9]: result = DataFrame()
for c in range(3):
y = 0
t = []
for delta in np.random.normal(loc=0.0, scale=1.0, size=100):
y += delta
t.append(y)
result['Trial %d' % c] = t
result.head()
Out[9]:
In [10]: result.plot(title='Random walk')
データフレームによるグラフの描画
■
DataFrameオブジェクトは自分自身のグラフを描く機能を持っています。
- 次のようにplot()メソッドを用いると、列ごとのデータをまとめてグラフに表示することができ
ます。
※ plot()メソッドの詳細は下記を参照
http://pandas.pydata.org/pandas-docs/version/0.17.0/visualization.html
68. 68
Python機械学習プログラミング
In [2]: def create_dataset(num):
dataset = DataFrame(columns=['x','y'])
for i in range(num):
x = float(i)/float(num-1)
y = np.sin(2*np.pi*x) + normal(scale=0.3)
dataset = dataset.append(Series([x,y], index=['x','y']),
ignore_index=True)
return dataset
In [3]: train_set = create_dataset(10)
In [4]: train_set
In [5]: train_set.plot(kind='scatter', x='x', y='y',
xlim=[-0.1,1.1], ylim=[-1.5,1.5])
サンプルデータの作成
■
区間 を等分したデータセットを生成します。
- (x, y) 座標を列に持つDataFrameとして用意します。ここでは、空のデータフレームに、1行ず
つSeriesオブジェクトを追加する方法で作成しています。
70. 70
Python機械学習プログラミング
係数の決定
■
最小二乗法の公式を用いて、多項式の係数を計算します。
- 次の関数では、決定された多項式 と係数 を返しています。
In[7] : def resolve(dataset, m):
t = dataset.y
phi = DataFrame()
for i in range(0,m+1):
p = dataset.x**i
p.name="x**%d" % i
phi = pd.concat([phi,p], axis=1)
tmp = np.linalg.inv(np.dot(phi.T, phi))
ws = np.dot(np.dot(tmp, phi.T), t)
def f(x):
y = 0
for i, w in enumerate(ws):
y += w * (x ** i)
return y
return (f, ws)
71. 71
Python機械学習プログラミング
係数の決定
- 各変数の内容を表示すると、次のようになります。
- 行列 は、DataFrameに列を追加する方法で作成しています。
In[8] : def resolve(dataset, m):
t = dataset.y
print "nt:"
print t
phi = DataFrame()
for i in range(0,m+1):
p = dataset.x**i
p.name="x**%d" % i
phi = pd.concat([phi,p], axis=1)
print "nphi:"
print phi
tmp = np.linalg.inv(np.dot(phi.T, phi))
ws = np.dot(np.dot(tmp, phi.T), t)
print "nws:"
print ws
def f(x):
y = 0
for i, w in enumerate(ws):
y += w * (x ** i)
return y
return (f, ws)
In[9] : f = resolve_debug(train_set, 3)
t:
0 -0.176290
1 0.406402
2 0.592576
3 1.175387
4 0.652480
5 -0.477052
6 -1.123978
7 -0.720408
8 -0.417265
9 -0.253635
Name: y, dtype: float64
phi:
x**0 x**1 x**2 x**3
0 1 0.000000 0.000000 0.000000
1 1 0.111111 0.012346 0.001372
2 1 0.222222 0.049383 0.010974
3 1 0.333333 0.111111 0.037037
4 1 0.444444 0.197531 0.087791
5 1 0.555556 0.308642 0.171468
6 1 0.666667 0.444444 0.296296
7 1 0.777778 0.604938 0.470508
8 1 0.888889 0.790123 0.702332
9 1 1.000000 1.000000 1.000000
ws:
[ -0.29207698, 11.0815224 , -30.56215955, 19.6937635 ]
73. 73
Python機械学習プログラミング
In [12]: def show_result(subplot, train_set, m):
f = resolve(train_set, m)
subplot.set_xlim(-0.05,1.05)
subplot.set_ylim(-1.5,1.5)
subplot.set_title("M=%d" % m)
# トレーニングセットを表示
subplot.scatter(train_set.x, train_set.y, marker='o',
color='blue', label=None)
# 真の曲線を表示
linex = np.linspace(0,1,101)
liney = np.sin(2*np.pi*linex)
subplot.plot(linex, liney, color='green', linestyle='--')
# 多項式近似の曲線を表示
linex = np.linspace(0,1,101)
liney = f(linex)
label = "E(RMS)=%.2f" % rms_error(train_set, f)
subplot.plot(linex, liney, color='red', label=label)
subplot.legend(loc=1)
In [13]: fig = plt.figure(figsize=(8, 6))
for i, m in enumerate([0,1,3,9]):
subplot = fig.add_subplot(2,2,i+1)
show_result(subplot, train_set, m)
分析結果のグラフ表示
■
決定された多項式の曲線など、分析結果をまとめてグラフに表示します。
- subplotオブジェクトを受け取って、その部分にグラフを描く関数を用意します。
- 次は、4種類のグラフをまとめて描きます。
74. 74
Python機械学習プログラミング
平方根平均二乗誤差の変化
■
多項式の次数にともなう平方根平均二乗誤差の変化を計算します。
- 次はトレーニングセットとテストセットについて、それぞれの平方根平均二乗誤差を計算してい
ます。 の各次数での結果をDataFrameにまとめて、グラフを表示します。
In [14]: def show_rms_trend(train_set, test_set):
df = DataFrame(columns=['Training set','Test set'])
for m in range(0,10): # 多項式の次数
f = resolve(train_set, m)
train_error = rms_error(train_set, f)
test_error = rms_error(test_set, f)
df = df.append(Series([train_error, test_error],
index=['Training set','Test set']),
ignore_index=True)
df.plot(title='RMS Error', style=['-','--'], grid=True, ylim=(0,0.9))
75. 75
Python機械学習プログラミング
In [15]: def show_rms_trend(train_set, test_set):
df = DataFrame(columns=['Training set','Test set'])
for m in range(0,10): # 多項式の次数
f = resolve(train_set, m)
train_error = rms_error(train_set, f)
test_error = rms_error(test_set, f)
df = df.append(Series([train_error, test_error],
index=['Training set','Test set']),
ignore_index=True)
print df
df.plot(title='RMS Error', style=['-','--'], grid=True, ylim=(0,0.9))
In [16]: train_set = create_dataset(10)
test_set = create_dataset(10)
show_rms_trend_debug(train_set, test_set)
Training set Test set
0 0.654370 0.743018
1 0.465365 0.573458
2 0.462929 0.576735
3 0.138445 0.281417
4 0.136046 0.290995
5 0.126021 0.280504
6 0.071521 0.293895
7 0.013880 0.310773
8 0.013857 0.311028
9 0.000186 0.314195
平方根平均二乗誤差の変化
- 次は実際に平方根平均二乗誤差をまとめたDataFrameの例です。
DataFrameの機能で
グラフを表示
78. 78
Python機械学習プログラミング
サンプルデータの作成
■
の属性を持つデータセットを用意します。
- 次の関数では、(x, y, t) それぞれの値を列とするDataFrameにまとめています。
In[2] : def prepare_dataset(n1, mu1, variance1, n2, mu2, variance2):
df1 = DataFrame(multivariate_normal(mu1, np.eye(2)*variance1 ,n1),
columns=['x','y'])
df1['type'] = 1
df2 = DataFrame(multivariate_normal(mu2, np.eye(2)*variance2, n2),
columns=['x','y'])
df2['type'] = -1
df = pd.concat([df1,df2], ignore_index=True)
df = df.reindex(np.random.permutation(df.index)).reset_index(drop=True)
return df
In[3] : train_set = prepare_dataset(20, [15,10], 15, 30, [0,0], 15)
In [4]: train_set.head(10)
79. 79
Python機械学習プログラミング
サンプルデータの作成
■
先の関数の処理の流れは、次のようになります。
- はじめに、 それぞれのデータを個別のDataFrameとして用意します。
- np.random.multivariate_normal() で2次元正規分布のDataFrameを作成して、その後で、type
の列を追加しています。
- 2つのDataFrameを結合して行をシャッフルすることで、最終的なデータセットとしています。
In [6]: train_set = prepare_dataset_debug(20, [15,10], 15, 30, [0,0], 15)
df1:
x y type
0 16.781857 13.639916 1
1 16.884073 6.919148 1
2 12.056751 4.794741 1
3 12.730577 14.388435 1
4 11.577948 9.154710 1
df2:
x y type
0 1.323629 2.003764 -1
1 1.874265 2.324382 -1
2 1.760324 1.896797 -1
3 -2.279221 -2.780630 -1
4 -3.115091 5.504012 -1
In[5] : def prepare_dataset_debug(n1, mu1, variance1, n2, mu2, variance2):
df1 = DataFrame(multivariate_normal(mu1, np.eye(2)*variance1 ,n1),
columns=['x','y'])
df1['type'] = 1
print 'ndf1:'
print df1.head()
df2 = DataFrame(multivariate_normal(mu2, np.eye(2)*variance2, n2),
columns=['x','y'])
df2['type'] = -1
print 'ndf2:'
print df2.head()
df = pd.concat([df1,df2], ignore_index=True)
df = df.reindex(np.random.permutation(df.index)).reset_index(drop=True)
return df
df = pd.concat([df1,df2], ignore_index=True)
df = df.reindex(np.random.permutation(df.index)).reset_index(drop=True)
return df
80. 80
Python機械学習プログラミング
パーセプトロンによる係数の決定
■
次はパーセプトロンのアルゴリズムで係数を修正する処理の流れです。
- iterrows()メソッドでトレーニングセットの各データについて、「正しく分類されない点につい
て係数の修正を行う」という処理を行ないます。この処理を30回繰り返して、それぞれの回を終
えた時点の係数をDataFrameとして記録していきます。
In [7] : def run_train(train_set):
# パラメータの初期値とbias項の設定
w0 = w1 = w2 = 0.0
bias = 0.5 * (train_set.x.mean() + train_set.y.mean())
# Iterationを実施
paramhist = DataFrame([[w0,w1,w2]], columns=['w0','w1','w2'])
for i in range(30):
for index, point in train_set.iterrows():
x, y, type = point.x, point.y, point.type
if type * (w0*bias + w1*x + w2*y) <= 0:
w0 += type * bias
w1 += type * x
w2 += type * y
paramhist = paramhist.append(Series([w0,w1,w2], ['w0','w1','w2']),
ignore_index=True)
# 判定誤差の計算
err = 0
for index, point in train_set.iterrows():
x, y, type = point.x, point.y, point.type
if type * (w0*bias + w1*x + w2*y) <= 0:
err += 1
err_rate = err * 100 / len(train_set)
return paramhist, err_rate
正しく分類されない点に
ついて係数を修正
81. 81
Python機械学習プログラミング
In [8]: paramhist, err_rate = run_train(train_set)
paramhist.head(10)
In [9]: paramhist.plot.legend(loc=1)
パーセプトロンによる係数の決定
- 係数の変化を記録したDataFrameの様子です。DataFrameの機能を利用して、グラフを描くこと
ができます。
82. 82
Python機械学習プログラミング
グラフの描画
■
トレーニングセットのデータと決定された直線は、サブプロットオブジェクトの
scatter()、および、plot()メソッドで表示しています。
In [10]: def show_result(subplot, train_set, w0, w1, w2, err_rate):
train_set1 = train_set[train_set['type']==1]
train_set2 = train_set[train_set['type']==-1]
bias = 0.5 * (train_set.x.mean() + train_set.y.mean())
ymin, ymax = train_set.y.min()-5, train_set.y.max()+10
xmin, xmax = train_set.x.min()-5, train_set.x.max()+10
subplot.set_ylim([ymin-1, ymax+1])
subplot.set_xlim([xmin-1, xmax+1])
subplot.scatter(train_set1.x, train_set1.y, marker='o', label=None)
subplot.scatter(train_set2.x, train_set2.y, marker='x', label=None)
linex = np.arange(xmin-5, xmax+5)
liney = - linex * w1 / w2 - bias * w0 / w2
label = "ERR %.2f%%" % err_rate
subplot.plot(linex, liney, label=label, color='red')
subplot.legend(loc=1)
In [11] : fig = plt.figure()
subplot = fig.add_subplot(1,1,1)
params = paramhist[-1:]
w0, w1, w2 = float(params.w0), float(params.w1), float(params.w2)
show_result(subplot, train_set, w0, w1, w2, err_rate)
t=±1のデータを
個別に取り出し
一番最後の係数の
値を取り出し