背景
SGDにおける損失関数をいろいろなテスト関数で試したかったので実装しました。
勾配も必要だったので同様に実装しました。
Bohachevsky関数
非線形関数のBohachevsky関数について実装を行いたかったが意外と勾配も含めて実装されている文献がなかったので実装の備忘録を書きました。
入力の次元は2次元、関数値はこの通りですね。
$$ f(x) ={x_1}^2 + 2{x_2}^2 -0.3cos3 \pi x_1 – 0.4cos4 \pi x_2 + 0.7$$
とりあえず実装してみました.
def f_opt(self, w): w = np.array(w) w1, w2 = w[0], w[1] f = w1 ** 2 + 2 * w2 ** 2 - 0.3 * np.cos(3 * np.pi * w1) - 0.4 * np.cos(4 * np.pi * w2) + 0.7 return f
加えて勾配ですがこちらは二方向に求まります。
片方だけ式を書きますとこんな感じです。
$$ f(x) ={2x_1} + 0.9 \pi sin3 \pi $$
def g_opt(self, w): w = np.array(w) w1, w2 = w[0], w[1] g_w1 = 2 * w1 + 0.9 * np.pi * np.sin(3 * np.pi * w1) g_w2 = 4 * w2 + 1.6 * np.pi * np.sin(4 * np.pi * w2) g = np.array([g_w1, g_w2]) return g


RosenBrock関数
入力の次元がD次元の時、関数値はこの通りですね。
$$ f(x) = \sum_{i=1}^{D-1} [100{(x_{i+1} – {x_i}^2 )}^2 + {(x_i – 1)}^2 ] $$
とりあえず実装してみました。
加えて勾配ですがこちらは入力の次元分だけ出力値が出るはずです。
同じく入力がD次元あったとき微分する次元(\(x_d\))で関数が異なります。
1)d=0
2)d=D
3)それ以外
のときで場合わけできます。
1)のとき
$$ g(x) = -400(x_{i+1} – {x_i}^2 )x_i + 2(x_i – 1) $$
2)のとき
$$ g(x) = 200(x_{i+1} – {x_i}^2 )x_i $$
3)のとき
$$ g(x) = -400(x_{i+1} – {x_i}^2 )x_i + 2(x_i – 1) + 200(x_i+1 – {x_i}^2 )x_i $$
class RosenBrock(models.Model): def __init__(self, name="RosenBrock", noise_value=np.array([0,0]), var=1): super(RosenBrock, self).__init__(name=name) self.w_star = np.ones(2) self.noise_value = noise_value def f_opt(self, w): w = np.array(w) d = w.shape[0] self.w_star = np.ones(d) for i in range(0, d - 1): tmp_1 = 100 * (w[i + 1] - w[i] ** 2) ** 2 tmp_2 = (w[i] - 1) ** 2 tmp = tmp_1 + tmp_2 self.noise_value = self.add_noise(tmp) tmp = tmp + self.noise_value return tmp def g_opt(self, w): w = np.array(w) d = w.shape[0] self.w_star = np.ones(d) tmp = np.zeros(w.shape) for i in range(d): if i == 0: tmp[i] = 100 * (-4) * w[i] * (w[i + 1] - w[i] ** 2) + 2 * (w[i] - 1) elif i == d - 1: tmp[i] = 100 * 2 * (w[i] - w[i - 1] ** 2) else: tmp[i] = 100 * (-4) * w[i] * (w[i + 1] - w[i] ** 2) + 2 * (w[i] - 1) + 100 * 2 * (w[i] - w[i - 1] ** 2) tmp = tmp + self.noise_value return tmp
f = model_opt.RosenBrock() x = np.arange(-0.5, 1.5, 0.1) y = np.arange(-0.5, 1.5, 0.1) X, Y = np.meshgrid(x, y) Z = f.f_opt([X,Y]) fig = plt.figure() ax = Axes3D(fig) ax.set_xlabel("x") ax.set_ylabel("y") ax.set_zlabel("f(x, y)") ax.plot_surface(Y,X , Z) plt.show()


コメント