多重回帰分析の実装、そして儚さ。
こんにちは、ワタルです。
はじめに
今回は、多重回帰分析について、理論的な仕組みを理解できるよう解説しつつ、実装してみようと思います。 さらに、その実装がseabornであれば1行で終わってしまう儚さを体験しつつ、seabornにおける多重回帰分析のメソッドを学びたいと思います。
数学的に厳密には正しくない説明になっている箇所もあるかと思います。説明に違和感を覚える方がいましたら是非勉強させていただきますので、コメントを頂けましたらと思います。
目的
今回は、以下のデータ群に対して、基底関数として3次項までの多項式基底を用い、推定モデルを算出することが目的になります。
線形回帰とは
計算に入る前に簡単に線形回帰について解説してみたいと思います。
まず、回帰とは、与えられたデータに適した関数を求める手法のことで、線形回帰とは、回帰分析の中の1つの手法のことを指します。
線形回帰の中でも、基底関数に多項式基底を用いた手法を多重回帰分析と呼びます。
ちなみに、基底関数に1次元項までの場合、単回帰分析と呼びます。
多重回帰分析の実装
さあ実装していきます。
まずはおまじないです。
import numpy as np import matplotlib.pyplot as plt %matplotlib inline import seaborn as sns
データ群を確認します。
X = np.array([0.02, 0.12, 0.19, 0.27, 0.42, 0.51, 0.64, 0.84, 0.88, 0.99]) t = np.array([0.05, 0.87, 0.94, 0.92, 0.54, -0.11, -0.78, -0.89, -0.79, -0.04]) plt.scatter(X,t)
天下り的ですが、ここで、3次関数っぽいなという感覚から今回は、3次多項式基底を用いることを思いつきます。 簡単のため、正規化項や過学習については、他のwebページに譲ることとします。
思いついたモデルは、係数が4×1の行列とすると、その解の行列を用いて、このように記述することができます。
ここで、Xの要素を求めるを求めます。
def phi(x): return [1, x, x**2, x**3] PHI = np.array([phi(x) for x in X])
次に、二乗誤差を算出するために、の転置行列で左から積を取り、 さらに左からその逆行列の積を取ることで、を求めます。
w = np.linalg.solve(np.dot(PHI.T, PHI), np.dot(PHI.T, t))
最後にプロットします。
def f(w, x): return np.dot(w, phi(x)) xlist = np.arange(0, 1, 0.01) ylist = [f(w, x) for x in xlist] plt.plot(xlist, ylist) plt.plot(X, t, 'o')
ここまでで、よくできた重回帰モデルができました。
seabornを用いて多重回帰分析の実装
次にseabornを用いて、ここまでの計算を1から行ってみます。
おまじないは同じなので省略します。
X = np.array([0.02, 0.12, 0.19, 0.27, 0.42, 0.51, 0.64, 0.84, 0.88, 0.99]) t = np.array([0.05, 0.87, 0.94, 0.92, 0.54, -0.11, -0.78, -0.89, -0.79, -0.04]) sns.regplot(X,t,order=3)
終わってしまいました。。。
このように、regplotに引数(order=3)をしたことで、3次項までの重回帰分析を行うことができます。
終わりに
今回は、多重回帰分析について、理論的な仕組みを理解しつつ、seabornにおける多重回帰分析のメソッドを学びました。
この様に、seabornやscikit-learnを用いると、あっという間に計算出来てしまいますが、一度くらいはせこせこと実装してみると勉強になると思います。
pandas入門8_「Dataframeにおける階層indexの考え方」
こんにちは、ワタルです。
さっと見て、「あぁそうだったそうだった」と確認できるハンドブックのような存在を目指して。
pandas入門第8回目、「Dataframeにおける階層indexの考え方」です。
今回の学習内容
今回は、階層的なindexを作る方法や、indexやcolumnsに名前を付ける方法について学んでいきます。
今回学ぶ関数
今回は、以下の関数について学びます。
dataframe.index.names = ['INDEX_1','INDEX_2'](indexに名前をつける) dataframe.columns.names = ['Columns1','Columns2'](columunsに名前をつける) dataframe.swaplevel('Columns1','Columns2',axis=1)(列方向の階層を逆にする)
おまじない
import numpy as np from pandas import Series,DataFrame import pandas as pd from numpy.random import randn
#まずは、階層的なindexとcolumnsをもったdataframeをつくります dframe = DataFrame(np.arange(16).reshape(4,4), index=[['a','a','b','b'],[1,2,1,2]], columns=[['A','A','B','C'],['X','Y','Y','X']]) dframe >>>
A | B | C | |||
---|---|---|---|---|---|
X | Y | Y | X | ||
a | 1 | 0 | 1 | 2 | 3 |
2 | 4 | 5 | 6 | 7 | |
b | 1 | 8 | 9 | 10 | 11 |
2 | 12 | 13 | 14 | 15 |
#階層的なindexに名前を付けてみます #以下のように行の名前をつけます dframe.index.names = ['INDEX_1','INDEX_2'] #以下のように行の名前をつけます dframe.columns.names = ['Columns1','Columns2'] dframe >>>
Columns1 | A | B | C | ||
---|---|---|---|---|---|
Columns2 | X | Y | Y | X | |
INDEX_1 | INDEX_2 | ||||
a | 1 | 0 | 1 | 2 | 3 |
2 | 4 | 5 | 6 | 7 | |
b | 1 | 8 | 9 | 10 | 11 |
2 | 12 | 13 | 14 | 15 |
dataframe.swaplevel('Columns1','Columns2',axis=1)(列方向の階層を逆にする)
#階層構造を逆にすることができます。今回は列方向を逆にします dframe.swaplevel('Columns1','Columns2',axis=1) >>>
Columns2 | X | Y | X | ||
---|---|---|---|---|---|
Columns1 | A | A | B | C | |
INDEX_1 | INDEX_2 | ||||
a | 1 | 0 | 1 | 2 | 3 |
2 | 4 | 5 | 6 | 7 | |
b | 1 | 8 | 9 | 10 | 11 |
2 | 12 | 13 | 14 | 15 |
今回は、少し短めでしたが、dataframeにおける階層的なindexを作る方法や、indexやcolumnsに名前を付ける方法について学びました。
お疲れ様でした!
それじゃー、また。
pandas入門7_「欠損値の扱い」
こんにちは、ワタルです。
さっと見て、「あぁそうだったそうだった」と確認できるハンドブックのような存在を目指して。
pandas入門第7回目、「欠損値の扱い」です。
今回の学習内容
今回は、欠損値が含まれたデータに対して、様々な対応の方法を学んでいきます。
今回学ぶ関数
今回は、以下の関数について学びます。
series.isnull()(欠損値を見つける) series.dropna()(欠損値を取り除く) dataframe.dropna()(dataframeの欠損値を取り除く) dataframe.drop(how='all')(全てが欠損値の行を落とす) dataframe.dropna(axis=1)(欠損値を含む列を落とす) dframe.dropna(thresh=n)(欠損値でない要素が決めた閾値数以上の行のみ表示する) dframe2.fillna(n)(欠損値を任意の数字で埋める)
- 今回の学習内容
- 今回学ぶ関数
- おまじない
- series.isnull()(欠損値を見つける)
- series.dropna()(欠損値を取り除く)
- dataframe.dropna()(dataframeの欠損値を取り除く)
- dframe2.fillna(n)(欠損値を任意の数字で埋める)
- 終わりに
おまじない
import numpy as np from numpy import nan from pandas import Series,DataFrame import pandas as pd
series.isnull()(欠損値を見つける)
#欠損値の含まれたseriesをつくります data = Series(['one','two', np.nan, 'four']) data >>> 0 one 1 two 2 NaN 3 four dtype: object
#null値を見つけます。 data.isnull() >>> 0 False 1 False 2 True 3 False dtype: bool
series.dropna()(欠損値を取り除く)
data.dropna() #欠損値の含まれていたindexが2の要素がなくなっていることがわかります >>> 0 one 1 two 3 four dtype: object
dataframe.dropna()(dataframeの欠損値を取り除く)
#seriesと同様にdataframeでも同じことができます #まずはdataframeをつくります dframe = DataFrame([[1,2,3],[np.nan,5,6],[7,np.nan,9],[np.nan,np.nan,np.nan]]) dframe >>> 0 1 2 0 1.0 2.0 3.0 1 NaN 5.0 6.0 2 7.0 NaN 9.0 3 NaN NaN NaN
dframe.dropna() #欠損値の含まれていないindexが0の行だけ残っていることがわかります >>> 0 1 2 0 1.0 2.0 3.0
dataframe.drop(how='all')(全てが欠損値の行を落とす)
dframe.dropna(how='all') #引数にhow='all'を指定したことで、全てが欠損値の行だけなくなっていることがわかります >>> 0 1 2 0 1.0 2.0 3.0 1 NaN 5.0 6.0 2 7.0 NaN 9.0
dataframe.dropna(axis=1)(欠損値を含む列を落とす)
dframe.dropna(axis=1) #どの列にも1つは欠損値があるので、すべての列がなくなっていることがわかります >>> 0 1 2 3
dframe.dropna(thresh=n)(欠損値でない要素が決めた閾値数以上の行のみ表示する)
#別のdataframeをつくります dframe2 = DataFrame([[1,2,3,np.nan],[2,np.nan,5,6],[np.nan,7,np.nan,9],[1,np.nan,np.nan,np.nan]]) dframe2 >>> 0 1 2 3 0 1.0 2.0 3.0 NaN 1 2.0 NaN 5.0 6.0 2 NaN 7.0 NaN 9.0 3 1.0 NaN NaN NaN
#nullではない値が2個以上存在する行のみ表示していることがわかります #つまり、index = 3の行がなくなっています dframe2.dropna(thresh=2) >>> 0 1 2 3 0 1.0 2.0 3.0 NaN 1 2.0 NaN 5.0 6.0 2 NaN 7.0 NaN 9.0
dframe2.fillna(n)(欠損値を任意の数字で埋める)
#欠損値を1で埋めてみます dframe2.fillna(1) >>> 0 1 2 3 0 1.0 2.0 3.0 1.0 1 2.0 1.0 5.0 6.0 2 1.0 7.0 1.0 9.0 3 1.0 1.0 1.0 1.0
列ごとに埋める値を決める
#0列目の欠損値には0を、1列目の欠損値には1を、というように埋めてみます dframe2.fillna({0:0,1:1,2:2,3:3}) >>> 0 1 2 3 0 1.0 2.0 3.0 3.0 1 2.0 1.0 5.0 6.0 2 0.0 7.0 2.0 9.0 3 1.0 1.0 2.0 3.0
終わりに
今回は、欠損値が含まれたデータに対して、様々な対応の方法について学びました。
お疲れ様でした!
次回はこちら
それじゃー、また。
pandas入門6_「Dataframeの操作と統計量」
こんにちは、ワタルです。
さっと見て、「あぁそうだったそうだった」と確認できるハンドブックのような存在を目指して。
pandas入門第6回目、「Dataframeの操作と統計量」です。
今回の学習内容
今回は、dataframeの合計や累積、様々な統計量の調べ方について学んでいきます。
今回学ぶ関数
今回は、以下の関数について学びます。
dataframe.sum()(行方向の合計) dataframe.sum(axis=1)(列方向の合計) dataframe.min()(行方向の最小値を求める。) dataframe.max()(行方向の最大値を求める。) dataframe.idxmin()(最小値の要素を持つindexを調べる) dataframe.idxmax()(最大値の要素を持つindexを調べる) dataframe.cumsum()(累積を求める) dataframe.describe()(DataFrameの様々な統計量をみる)
- 今回の学習内容
- 今回学ぶ関数
- おまじない
- dataframe.sum()(dataframeにおける行、列の合計)
- dataframe.min()(行方向の最小値を求める。)
- dataframe.idxmin()(最小値の要素を持つindexを調べる)
- dataframe.idxmax()(最小値の要素を持つindexを調べる)
- dataframe.cumsum()(累積を求める)
- dataframe.describe()(DataFrameの様々な統計量をみる)
- おわりに
おまじない
import numpy as np from pandas import Series,DataFrame import pandas as pd
dataframe.sum()(dataframeにおける行、列の合計)
#arrayからdataframeをつくります arr = np.array([[1,2,np.nan],[np.nan,3,4]]) dframe = DataFrame(arr,index=['A','B'],columns = ['One','Two','Three']) dframe >>> One Two Three A 1.0 2.0 NaN B NaN 3.0 4.0
dataframe.sum()(行方向の合計)
dframe.sum() #行方向の合計が計算されていることがわかります >>> One 1.0 Two 5.0 Three 4.0 dtype: float64
dataframe.sum(axis=1)(列方向の合計)
#引数に(axis=1)を指定することで、列方向が対象になります dframe.sum(axis=1) >>> A 3.0 B 7.0 dtype: float64
dataframe.min()(行方向の最小値を求める。)
dframe.min() #行の中の最小値が出力されていることがわかります #列方向に調べたいときは、引数に(axis=1)を指定します >>> One 1.0 Two 2.0 Three 4.0 dtype: float64
dataframe.idxmin()(最小値の要素を持つindexを調べる)
dframe1.idxmin()
>>>
One A
Two A
Three B
dtype: object
dataframe.idxmax()(最小値の要素を持つindexを調べる)
dframe.idxmax()
>>>
One A
Two B
Three B
dtype: object
dataframe.cumsum()(累積を求める)
dframe.cumsum() >>> One Two Three A 1.0 2.0 NaN B NaN 5.0 4.0
dataframe.describe()(DataFrameの様々な統計量をみる)
dframe.describe() #上から順に意味は以下の様になっています #count:columns方向の数 #mean:平均 #std:標準偏差 #min:最小値 #25%:第一四分位数 #50%:第二四分位数 #75%:第三四分位数 #max:最大値 >>> One Two Three count 1.0 2.000000 1.0 mean 1.0 2.500000 4.0 std NaN 0.707107 NaN min 1.0 2.000000 4.0 25% 1.0 2.250000 4.0 50% 1.0 2.500000 4.0 75% 1.0 2.750000 4.0 max 1.0 3.000000 4.0
第一四分位数についての詳細はこちらがおすすめです。 https://qiita.com/chatrate/items/e95ba42cffd6565d8fbb
おわりに
今回は、dataframeの合計や累積、様々な統計量の調べ方について学びました。
お疲れ様でした!
次回はこちら
それじゃー、また。
pandas入門5_「データの並び替え」
こんにちは、ワタルです。
さっと見て、「あぁそうだったそうだった」と確認できるハンドブックのような存在を目指して。
pandas入門第5回目、「データの並び替え」です。
- 今回の学習内容
- 今回学ぶ関数
- おまじない
- ser.sort_index()(indexで並び替える)
- ser.order()(値で並び替える)
- ser.rank()(何番目に小さいかを表す)
- ser.unique()(重複する要素をまとめる)
- ser1.value_counts()(重複するデータの数を数える)
今回の学習内容
今回は、Seriesの要素をindexの順や、要素小さい順に並び替えたり、その順位を見る方法について学んでいきます。
今回学ぶ関数
今回は、以下の関数について学びます。
ser.sort_index()(indexで並び替える) ser.order()(値で並び替える) ser.rank()(何番目に小さいかを表す) ser.unique()(重複する要素をまとめる) ser1.value_counts()(重複するデータの数を数える)
おまじない
import numpy as np from pandas import Series,DataFrame import pandas as pd from numpy.random import randn
ser.sort_index()(indexで並び替える)
#まずはseriesをつくります ser = Series(range(3),index=['C','A','B']) ser >>> C 0 A 1 B 2 dtype: int64
#indexで並び替えます ser1.sort_index() #A,B,Cの順になったことがわかります >>> A 1 B 2 C 0 dtype: int64
ser.order()(値で並び替える)
ser.order() >>> C 0 A 1 B 2 dtype: int64
ser.rank()(何番目に小さいかを表す)
#ランダムな要素を持ったseriesをつくります ser2 = Series(randn(10)) ser2 >>> 0 -1.188607 1 -0.821823 2 -1.003925 3 1.316921 4 -1.273743 5 -1.005138 6 -0.977085 7 -0.328831 8 -0.558445 9 1.552390 dtype: float64
#何番目に小さいかの順位をみてみます ser2.rank() >>> 0 2.0 1 6.0 2 4.0 3 9.0 4 1.0 5 3.0 6 5.0 7 8.0 8 7.0 9 10.0 dtype: float64
ser.unique()(重複する要素をまとめる)
#新たにseriesをつくります ser3 = Series(['w','w','x', 'y', 'z' ,'w' ,'w' ,'x' ,'x' ,'y' ,'a' ,'z' ]) ser3 >>> 0 w 1 w 2 x 3 y 4 z 5 w 6 w 7 x 8 x 9 y 10 a 11 z dtype: object
#重複するデータをまとめます。 ser3.unique() >>> array(['w', 'x', 'y', 'z', 'a'], dtype=object)
ser1.value_counts()(重複するデータの数を数える)
ser3.value_counts() #重複するデータの数がわかります >>> w 4 x 3 z 2 y 2 a 1 dtype: int64
今回は、Seriesの要素をindexの順や、要素小さい順に並び替えたり、その順位を見る方法について学びました。
お疲れ様でした!
次回は、こちら。
それじゃー、また。
pandas入門4_「データ同士の計算」
こんにちは、ワタルです。
さっと見て、「あぁそうだったそうだった」と確認できるハンドブックのような存在を目指して。
pandas入門第4回目、「データ同士の計算」です。
今回の学習内容
今回では、新しい関数について学ぶのではなく、SeriesやDataframe同士を足し算や引き算をした場合にどういった挙動をするのかについて学んでいきます。
おまじない
import numpy as np from pandas import Series,DataFrame import pandas as pd
Seriesをつくる
#Seriesを2つ、つくります #1つめ ser1 = Series([0,1,2],index=['A','B','C']) ser1 >>> A 0 B 1 C 2 dtype: int64
#2つめ ser2 = Series([3,4,5,6],index=['A','B','C','D']) ser2 >>> A 3 B 4 C 5 D 6 dtype: int64
Seriesの足し算
ser1 + ser2 #同じindexの要素が足し算されていることがわかります #片方にしかindexが存在しない場合には、NaNが自動的に追加されています >>> A 3 B 5 C 7 D NaN dtype: float64
DataFrameをつくる
dframe1 = DataFrame(np.arange(4).reshape(2,2),columns=list('AB'),index=['NYC','LA']) dframe1 >>> A B NYC 0 1 LA 2 3
dframe2 = DataFrame(np.arange(9).reshape(3,3),columns=list('ADC'),index=['NYC','SF','LA']) dframe2 >>> A D C NYC 0 1 2 SF 3 4 5 LA 6 7 8
DataFrameの足し算
dframe1 + dframe2 #片方にしかindexとcolumnsが存在しない場合には、NaNが自動的に追加されています >>> A B C D LA 8.0 NaN NaN NaN NYC 0.0 NaN NaN NaN SF NaN NaN NaN NaN
addメソッドによる足し算
#addに引数(fill_value=0)を使うと、NaNを置き換えられます。 dframe1.add(dframe2,fill_value=0) # SF-Bはどちらにも存在しないので、NaNになります。 >>> A B C D LA 8 3 8 7 NYC 0 1 2 1 SF 3 NaN 5 4
DataFrameとSeriesの計算
#Dataframeの確認 dframe2 >>> A D C NYC 0 1 2 SF 3 4 5 LA 6 7 8
dataframe.locとdataframe.iloc(Dataframeから、Seriesをつくる)
#locの時は、行ラベル名・ 列ラベル名で指定ができます。 #ilocの時は、行の番号(0 ~ )、列の番号(0 ~ )で指定ができます。 ser3 = dframe2.iloc[0]#dframe2のindex = 0(1行目)を指定しています ser3 >>> A 0 D 1 C 2 Name: NYC, dtype: int64
DataFrameとSeriesの引き算
dframe2-ser3 #ser3は1×3の配列であり、行ごとに引き算されているのがわかります。 >>> A D C NYC 0 0 0 SF 3 3 3 LA 6 6 6
今回は、DataframeやSeries同士の計算を学びました。
お疲れ様でした!
次回はこちら。
それじゃー、また。
pandas入門3_「indexのあれこれ」
こんにちは、ワタルです。
さっと見て、「あぁそうだったそうだった」と確認できるハンドブックのような存在を目指して。
pandas入門第3回目、「indexのあれこれ」です。
今回では、以下の関数を使えるようになることが目標です。
ser2 = ser1.reindex(['index1','index2','index3'])(indexを変える) #reindexの引数(fill_value=)(新しいindexの値を指定して埋める) #reindexの引数(method='ffill')(次の値が存在するまで、その値で埋める)
おまじない
import numpy as np from pandas import Series, DataFrame import pandas as pd from numpy.random import randn
ser2 = ser1.reindex(['index1','index2','index3'])(indexを変える)
#まずは、Seriesをつくります ser1 = Series([1,2,3,4],index=['A','B','C','D']) ser1 >>> A 1 B 2 C 3 D 4 dtype: int64
#reindexを使って、indexを変えます。 ser2 = ser1.reindex(['A','B','C','D','E','F']) ser2 >>> #要素が存在しない場所には、nullが入ります。 A 1 B 2 C 3 D 4 E NaN F NaN dtype: float64
reindexの引数(fill_value=)(新しいindexの値を指定して埋める)
#新しいindexの値を埋めることもできます。 ser2.reindex(['A','B','C','D','E','F','G'],fill_value=0) >>> #新しいindexのGに0が入ったことがわかります A 1 B 2 C 3 D 4 E NaN F NaN G 0 dtype: float64
reindexの引数(method='ffill')(次の値が存在するまで、その値で埋める)
#新しいSeriesをつくります ser3 = Series(['USA','Mexico','Canada'],index=[0,5,10]) ser3 >>> 0 USA 5 Mexico 10 Canada dtype: object
ser3.reindex(range(15),method='ffill')#ffillは、forward fillの略です。 >>> #次の値が存在するまで、その値が入力されていることがわかります 0 USA 1 USA 2 USA 3 USA 4 USA 5 Mexico 6 Mexico 7 Mexico 8 Mexico 9 Mexico 10 Canada 11 Canada 12 Canada 13 Canada 14 Canada dtype: object
DataframeのReindex
#まずは、5×5のDataFrameをつくります dframe = DataFrame(randn(25).reshape((5,5)),index=['A','B','D','E','F'],columns=['col1','col2','col3','col4','col5']) dframe >>>
col1 | col2 | col3 | col4 | col5 | |
---|---|---|---|---|---|
A | -0.833892 | 0.096806 | -0.546194 | 0.284642 | 0.938754 |
B | -0.040001 | -0.779153 | 1.248989 | -1.088699 | 0.087533 |
D | -0.767749 | 0.577453 | -1.241944 | 1.814318 | -0.374022 |
E | -1.579335 | -1.407157 | 2.671767 | -1.120105 | 1.161817 |
F | -1.458378 | 1.330623 | -1.773946 | 0.626151 | 1.362205 |
#新しいindexと新しいcolumnsのlistをつくります new_index = ['A','B','C','D','E','F'] new_columns = ['col1','col2','col3','col4','col5','col6'] #new_indexとnew_columnsを同時に追加します dframe.reindex(index = new_index,columns = new_columns) >>> #indexがC行の行と、columnsがcol6の列が追加されていることがわかります
col1 | col2 | col3 | col4 | col5 | col6 | |
---|---|---|---|---|---|---|
A | -0.833892 | 0.096806 | -0.546194 | 0.284642 | 0.938754 | NaN |
B | -0.040001 | -0.779153 | 1.248989 | -1.088699 | 0.087533 | NaN |
C | NaN | NaN | NaN | NaN | NaN | NaN |
D | -0.767749 | 0.577453 | -1.241944 | 1.814318 | -0.374022 | NaN |
E | -1.579335 | -1.407157 | 2.671767 | -1.120105 | 1.161817 | NaN |
F | -1.458378 | 1.330623 | -1.773946 | 0.626151 | 1.362205 | NaN |
今回では、SeriesやDataframeのindexやcolumnsを追加したり、変更したりする方法について学びました。 お疲れ様でした!
次回はこちら。
それじゃー、また。