循环内的优化函数和另一个函数

0 投票
2 回答
1300 浏览
提问于 2025-04-18 05:03

我正在尝试用不同的随机值反复求解最佳值。所以我把最小化的函数放在一个循环和一个函数里面,然后调用这个函数。然而,它总是给我不同的答案。

import numpy as np
from scipy.optimize import minimize
def Ln(theta): # Every loop tries to minimize this value
    error = Y - np.maximum(0, theta[0] + X.dot(theta[1:]))
    error_total = np.absolute(error).sum()
    return error_total
theta_true = np.array([-6,3,3,3])
Y = np.array(10)
def get_opt_x():
    for i in range(10):
        X = np.random.standard_normal([10,3]) # generate random values
        u = X[:,0]**2*np.random.standard_normal(10)
        Y_star = theta_true[0] + X.dot(theta_true[1:]) + u
        Y = np.maximum(0, Y_star)
        theta0 = np.ones(4)
        result = minimize(Ln, theta0, method='BFGS')
        print result.x
    return 
get_opt_x()

这是它给出的结果:

enter image description here

正确的答案应该是不同的,因为每次循环都会生成一组新的随机值。如果我去掉这个函数,只用循环,结果就正常了:

for i in range(10):
    X = np.random.standard_normal([10,3])
    u = X[:,0]**2*np.random.standard_normal(10)
    Y_star = theta_true[0] + X.dot(theta_true[1:]) + u
    Y = np.maximum(0, Y_star)
    theta0 = np.ones(4)
    result = minimize(Ln, theta0, method='BFGS')
    print result.x

enter image description here

在循环和另一个函数里面使用最小化函数一定是出了什么问题。

2 个回答

1

问题在于,你在函数 get_opt_x 里面定义了变量 Y,然后希望在函数 Ln 中也能看到这个变量,但Python不允许这样做。当你去掉 get_opt_x 这个函数时,变量 Y 就可以在全局范围内使用,因此 Ln 函数也能看到它。

你需要在 get_opt_x 的开头告诉Python Y 是一个全局变量:

def get_opt_x():
    global Y
1

在函数 get_opt_x() 中的变量 XY 是局部变量,也就是说它们只在这个函数里面有效,和函数 Ln 中的 XY 是不一样的。你从 get_opt_x() 得到的结果都是一样的,因为它使用的是你上一次运行循环时的值(通过去掉你的函数来实现的)。为了证明这一点,你可以尝试关闭你的会话,然后先运行第一段代码,再运行第二段代码,你会看到一个错误,提示 X 没有被初始化。

解决办法:XY 作为额外的参数传递给 minimize 函数。

def Ln(theta, X, Y): # Every loop tries to minimize this value
    error = Y - np.maximum(0, theta[0] + X.dot(theta[1:]))
    error_total = np.absolute(error).sum()
    return error_total

theta_true = np.array([-6,3,3,3])
Y = np.array(10)

def get_opt_x():
    for i in range(10):
        X = np.random.standard_normal([10,3]) # generate random values
        u = X[:,0]**2*np.random.standard_normal(10)
        Y_star = theta_true[0] + X.dot(theta_true[1:]) + u
        Y = np.maximum(0, Y_star)
        theta0 = np.ones(4)
        result = minimize(Ln, theta0, (X, Y), method='BFGS')
        print result.x
    return 

get_opt_x()

撰写回答