前提
講義で、以下の問題が課題になっているのですが、極めて初歩的なプログラミングしか知らず...
必須単位なので、何とか問題を解きたいのですが...
基本中の基本をお伺いしている部分も多いかと存じますが、考え方のヒントでも構いませんので、どなたか御指南下さいますでしょうか...
なお、今回、初めてこちらに投稿させて頂いておりますため、ルールなど、不束なことも多いかと存じます。
ご指導、ご寛恕いただけましたら幸いです。
よろしくお願いいたします。
===================================--
問題文
(i), (ii) の 2 変数関数の(無制約)最小化問題に対し,関数が凸であるか否かを解析的に判定し,バックトラッキング法を用いた最急降下法とニュートン法を適用した場合の解の挙動を以下の観点から調べて説明せよ
(Python等での実装、もしくはExcelでのグラフor表での表記をすること)
また,収束しそうな点がそのようになることや収束速度については予想されるものかどうかも理由付きで答えよ(数式はいくらでも用いて良い)。
• 大域的最適解に収束しそうか? 大域的最適解ではないが,局所的最適解に収束しそうか? 局所的最適解ですらない解に収束しそうか?
• どちらの手法が速く収束しそうか?
解答には,バックトラッキング法で利用した種々のパラメータを記載せよ.なお,対称行列A ∈ Rn×n (注:「n×n」はRの指数)が半正定値であることは,A ∈ Rn×n(注:「n×n」はRの指数) の全ての主小行列式が非負であることと同値である。
(i) f(x, y) = x^2 + y^2 + exp(−x^2 − y^2)。初期点は,(−1, −1)⊤ と (2, −1)⊤ の 2 種類を試してみよ。
(ii) f(x, y) = 2x^2 − 1.05x^4 +(x^6)/6 + xy + y^2。初期点は,(−1, −1)⊤ と,(2, −1)⊤ の 2 種類を試してみよ。
実現したいこと
・(i), (ii) の 2 変数関数の(無制約)最小化問題の関数が凸であるか否かを解析的に判定
・バックトラッキング法を用いた最急降下法とニュートン法を適用した場合の解の挙動をPythonで実装
発生している問題・エラーメッセージ
ニュートン法での方の実装を進めているのですが、(私の認識できている限りでは)以下の点について問題が起きてしまっています。
①特定の値についての勾配ベクトルしか求めることが出来ず、xとyを用いた一般的な式が求められない
②ヘッセ行列を求めるプログラミングが作成できない(申し訳ありません、知識的に手計算ではヘッセ行列が求められず、Pythonで計算しようとしたのですが、それもできなかった形です)
エラーメッセージ
### 該当のソースコード 使用言語はPythonを考えております。以下が、現時点でのコードの全文です。
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
#関数の図示
N = 41 #N=41の意味は理解できていません...
x1 = np.linspace(-2, 2, N)
x2 = np.linspace(-2, 2, N)
X1, X2 = np.meshgrid(x1, x2)
Y = X1 ** 2 + X2 ** 2 + np.exp(- X1 ** 2 - X2 ** 2)
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
surf = ax.plot_surface(X1, X2, Y, cmap='bwr', linewidth=0)
fig.colorbar(surf)
ax.set_xlabel("x1")
ax.set_ylabel("x2")
fig.show()
#極小値は(0,0)
#勾配ベクトルの計算、ヘッセ行列の求め方は分からず...
import numpy as np
def numerical_gradient(f,x):
h = 1e-4
grad = np.zeros_like(x)
for idx in range(x.size): tmp_val = x[idx] # f(x+h)の計算 x[idx] = tmp_val + h fxh1 = f(x) #f(x-h)の計算 x[idx] = tmp_val - h fxh2 = f(x) grad[idx] = (fxh1 - fxh2) / (2*h) x[idx] = tmp_val # 値を元に戻す return grad
def func_2(x):
return x[0] ** 2 + x[1] ** 2 + np.exp(- x[0] ** 2 - x[1] ** 2)
numerical_gradient(func_2,np.array([0.0,0.0])) #ここで、特定の値についての勾配ベクトルしか求めることが出来ず、xとyを用いた一般的な式が求められません
def f(x0, x1):
#y = 勾配ベクトル
dydx = np.array([4x0**3 + 2x0 + x1,
x0 + 2x1 + 8x1**3])
#H = np.array([ヘッセ行列])
return y, dydx, H
#ニュートン法を用いた関数の最小化、初期値(-1,-1)
x0, x1 = -1, -1
print("i x1 x2 f(x)")
for i in range(10):
y, dydx, H = f(x0, x1)
print(f"{i:3d} [{x0:10.3e}, {x1:10.3e}], {y:10.3e}")
d = - np.dot(np.linalg.inv(H), dydx)
x0 += d[0]
x1 += d[1]
### 試したこと ネット上の再急降下法やニュートン法を実装したコードを、一部書き換えさせていただいて実装しようとしています 現時点で主に参考にさせて頂いているのは ・ニュートン法について:https://helve-blog.com/posts/math/newtons-method-python/ ・勾配ベクトルの求め方について:https://www.f.waseda.jp/yusukekondo/TALLFALL19/TALLFALL0302.html のサイトです。 基本的に、コードをコピーさせて頂いて、xやyの部分を適宜変更しているため、変数名が一定でなかったりしているかもしれません... ### 補足情報(FW/ツールのバージョンなど) ここにより詳細な情報を記載してください。 Yahoo 知恵袋さんに既に投稿させて頂いていたのですが、プログラミングを含むため、より専門的なこちらにお伺いさせていただけないかとマルチポストさせていただきました... https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q12271242377
