複数の入力変数(24と30の間)を持つターゲット関数を最適化しようとしています。これらの変数は、3つの異なる統計変数のサンプルであり、目標関数値はt検定確率値である。誤差関数は、所望のt検定確率と実際のt検定確率との誤差(差の二乗の和)を表す。私は、3つのt検定のすべてについて、誤差が1e-8未満の解のみを受け入れることができます。scipyで離散変数値を持つ関数を最小化する方法
私はscipy.optimize.fmin
を使用していました。ターゲット関数がゼロになった解決策はたくさんあります。
問題は、変数が0から10.0の間であり、整数であるか、2桁以上の小数部を持たない解を見つける必要があるということです。有効な値の例は0 10 3 5.5 6.8
です。無効な値の例:-3 2.23 30
または0.16666667
私は目標値が実際の測定データから来ているので、少なくとも1つの解決策があることを知りました。元のデータは失われていて、私の仕事はそれらを見つけることです。しかし、私はどのように知りません。試行錯誤の使用は選択肢ではありません。なぜなら各変数に約100の可能な値があり、変数の数が与えられれば、100 ** 30の数が多すぎます。 fminの使用は素晴らしいですが、慎重な値では機能しません。
これを解決する方法はありますか?解決策を見つけるために何時間もプログラムを実行する必要があるなら、問題はありません。しかし、私は数日以内に約10の目標値の解決策を見つける必要があり、私は新しいアイデアがありません。ここで
は、例えばMWEです: 整数計画と呼ばれ、それがNP困難であるされて何が(私はあなたのセットアップを理解している場合)を実行しようとしているimport math
import numpy
import scipy.optimize
import scipy.stats
import sys
def log(s):
sys.stdout.write(str(s))
sys.stdout.flush()
# List of target T values: TAB, TCA, TCB
TARGETS = numpy.array([
[0.05456834, 0.01510358, 0.15223353 ], # task 1 to solve
[0.15891875, 0.0083665, 0.00040262 ], # task 2 to solve
])
MAX_ERR = 1e-10 # Maximum error in T values
NMIN,NMAX = 8,10 # Number of samples for T probes. Inclusive.
def fsq(x, t, n):
"""Returns the differences between the target and the actual values."""
a,b,c = x[0:n],x[n:2*n],x[2*n:3*n]
results = numpy.array([
scipy.stats.ttest_rel(a,b)[1], # ab
scipy.stats.ttest_rel(c,a)[1], # ca
scipy.stats.ttest_rel(c,b)[1] # cb
])
# Sum of squares of diffs
return (results - t)
def f(x, t, n):
"""This is the target function that needs to be minimized."""
return (fsq(x,t,n)**2).sum()
def main():
for tidx,t in enumerate(TARGETS):
print "============================================="
print "Target %d/%d"%(tidx+1,len(TARGETS))
for n in range(NMIN,NMAX+1):
log(" => n=%s "%n)
successful = False
tries = 0
factor = 0.1
while not successful:
x0 = numpy.random.random(3*n) * factor
x = scipy.optimize.fmin(f,x0, [t,n], xtol=MAX_ERR, ftol=MAX_ERR)
diffs = fsq(x,t,n)
successful = (numpy.abs(diffs)<MAX_ERR).all()
if successful:
log(" OK, error=[%s,%s,%s]\n"%(diffs[0],diffs[1],diffs[2]))
print " SOLUTION FOUND "
print x
else:
tries += 1
log(" FAILED, tries=%d\n"%tries)
print diffs
factor += 0.1
if tries>5:
print "!!!!!!!!!!!! GIVING UP !!!!!!!!!!!"
break
if __name__ == "__main__":
main()
'scipy.optimize.fmin'はNelder-Meadアルゴリズムを使います。SciPyの実装は' optimize.py'ファイルの '_minimize_neldermead'関数にあります。この関数のコピーを取って、変数の変更(関数の簡単な検査から 'x ...')を関数の都度(0と10の間の10進数で)丸めることができますそれらを変更します。 (保証は保証されていません) –
あなたのアイデアで、私ができる最良のものは、すべてのt検定値に対して約1e-5の差です。私は少し良いが必要です:1e - 8。トライアルモードでプログラムを実行しています。より良い解決策を見つけるかもしれません。 – nagylzs