俺人〜OREGIN〜俺、バカだから人工知能に代わりに頑張ってもらうまでのお話

俺って、おバカさんなので、とっても優秀な人工知能を作って代わりに頑張ってもらうことにしました。世界の端っこでおバカな俺が夢の達成に向けてチマチマ頑張る、そんな小さなお話です。現在はG検定、E資格に合格し、KaggleやProbSpaceのコンペに参画しながら、Pythonや機械学習、統計学、Dockerなどの勉強中です。学習したことをブログにアウトプットすることで、自分の身に着けていきたいと思います。まだまだ道半ばですが、お時間がありましたら見て行ってください。

ep4-3:多項式の次数を上げて近似する。( 「実践 機械学習システム」に学ぶ。)

オライリージャパン社の「実践 機械学習システム」に取り組んでいます。

今回は、多項式の次数を上げて近似します。

前回の直線で近似した記事は以下の通りです。

oregin-ai.hatenablog.com

では、順に取り組んでいきます。

 1.まずは、2次の多項式曲線(二次曲線)で近似します。

#次数が2の多項式曲線(二次曲線)で近似してみる。
fp2 = sp.polyfit(x,y,2)
print("Model parameters: %s" % fp2)

Model parameters: [ 1.04553117e-02 -5.21750402e+00 1.97446557e+03]

 

これで求められたモデルの関数は以下になります。
f(x)= 0.0104553117  x**2 -521.750402 x + 1.97446557 

2.モデルパラメータ(fp2)からモデル関数をを作る。

#求めたパラメータから、2次の多項式曲線モデル関数を作る。
f2 = sp.poly1d(fp2)
#誤差を求める。
print(error(f2,x,y))
180977929.6253154

poly1d()関数に、モデルパラメータ fp2 を渡すことで、モデル関数f2を定義します。

前回、直線で近似したときよりも、誤差が小さくなっています。

 3.モデルの二次曲線を散布図上に描画する。

#実測値の散布図を描画してみる。
plt.scatter(x,y) plt.title("Web traffic over the last month") plt.xlabel("Time") plt.ylabel("Hits/hour") plt.xticks([w*7*24 for w in range(10)],['week %i'%w for w in range(10)]) plt.autoscale(tight=True) plt.grid() #f1()を使って、訓練データから学習したモデルを描画してみる。 fx = sp.linspace(0,x[-1],1000) #プロット用に"x値"を生成 plt.plot(fx,f1(fx),linewidth=4,c='red') plt.legend(["d=%i" % f1.order], loc="upper left") #f2()を使って、訓練データから学習したモデルを描画してみる。 plt.plot(fx,f2(fx),linestyle="--",linewidth=4,c='orange') plt.legend(["d=%i" % f2.order], loc="upper left") plt.show()

f:id:kanriyou_h004:20190630183402p:plain


 

直線に比べると、ずいぶん実測値に近くなっています。視覚的にも誤差が小さくなっていることが分かります。

4.モデルパラメータ(fp2)からモデル関数をを作る。

#さらに次元を上げた多項式曲線モデル関数を作る。
#モデルパラメータを直接、poly1d()関数の引数として渡します。
f3 = sp.poly1d(sp.polyfit(x, y, 3))
f10 = sp.poly1d(sp.polyfit(x, y, 10))
f100 = sp.poly1d(sp.polyfit(x, y, 100))

3次、10次、100次の多項式曲線のモデル関数を作ります。

 3.各モデルの多項式曲線を散布図上に描画する。

#実測値の散布図を描画してみる。

#色と線の種類を指定
colors = ['g', 'k', 'b', 'm', 'r']
linestyles = ['-', '-.', '--', '-', '-']

#描画する関数を定義
def
plot_models(x, y, models, mx=None, ymax=None, xmin=None): plt.figure(figsize=(10, 5)) plt.clf() plt.scatter(x, y, c='orange', s=10) plt.title("Web traffic over the last month") plt.xlabel("Time") plt.ylabel("Hits/hour") plt.xticks( [w * 7 * 24 for w in range(10)], ['week %i' % w for w in range(10)]) if models: if mx is None: mx = sp.linspace(0, x[-1], 1000) for model, style, color in zip(models, linestyles, colors): plt.plot(mx, model(mx), linestyle=style, linewidth=2, c=color) plt.legend(["d=%i" % m.order for m in models], loc="upper left") plt.autoscale(tight=True) plt.ylim(ymin=0) if ymax: plt.ylim(ymax=ymax) if xmin: plt.xlim(xmin=xmin) plt.grid(True, linestyle='-', color='0.75') plt.show

#関数を呼びだして、各モデルの多項式曲線を描画
plot_models
(x, y, [f1, f2, f3, f10, f100])

f:id:kanriyou_h004:20190630184226p:plain

#誤差を求める。
print(error(f1,x,y))
print(error(f2,x,y))
print(error(f3,x,y))
print(error(f10,x,y))
print(error(f100,x,y))
318104548.81995213
180977929.62531537
138753471.74146083
121925460.47154611
110042465.176679 

多項式の次元を上げていく(複雑化する)と、誤差が小さくなって、良いモデルになっているような気がします。

しかしながら、描画した曲線を見ると、次数が100の曲線は、ジグザグに振動しているように見え、実績値にはあっているかもしれませんが、突発的な値等にも適応してしまっているようにも見えます。

今回は、多項式の次数を上げて、複雑に近似するモデルを作成しました。

複雑なモデルになればなるほど、実績値に対する誤差は小さくなってきました。

しかしながら、次数を上げすぎると、実績値に合わせすぎて、今後の予測には使いにくいモデルになってしまいました。

いわゆる「過学習(overfitting)」の状態です。

次数をあげれば上げるほど良いというわけではなさそうです。

次回からは、別の視点からも考察していきたいと思います。 

 2019年3月9日(土)にG検定を受験し、見事合格できました!

受験の体験記や勉強法などを別のブログにまとめました。

これから受験される方がいらっしゃいましたらご参考まで。

g-kentei.hatenablog.com