前回の線形fittingでは、身長が低いところでfittingのずれが大きくなっていましたので、今回は2次関数でfittingすることにします。
同時に、入力データやパラメータをmatrixで扱うことでコードをシンプルにしています。
前回との差分は、fitting関数を
y = theta0 + theta1 * x + theta2 * x^2
に変更したことです。
具体的なコードは以下のようになります。
matrixを使ったことでコードがシンプルになりました。
############### # 多項式回帰の実装 ############### import numpy as np import matplotlib.pyplot as plt ### (1) データ読み込み ### trainData = np.loadtxt('kodomoShinchouTaijyu.txt', delimiter=',', skiprows=0) trainDataX = trainData[:, 0] trainDataY = trainData[:, 1] #plt.plot(trainDataX, trainDataY, 'o') #plt.show() ### (2) データの標準化 mu = trainDataX.mean() # 平均 sigma = trainDataX.std() # 標準偏差 def standaradize(x): return (x - mu)/sigma trainDataXSTD = standaradize(trainDataX) # fitting 関数を2次関数にする # y = theta0 + theta1 * x + theta2 * x^2 # 学習データをマトリクスとしてまとめる # 2次関数でfittingするので2次まで def toMatrix(x): return np.vstack([np.ones(x.shape[0]), x, x**2]).T X = toMatrix(trainDataXSTD) #print(X) # パラメータの初期値 theta = np.random.rand(3) ### 線形fitting ### # fitting関数 (線形回帰) def f(x): return np.dot(x, theta) # MSE関数(最小2乗の損失関数) def E(x, y): return 0.5 * np.sum( (y - f(x)) ** 2) ### 学習 ### ncount = 0 # 更新回数 eta = 1e-2 #学習率 diff = 1 # 誤差 # 学習する error = E(X, trainDataY) while diff > 1e-3: # 損失関数の変化が小さくなるまでループする # 勾配降下法の実行 theta = theta - eta * np.dot(f(X) - trainDataY, X)[f:id:wshinya:20180325151001p:plain] # 1つ前のステップの誤差との差分 currentError = E(X, trainDataY) diff = error - currentError error = currentError # 途中経過を出力 ncount += 1 #log = '{}: t0 = {:.3f} t1 = {:.3f}, diff={:.4f}' #print(log.format(ncount, t0, t1, diff) ) ### 結果をグラフにする x = np.linspace(-2, 2, 100) plt.plot(trainDataXSTD, trainDataY, 'o') plt.plot(x, f(toMatrix(x))) plt.show()
実行結果は以下のようなグラフになりました。直線で近似した時よりもxが小さいところでよくfitしていることがわかります。