LoginSignup
0
1

More than 5 years have passed since last update.

返り値が複数ある関数に対してscipy.optimize.fminするとValueErrorが出るときの解決策

Last updated at Posted at 2018-04-23

若干ハマって解決法が出てこなかったのでメモ。

X,yともにデータ(m件)が入っていて、Xがm×nの行列、yがm次元のベクトルとします。例えばロジスティック回帰のコスト関数

import numpy as np
from scipy.optimize import fmin

def cost_function(theta, X, y):
    h_theta = 1 / (1 + np.exp(np.dot(-X, theta)))
    J = np.sum(-y * np.log(h_theta) - (1 - y) * np.log(1 - h_theta)) / len(y)
    grad = np.zeros(len(theta))
    for j in range(len(theta)):
        grad[j] = sum((h_theta - y) * X[:, j]) / len(y)
    return J, grad

でthetaを変化させて、Jを最小化したいような問題を解きたいとします。scipy.optimizeモジュールには組み込みの関数があります。

参考:Optimization (scipy.optimize)

fmin関数を使うとシンプレックス法で最小化問題を解くことができます。

参考:scipy.optimize.fmin

ダメな例

fmin(cost_function, initial_theta, args=(X, y, ))
出力
    print(fmin(cost_function, initial_theta, args=(X, y, )))
  File "C:\Program Files\Anaconda3\lib\site-packages\scipy\optimize\optimize.py"
, line 393, in fmin
    res = _minimize_neldermead(func, x0, args, callback=callback, **opts)
  File "C:\Program Files\Anaconda3\lib\site-packages\scipy\optimize\optimize.py"
, line 517, in _minimize_neldermead
    fsim[k] = func(sim[k])
ValueError: setting an array element with a sequence.

スタックトレースからはわかりづらいが、原因はどの返り値で最適化していいかわからないかららしい。

解決策

最適化に必要な1つの返り値のみを返す関数で1回ラップして、そのラップした関数を最適化します。

cost_wrap = lambda theta,X,y : cost_function(theta, X, y)[0]
fmin(cost_wrap, initial_theta, args=(X, y, ))

これで上手く行きました。

ちなみにargsの引数には、最適化で動かしても変化させない定数(例えばデータなど)を入れます。このargsを使えば目的関数の引数が複数の場合でも対応できます。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1