多項式回帰(polynomial regression)
重回帰分析の式と似ているが、よく見ると異なる。
以下が多項式回帰の式である。
y = b0 + b1*x1 + b2*x1^2 + .... + bn*x1^n
重回帰分析では、係数がb0、b1、、、、となるたびに独立変数も増えていったが、
多項式回帰では、その代わりに、power(指数)の数が増えていき、独立変数は1つだけである。
じゃあ多項式回帰を使うのはいつ??
上記のようなデータ分布の場合、線形単回帰でうまく予測できるが、以下のようなデータ分布の場合うまく予想できない。
そう言った場合に多項式回帰を使うと、指数の項が入っているため、うまく放物線を近侍できる。
実際は、線形単回帰や重回帰を使ってうまくいかなかった時、このようなデータになっていることがあり、その時に多項式回帰を使うとうまくいく。
例えば、病気がどのように広がり、パンデミックが領土全域にどのように広がっていくかを説明するために使われる。
ちなみに多項式回帰は線形かと言われるとそうである場合とそうでない場合がある。
線形非線形の理解はこちらのURLを見るとわかりやすい。
https://oshiete.goo.ne.jp/qa/2113039.html
結論を言うと多項式回帰になるのは、重回帰分析の特別なケースである。
つまり多項式回帰は新しいタイプの回帰ではなく、重回帰分析の1つのバージョンである。
ここで1つの疑問があるかもしれない。
回帰では独立変数同士が互いに高い相関があるとうまく分析できなかった。
多項式回帰の式をもう一度見てみると
y = b0 + b1*x1 + b2*x1^2 + .... + bn*x1^n
そもそも同じ独立変数を使っており、非常に高い相関があるのでは?と思う。
^^^^^^^^^^^^^^^^^^^^^^^^^^^
今回の予測
使うデータは以下のものである。
Position |
Level |
Salary |
Business Analyst |
1 |
45000 |
Junior Consultant |
2 |
50000 |
Senior Consultant |
3 |
60000 |
Manager |
4 |
80000 |
Country Manager |
5 |
110000 |
Region Manager |
6 |
150000 |
Partner |
7 |
200000 |
Senior Partner |
8 |
300000 |
C-level |
9 |
500000 |
CEO |
10 |
1000000 |
levelを使ってSalaryを予測する。
なので特徴行列にはlevelの列を、目的ベクトルにはSalaryの列を使う。
ここで注意したいのが、
X = dataset.iloc[:, 1].valuesと記述すると、python側がXをベクトルとして認識してしまうことだ。
そのため
X = dataset.iloc[:, 1:2].valuesこのように記述する。こうするとpythonはXを行列として認識してくれる。
また今回はトレーニングセットとデータセットに分割することはしない。と言うのも、データ数が少ないし、また正確性を高めたいから、少しでも多くのデータを使いたいからである。
そしてFeature Scalingも行わない。なぜなら独立変数が1つしかなく、スケールをおなじにする必要がないからである。
Linear Regression modelとPolynomial Regression modelを作る
なぜ2つのモデルを作るかと言うと、2つを比較させたいからである。
linear regressionの方は今までやってきた方法と同じである。
from sklearn.linear_model import LinearRegression
lin_reg = LinearRegression()
lin_reg.fit(X,y)
一方、polynomial regressionは新しいライブラリを使う。
from sklearn.preprocessing import PolynomialFeatures
poly_reg = PolynomialFeatures(degree = 2)
さて、ここでPolynomialFeaturesクラスについて見ていく。
- degree
多項式の次数。今回は二次の項まで考慮。
- interaction_only
Trueにすると交互作用項だけ出力します。交互作用項というのは、つまりX[:,0]*X[:,1]のようなものです。よくわからない笑
- include_bias
デフォルトではTrueで、バイアス項(=すべて1の列)を入れてくれます。sklearnの他のモデルで切片を推定してくれないものは少ないので、ほとんどのケースではFalseにしても差し支えないでしょう。
今回はデフォルトなのですべて1の列が最初に入る。
- order
出力の列の順番が変わります。普通は意識しなくてもいいでしょう。意識してない。
そしてpoly_regで作ったモデルにデータを入れて新しい特徴行列を作る。
X_poly = poly_reg.fit_transform(X)
fit_transformを使うかはこれがめっちゃわかりやすい!
https://qiita.com/makopo/items/35c103e2df2e282f839a
fitとfit_transformとtransformなどの違いがまとめられている。
X_polyの中身を見てみる。
1列目にすべて1の列が追加されており、2列目は元の X行列の1列目の値、3列目にはそれを二乗した値が入っている。
1列目はbackward eliminationで手動で追加したb0にかけられる項であり、polynomialfeaturesでは自動的に追加される。
そしてこの新しくできたX_polyをmultiple linear regressionモデルに適用させる必要がある。
そこで新しいモデルを作る。
lin_reg_2 = LinearRegression()
そしてデータをモデルに入れる。
lin_reg_2.fit(X_poly,y)
グラフで図示して比較してみる
まずはLinearRegressionで予測したものを図示する。
plt.scatter(X,y,color='red')
plt.plot(X,lin_reg.predict(X),color='blue')
plt.title('Truth or Bluff(Linear Regression)')
plt.xlabel('postion lebel')
plt.ylabel('salary')
plt.show()
赤い点が実際の観測点であり、青い線が予測した線である。直線なのはLinear Regressionモデルを使っているからである。
次にPolynomial regressionで予測したものだ。
plt.scatter(X, y, color = 'red')
plt.plot(X, lin_reg_2.predict(poly_reg.fit_transform(X)), color = 'blue')
ここでpredictの第一引数がX_polyではないのに注意したい。X_polyは既に定義されているので使わない。????
plt.title('Truth or Bluff (Polynomial Regression)')
plt.xlabel('Position level')
plt.ylabel('Salary')
plt.show()
きれいに放物線を描けいており、ここから、polynomial regressionモデルは線形回帰モデルでないことがわかる。
線形回帰モデルでは直線が得られ、非線形回帰モデルでは曲線であったり、非常に複雑な数学分布が得られる。
多項式回帰の式の項(degree)を増やしてみる
先ほどのpolynomial regressionモデルではdegree=2、つまりx^2の項まで考慮していた。
ではx^3の項まで考慮するとどうなるのか。
degree=3にしてもう一度図示してみる。
すると結果は、先ほどのモデルの精度より高くなっていることがわかる。
degree=4にしてみる。
ほとんど完璧な精度になった。
もう少し高度にしてみる
先ほどまでやっていたことは、1~10までの間に1つずつ直線を入れていった処理になっている。これを0.1ずつの間に直線を入れていけば、より精度が上がるし、より曲線に近くなる。
新たな行列X_gridを作る。
X_grid = np.arange(min(X),max(X),0.1)
X_grid = X_grid.reshape(len(X_grid),1)
そしてそのX_gridに対して予測を行う
plt.scatter(X, y, color = 'red')
plt.plot(X_grid, lin_reg_2.predict(poly_reg.fit_transform(X_grid)), color = 'blue')
plt.title('Truth or Bluff (Polynomial Regression)')
plt.xlabel('Position level')
plt.ylabel('Salary')
plt.show()
さっきまでは、滑らかな曲線ではなかったが、今回は滑らかな曲線になっている。
重回帰分析
単回帰分析はy = b0 + b1*xであり、求めたい係数はb0とb1だけであった。
また独立変数も1つだけである。
一方、重回帰分析はy = b0 + b1*x1 + b2*x2 + .... + bn*xn と求めたい係数も増え、また独立変数の数も二個以上である。
線形回帰で注意したいこと
以下の5つの仮定が成り立つ時にしか線形回帰ができない
・Linearity(線形性)
独立変数と従属変数の間に線形性がある
・homoscedasticity(等分散性)
独立変数と従属変数が同じ散らばり具合
・multivariate nomarity(多変量正規性)
多重線形回帰は、残差(従属変数yの観測値と予測値yˆの差が正規分布している。
・independence of errors(誤差の独立)
残差(従属変数yの観測値と予測値yˆの差は独立している。
・lack of multicollinearity(多重共線性の欠如)
独立変数間に強い相関があったり、一次従属な変数がある場合、解析が不可能であったり、たとえできたとしても信頼性が非常に低くなる。このような場合に多重共線性があるという。よって多重共線性がないことが大事。この仮定はVIFを使ってテストされる。
今回使うデータ
50社のスタートアップの資金投入や利益などのデータ(4社を抜き出している)
R&D Spend |
Administration |
Marketing Spend |
State |
Profit |
165349.2 |
136897.8 |
471784.1 |
New York |
192261.83 |
162597.7 |
151377.59 |
443898.53 |
California |
191792.06 |
153441.51 |
101145.55 |
407934.54 |
Florida |
191050.39 |
144372.41 |
118671.85 |
383199.62 |
New York |
182901.99 |
R&D Spend:研究と開発にどれだけの費用を費やしたか
Administration:管理費
Marketing Spend:宣伝費
State:企業の所在地
Profit:利益
今回の従属変数はProfitであり、それ以外は独立変数である。
するとyがProfit、b1がR&D Spend、b2がAdmin、B3がMarketingであることは容易に想像できる。
しかしStateはどうだろうか??これはカテゴリー変数である。
そのためdummy variableを追加する必要がある。
StateにはNew YorkとCaliforniaの2つの変数がある。そのため1つの変数がわかればもう1つの変数も自動的にわかる。
具体的に新たな列を追加して、New Yorkの列が1ならその行の会社はNew Yorkにあるということになる。
そしてNew Yorkの列が1の時D1が1であり、0の時(Californiaの時)はD1が0になる。
つまり、係数が0になる。
しかし、この時Caloforniaの要素はb0に含まれている。
それでは、2つ目のdummy variable D2を加えたらどうなるか??
これは変数を複製していることになる。
どういうことか??
D2 = 1-D1という式が成り立つからである。
D2(California)が1の時、当然D1は0になり、逆もまた成り立つ。
これは上記の仮定のmulticollinearity(多重共線性)にあたり、正常に動作しなくなる。
これをdummy variable trap(ダミー変数トラップ)とよぶ。
p-valueとは??
Backward Elimination(変数減少法)に入る前に、p-valueについて、その仕組みを基本的に理解する必要がある。
https://haru-reha.com/p-value-mean/
このブログがわかりやすい。
モデルの作成
単回帰分析では1つの独立変数と1つの従属変数であったので簡単だった。しかし重回帰分析はいくつもの独立変数がある。
なのでそれらの中からどれを使い、どれを捨てるか決める必要がある。
なぜか??
理由は主に2つある。
1つ目は「garbage in ,gatbage out」である。これはコンピュータサイエンスにおける概念で、無意味なデータを入れると無意味なデータが返されるという意味である。つまり、無意味に独立変数を増やしすぎても、返されるデータは必ずしも良くならないというわけである。
2つ目は、ある変数が従属変数の振る舞いを予測しても、それを上司や仲間などに説明する必要がある(働いてたらそういうシチュエーションになるよねって話かな)。もし変数が1000もあったら、それを説明するのは大変。
これらに気をつけてモデルを作成する。
モデルを作る方法は5つある
1 : All-in
2 : Backward Elimination
3 : Forward Selection
4 : Bidirectional Elimination
5 : Score Comparison
Stepwise Regression(ステップワイズ回帰)はこの中の2、3、4である。が4のBidirectional Eliminationだけをステップワイズ回帰という人もいる。
1All-in
これはテクニカルな話ではなく、基本的に全ての変数を投げ入れることをいう。
これを使う時は、事前に知識がある場合である。
もしこれらの正確な変数が真の予測因子のものと知っていれば、事実であると既に知っているものを構築する必要はない。
専門知識から知っているかもしれないし、誰かの前にこのモデルを構築したので知っているかもしれない。
そして使わなければいけない時(仕事の都合などで)
最後に変数減少法(Backward Elimination)を用いて、準備する時
Backward Eliminationとは??
ステップ1:
モデルにとどまるための重要レベル(Sginificant Level)を選択する必要がある。したがって、デフォルトでは5パーセント、つまりSL(重要レベル)=0.05を使用し、次のステップで使用する。
ステップ2:
すべての可能な予測因子で完全なモデルを適合させるため、先ほど説明したアプローチですべてを実行し、すべての変数をモデルに入れて、それらを削除し始める。
ステップ3:
最も高いP値を持つ予測変数を検討する。
p>SLの時、ステップ4に進み、それ以外の時はモデルの準備が完了したことを意味する。
ステップ4:
基本的に最高のpを持つ変数を削除するためにその予測因子を削除する
正直何を言っているかよくわからない。。。。。
が5つの方法の中で最も早く、また実践的なのがこれらしい。
pythonでモデルを作る
線形単回帰と全く同じである。
#Fitting Multiple Linear Regression to the Training set
from sklearn.linear_model import LinearRegression
regressor = LinearRegression()
regressor.fit(X_train,y_train)
#Predictiong the Testting set result
y_pred = regressor.predict(X_test)
実行結果
y_testの値は
103282
144259
146122
77798.8
191050
105008
81229.1
97483.6
110352
166188
y_predの値は
103015
132582
132448
71976.1
178537
116161
67851.7
98791.7
113969
167921
となり、しっかりと予測できていることがわかる。
とはいえ、なぜ線形単回帰と全く同じような実装で重回帰ができるか謎。、、
おそらく重回帰分析のやり方がLinearRegressionの中に入っていて、変数がたくさんある時は、重回帰分析になって1つの時は線形単回帰分析になるのではないかという予測。
まあ、中身で何をしているのかよくわかっていないけど。。
ここでしたやり方は全ての独立変数を使ったやり方であり、どの独立変数が予測の上で効果的かとか効果的でないのかとかは考えてない。
つまりAll-inのやり方だと思う。
backward eliminationを使って最適なモデルを作る
次はbackward eliminationを使って最適なモデルを作っていく。
最初にライブラリをインポートする
import statsmodels.formula.api as sm
次にbackward eliminationがちゃんと動くように少しトリックを加える必要がある。
具体的にいうと、特徴行列に1行加える必要がある。
なぜこれをする必要があるかは、重回帰分析の式を見るとわかりやすい。
y = b0 + b1*x1 + ..... + bn*xn
b0にx0がかかっていないが、実はx0が1だからである。よって本当の形は
y = b0*x0 + b1*x1 + .... + bn*xnとなる。
そして、今から使おうとしているstatsmodelライブラリはこのb0を考慮していない。
(ほとんどのライブラリ(例えばLinearRegression)ではb0は考慮されているのでx0を加える必要がない。)
だから、特徴行列に全ての要素が1のx0の列を加えてあげる必要がある。
こうすることで、statsmodelライブラリは重回帰分析の式を
y = b0 + b1*x1 + ..... + bn*xn
と認識することができる。
追加の仕方
np,appendを使う。
第一引数arrはarrの末尾に値を追加した配列を生成する。この時arr自体は変化しない。
第二引数valuesは追加したいもの。arrと同じ型にする。
第三引数axisは列に追加したいか行に追加したいか。0なら行に追加。1なら列に追加。
これでBackward eliminationをする準備が完了。
Backwardelimination
最初にすることは最終的に最適な特徴行列になる新しい行列を作ることだ。この行列には最終的に、従属変数の予測によくきく独立変数のみが入ることになる。
そして、backwardeliminationは最初に全ての独立変数を含み、そこから1つずつ重要でないものを消していく作業をする。
よって
X_opt = X[:,[0,1,2,3,4]]というふうに書く。
最初のステップ1は、モデルにとどまる有意水準(SL)を選択することです。
つまり、独立変数のp値が有意水準を下回る場合、独立変数がモデル内に留まるように、有意水準を選択する必要があります。ただし、独立変数のp値が有意水準のバーである場合、それはモデル内に留まらず、削除します。
単純にステップ1がすることはSLを選択すること。そしてその選択は0.05、つまり5%とする。
ステップ2ではFit the full model with all possible predictorsを行う。
このall possible preditorsにあたるのが上で作ったX_optである。そしてFitはまだできていなかったので、新しいライブラリを使って行う。
import statsmodels.api as sm
このライブラリを使って重回帰モデルを機能XとYの将来の最適な行列に修正する。実際にフィットさせるにはyが必要になるからです。
regressor_OLS = sm.OLS(endog=y,exog=X_opt).fit()
このOLSはoridinary least squares (普通の最小二乗法)の略である。
第一引数endogには従属変数を入れる。
第二引数exogには観測の数とリグレッサーの数を持った配列を入れる。つまりX_opt。
ステップ3では最も高いp値を持つ独立変数を探す。そしてもしそのp値がSLの5%を超えていたらステップ4に進み、もし下回っていたらモデルの準備は完成ということになる。
そして高いp値を探すにはsummary関数を使う必要がある。これは、モデルを作るときに、重要となる全ての統計行列を含む優れたテーブルを返してくれます。そして、そのテーブルにはそれぞれの独立変数に対応するp値が含まれており、それをSLと比較することで、どれをモデルから削除するか決めれる。
regressor_OLS.summary()
出力
それぞれの独立変数に対してのp値が見れる。constはb0を表す。
重要なのはp値が低いほど、独立変数が従属変数に対してより重要であるということだ。
次にステップ4。独立変数の削除だ。
表を見て最も高いp値はx2の0.990である。これはSLの0.05を超えているため、この独立変数をモデルから削除する。インデックス番号で言うと、X_optの2番目の列にあたる。
X_opt = X[:,[0,1,3,4,5]]
これで二番目の列を削除した新たなX_optを作成
ステップ5
そして後は同じ手順でモデルを適用させテーブルを出す。そしてステップ3に戻る。
regressor_OLS = sm.OLS(endog=y,exog=X_opt).fit()
regressor_OLS.summary()
そして今度は新たなX_optのインデックス番号1番目の列が最もp値が高いのでこれを削除する。
60%なのでまた5%を超えているのでこの作業を続ける。
x1はR&D Spendだがこれは0.000となっていてprofitを予測するのに非常に強い独立変数であることがわかる。またp値は0になることはないので、これは0に非常に近いと言うことである。
x2は0.05よりわずかに大きい。SLを10%などと違う値を設定することでこの独立変数を維持することはできるが今回はこのルールに従う。
よって今回の最適な独立変数の組み合わせはR&D Spend1つのみと言う結果になった。
時間と共に指数関数的に増える従属関数を予測する時は、重回帰分析は向かない。
線形単回帰
線形単回帰とは、y = b0 + b1*xという式で表され、xからyを予測できるようなそれっぽい直線(つまり切片b0と傾きb1)を求めるものである。
ここで、yは従属変数(dependent variable)であり、xは独立変数(independent variable)である。
そしてこのようなデータを使うことを考える。
YearsExperience |
Salary |
1.1 |
39343.00 |
1.3 |
46205.00 |
1.5 |
37731.00 |
2.0 |
43525.00 |
2.2 |
39891.00 |
2.9 |
56642.00 |
3.0 |
60150.00 |
3.2 |
54445.00 |
3.2 |
64445.00 |
3.7 |
57189.00 |
3.9 |
63218.00 |
4.0 |
55794.00 |
4.0 |
56957.00 |
4.1 |
57081.00 |
4.5 |
61111.00 |
4.9 |
67938.00 |
5.1 |
66029.00 |
5.3 |
83088.00 |
5.9 |
81363.00 |
6.0 |
93940.00 |
6.8 |
91738.00 |
7.1 |
98273.00 |
7.9 |
101302.00 |
8.2 |
113812.00 |
8.7 |
109431.00 |
9.0 |
105582.00 |
9.5 |
116969.00 |
9.6 |
112635.00 |
10.3 |
122391.00 |
10.5 |
121872.00 |
YearsExperienceが勤続年数であり、Salaryが給与である。
x成分が勤続年数でy成分が給与とする。
そして特徴行列Xは勤続年数、目的行列yは給与とする。
今回の特徴行列の中にある特徴量は勤続年数1つだけなのでFeature Scalingは必要ない。前回のデータの前処理で使ったような特徴量がいくつかある時で、スケールを同じにしたい時に使う。
最小二乗法を使う
それっぽい直線を求めるにはどうすれば良いか。
答えは最小二乗法を用いることにある。
それっぽい直線を最初に引き、あるxの値のところの、予測値yハットと実際の値yを比べる。
比べる時に、(y-yハット)^2の値を用いる。これが二乗誤差である。これは一辺の長さがy-yハットの正方形の面積を求めていることと同じ意味である。そして、この面積(値)が小さければ小さいほど、予測値と実際の値の差が小さいことになる。
そして、この計算をそれぞれのxの値に対して行い、得た二乗誤差を足す。
これをそれっぽい直線を何本かひき、それぞれの二乗誤差を求め、最二乗誤差が最小になる直線を選ぶ。
その直線が答えである。
線形単回帰モデルの作成
from sklearn.linear_model import LinearRegression
regressor = LinearRegression
regressor.fit(X_train,y_train)
linear_modelのfitは何をしているか??
第一引数のX_train、第二引数のy_trainから値を抽出し、上述の手法で線形単回帰の方程式y=b0+b1*xの係数b0とb1を計算している。
データの予測
作成したモデルを用いてデータを予測する。
y_pred = regressor.predict(X_test)
ここでy_predは予測した給料の値であり、y_testは実際の給料の値である。
y_test
37731
122391
57081
63218
116969
109431
112635
55794
83088
101302
y_pred
40835.1
123079
65134.6
63265.4
115603
108126
116537
64200
76349.7
100649
大体似たような値になっていることがわかる。
図にプロットしてみてみる
plt.scatter(X_train,y_train,color='red')
plt.plot(X_train,regressor.predict(X_train),color='blue')
plt.title('Salary vs Experience (Training set)')
plt.xlabel('Years of Experiece')
plt.ylabel('Salaries')
plt.show()
赤の点が実際の値である。
青い線が勤務年数を与えた時に、線形単回帰モデルを用いて予測した給料の値である。
次にテストセットは以下のようになる。
plt.scatter(X_test,y_test,color='red')
plt.plot(X_test,regressor.predict(X_test),color='blue')
plt.title('Salary vs Experience (Testing set)')
plt.xlabel('Years of Experiece')
plt.ylabel('Salaries')
plt.show()
赤い点が実際の値で、青い線は勤務年数を与えた時に、線形単回帰モデルで予測した給料の値である。
非常に高い精度で予測できていることがわかる。
Feature Scalingの話
Feature scalingと何か??
特徴量の取りうる値の範囲(スケール)を変えることである。
これが必要な理由は何か。
例えば、特徴量に年齢と給料があるとする。
年齢は大体30才とか40才とかの範囲にあるが、給料は40万であったり、60万であったりと、年齢と給料の間に大きなスケールの違いがある。
このように各特徴量間で、スケールに大きな違いがあるデータで機械学習をするとうまく学習できないという問題がある。
具体的にいうと、多くの機械学習のモデルではユークリッド距離というものがベースになっている。
ユークリッド距離というのは2点間の距離であり、例えば点a(x,y)と点bが(j,k)があったとして、sqrt((x-j)^2+(y-k)^2)である。
例えばx座標が年齢でy座標が給料とする。そして年齢が20才で給料が20万のAさんのデータと、年齢が40才で給料が50万のBさんのデータでユークリッド距離をとることを考える。
給料:(50-20)^2 = 900万
年齢:(40-20)^2 = 400
となり、この2つのデータ間のユークリッド距離というのは年齢の寄与が全くなく、ほとんど給料の差のみで決まると言える。これだと機械学習はうまくできない。
これを解消するために、年齢と給料のレンジを同じくらいにして、寄与度もおなじくらいにしてあげる必要がある。
Feature Scalingのやり方
正規化(Standardization)と標準化(Normalization)がある。
pythonでこれを行うにはライブラリーから以下のようにimportする必要がある。
from sklearn.preprocessing import StandardScaler
sc_X = StandardScaler()
X_train = sc_X.fit_transform(X_train)
X_test = sc_X.transform(X_test)
なぜX_trainはfit_transformでX_testはtransformなのか??
''fit''の部分はパラメータ(平均や標準偏差)を計算している。''transform''の部分はデータをスケーリングしている。
X_testでfitを使わないのは、X_trainと同じパラメータを使いたいからである。つまりX_testでfitを使うとX_trainで使ったパラメータと違う値になるからである。
dummy variablesにFeature Scalingを適用すべきか
モデルの予測の正確さを最適化させたい時は適用すべき
モデルで可能な限り多くの解釈を維持したい時は適用すべきでない
Standardization(正規化)とNormalization(標準化)の使い分け
一般的に、データが正規分布している時は標準化を使い、そうでない時は正規化を使う。よくわからない時は正規化を使う。
しかし、一般的なのは2つのスケーリング方法をテストすることである。
train_test_splitでトレーニングセットとテストセットに分ける
機械学習をする上で用いるデータをトレーニングセットとテストセットに分割する必要がある。
トレーニングセットで機械学習のモデルを構築し、dependent varialesとindependent variablesの関係を学習し、テストセットでその性能を図る。
なぜトレーニングセットとテストセットを分割する必要があるのか??
例えばトレーニングセットを試験勉強するために使っていた教材、テストセットを試験問題だとしよう。
もしトレーニングセットとテストセットで同じデータを使っていたら、当然試験問題そのものを勉強しているわけなので余程勉強不足かへマをしなければ試験では100点を取れるだろう。
機械学習もこれと同じである。ましてやコンピュータなので余計100点がとりやすい。
今回はそれを防ぐために、データをトレーニングセットとデータセットに分ける方法を学んでいく。
データの分け方
from sklearn.model_selection import train_test_split
X_train,X_test,y_train,y_test = train_test_split(X,y,test_size=0.2,random_state=0)
train_test_split
第一引数:特徴行列
第二引数:目的行列
test_size:テスト用のデータを何割にするか(一般的に0.2~0.3くらい)
random_state:分割の乱数のシード値
データの前処理(preproceccing)
機械学習ではデータの前処理が大事になってくる。
例えば、以下のようなデータを考える
Country |
Age |
Salary |
Purchased |
France |
44 |
72000 |
No |
Spain |
27 |
48000 |
Yes |
Germany |
30 |
54000 |
No |
Spain |
38 |
61000 |
No |
Germany |
40 |
|
Yes |
France |
35 |
58000 |
Yes |
Spain |
|
52000 |
No |
France |
48 |
79000 |
Yes |
Germany |
50 |
83000 |
No |
France |
37 |
67000 |
Yes |
1列目は国、2列目は年齢、3列目は給料、4列目は購入したかどうかのデータが入っている。
機械学習で大事なことは、上記のようなデータセットが与えられた時、特徴行列と変数ベクトルに区別することである。
上記の例で考えると、予測したいものは購入したかどうかなので、特徴行列は1〜3行目から10列目の行列、変数ベクトルは4行目から10列目のものである。
そして区別するためのデータセットをpandasによって作っていく。
dataset = pd.read_csv('Data.csv') これで上記のcsvファイルを読み込む
X = dataset.iloc[:,:-1].values これが特徴行列になる
[]の左側が行をしている所で、右側が列を指定している所である。今回の場合、行は全ての行が欲しいので何も選択せず、列は1番右の列以外のものを選択している。
y = dataset.iloc[:,3].values これが変数ベクトルになる。
1番右の列の全ての行のデータが欲しいのでこのような記述になる。
欠損の処理
データを見ると所々抜けがあることがわかる。こういったデータを機械学習に使うにはデータを削除するか、抜けを埋めてあげる必要がある。
大切なデータを削除するのは危険なので普通はデータを埋める方式を使う。
scikitlearnのpreproceccingからImputerクラスを使う。
具体的な使い方
from sklearn.preprocessing import Imputer
#NaNの部分をaxis=0(列)の平均値(strategy="mean")で埋める
imputer = Imputer(missing_values="NaN",strategy="mean",axis=0)
imputer = imputer.fit(X[:,1:3])
X[:,1:3] = imputer.transform(X[:,1:3])
fitとtransformの違いは??
fitは適用したいオブジェクトから指定した情報を引き抜く(上の例の場合、欠損値と列の平均値)
一方、transformはその変換を適用する時に使う
categorical variableとは?
上のデータの例だとCountryとPurchasedである。国はFrance、Spain、Germanyの3つに分かれており、PurchasedはYesとNoに分かれている。
機械学習では数式が用いられるため、このようなtextの形だと問題がある。
なのでそれらをtextからnumberにencodeする必要がある。
エンコードの仕方
sklearn.preprocessingのLabelEncoderクラスを使う。
from sklearn.preprocessing import LabelEncoder
labelencoder_X = LabelEncoder()
X[:,0] = labelencoder_X.fit_transform(X[:,0])
Xの中身
[0, 44.0, 72000.0],
[2, 27.0, 48000.0],
[1, 30.0, 54000.0],
[2, 38.0, 61000.0],
[1, 40.0, 63777.77777777778],
[0, 35.0, 58000.0],
[2, 38.77777777777778, 52000.0],
[0, 48.0, 79000.0],
[1, 50.0, 83000.0],
[0, 37.0, 67000.0]]
問題点
無事に国名が0~2にエンコードされたが、この問題点はなんだろうか。
機械学習をする上で、このような数字に変換してしまうと、SpainはFranceとGermanyより大きく、またGermanyはFranceより大きく、Franceは1番小さいという意味がない分類分けが影響を与えてしまう可能性がある。
それを解決するためにOneHotEncoderを使う。
OneHotEncoderの使い方
from sklearn.preprocessing import OneHotEncoder
onehotencoder = OneHotEncoder(categorical_features = [0]) #引数はどの列に対して
X = onehotencoder.fit_transform(X).toarray()
0~2の列がそれぞれ変換された国名に対応しており、1だったらその国名に該当することを意味する。例えば0行目0列目は1で0行目1列目0行目2列目は0なので0行目のデータはFranceのデータである。
このようにすることで国名によって数字の大きさが変わることがなくなるので、それが機械学習に反映されなくなり、良い。
fit_transformの働きは??
LabelEncoderクラスから呼ばれるfit_transformはcategorical strings(categorical varibales)をintegers(整数)に変換する。Franceは0に、Germanyは1に、Spainは2になる。
OneHotEncoderクラスから呼ばれるfit_transformはラベルによって0か1に分けられた列を作る。分けられた列はdummy variablesと言われる。
Spyderの使い方
Spyderは、Anacondaで作成した仮想環境の中で
Pythonのスプリクトファイルを作成し、
実行するための機能である
筆者の使っているOSはmacなのでwindowsだと若干違うかも。
実際の使い方
Viewのpanes
Viewタグのpanesから好きなものを画面上に追加できる。例えば、Editor(プログラムを書くもの)やIPythonconsoler(プログラムを実行するもの)やVariable explor(変数の値を保存してくれるもの)、Help(ヘルプ)など
レイアウトの変え方
pythonタブからpreferencesを選ぶ。
そこからエディタの背景色だったり、文字の大きさなど様々な設定が可能。
pythonファイルの読み込み方
左上にあるフォルダのマークのところをクリックして、読み込みたいファイルを選択し開くをおす。
Help
クラスなどの使い方を見ることができる。エディタで調べたいクラスを選択して、Ctr+IかCommand+Iで調べられる。