在函数中(局部)使用遗传算法-最小化函数

时间:2019-12-19 09:20:27

标签: python numpy-ndarray scipy-optimize differential-evolution

我一直在尝试使用遗传算法来使我的幂定律适合不同的实验。问题是我不太了解它。我想我了解所有内容,但sumOfSquaredError(parameterTuple)函数除外。

我一直试图理解和使用的代码,它是社区中普遍共享的一种,它是由称为

的函数构建的
  • func(x,a,b)-适合我们的实验数据的模型函数

  • sumOfSquaredError(parameterTuple)-通过遗传算法最小化的功能

  • generate_Initial_Parameters()-基于SciPy的遗传算法生成初始参数

然后我要做的是使用具有pandas.DataFrame作为输入的main函数。此功能从数据框中选择特定的行和列(以进行单个实验)并进行处理。

我与发布的一般代码的不同之处在于,我具有使用熊猫数据框输入的此功能,这仅是索引数据集。然后,我对其施加了一些条件,以便从数据集中提取特定数据,以便每次迭代仅对整个数据集进行一次实验,然后尝试将其定义为xData和yData。


精算

如果尝试输入xData和yData:

yData = np.asarray(y_eff)
xData = np.asarray(x)

# diff_evolution completes by calling curve_fit() using param. bounds
geneticParameters = generate_Initial_Parameters(xData, yData)

为了定义sumOfSquaredError(xData,yData,parameterTuple):

    # "seed" the numpy random number generator for repeatable results
result = scipy.optimize.differential_evolution(
    sumOfSquaredError(xData, yData, parameterBounds),
    parameterBounds, seed=3)

它返回:

get_Results中的文件“ /home/josep/programa.py”,第361行     GeneticParameters = generate_Initial_Parameters(xData,yData)

generate_Initial_Parameters中的文件“ /home/josep/programa.py”,第267行     parameterBounds,seed = 3)

文件“ /home/josep/anaconda3/lib/python3.7/site-packages/scipy/optimize/_differentialevolution.py”,第276行,在differential_evolution中     ret = Solver.solve()

文件“ /home/josep/anaconda3/lib/python3.7/site-packages/scipy/optimize/_differentialevolution.py”,第688行,正在解决     人口)

文件“ /home/josep/anaconda3/lib/python3.7/site-packages/scipy/optimize/_differentialevolution.py”,第794行,在_calculate_population_energies中     提高RuntimeError(“类似地图的可调用对象必须是”

RuntimeError:类似于地图的可调用对象必须采用f(func,iterable)的形式,并返回与'iterable'相同长度的数字序列。


我遇到的错误是:

  • NameError:未定义名称“ xData” 文件“ /home/josep/programa.py”,行245,位于sumOfSquaredError中 val = func(xData,* parameterTuple)

我认为在函数内部调用sumOfSquaredError(parameterTuple)时遇到问题,因为该函数使用的是定义为全局变量的变量。这可能还与 scipy.optimize.differential_evolution()有关。

如果我尝试输入xData和yData作为输入参数,那么它会要求我也输入 parameterTuple 我不知道它的来源,因为它是在任何地方都没有定义。

def sumOfSquaredError(parameterTuple):
    """
    Input to the genetic algorithm.

    Function for the genetic algorithm to minimize (sum of squared error).

    Parameters: xData, yData, parameterTuple
    ----------

    Returns
    -------
    Squared difference between experimental data and predicted data
    """
    # do not print warnings by genetic algorithm
    warnings.filterwarnings("ignore")
    val = func(xData, *parameterTuple)
    return np.sum((yData - val) ** 2.0)

我正在使用的其他功能是:

def generate_Initial_Parameters():
    """
    Generate initial parameters based on SciPy's genetic algorithm.

    Returns
    -------
    result.x is the optimization result

    """
    parameterBounds = []
    parameterBounds.append([0, 100.0])  # search bounds for a
    parameterBounds.append([0, 100.0])  # search bounds for b

    # "seed" the numpy random number generator for repeatable results
    result = differential_evolution(sumOfSquaredError, parameterBounds, seed=3)
    return result.x

这是我在代码中调用的主要函数,在该代码中我输入df并在每次迭代中选择特定的行。 (如果有人要导入,我也会在这里写出来)

import numpy
import pandas as pd
import matplotlib.pyplot as plt
import scipy as scipy
from scipy.optimize import differential_evolution
from sklearn import linear_model
from sklearn.metrics import mean_squared_error, r2_score
import warnings

def get_Results(df):
    """
    Process df.

    Parameters.
    ----------
    df : Dataframe with the data

    Returns results which is a DataFrame with columns describing
    regression coefficients
    -------
    """
    columns_results = 'Full_Name', 'Slope', 'Y-intercept', 'MSE', 'R2_score'

    results = pd.DataFrame(columns=columns_results)

# Processing - Ht(%) = 0
    sample_names = df['Sample'][
        df['Ht(%)'] == 0].drop_duplicates()

    for i in range(len(sample_names)):
        df_i = df[(df['Sample'] == sample_names.values[i])
                     & (df['Ht(%)'] == 0.0)]

        name = 'Ht(%)=' + str(df_i['Ht(%)'].values[i]) \
            + '    ' + 'Sample: ' + df_i['Sample'].values[i]

        y_o = pd.DataFrame(df_i['Pressure(Pa)'].values)
        x_o = pd.DataFrame(df_i['Velocity(um/s)'].values)

# Create linear regression object
        regr = linear_model.LinearRegression()
# Train the model using the dataset
        regr.fit(x_o, y_o)  # fit(self, X, y[, sample_weight]) - Fit linear model.
# Make predictions using the estimator set
        y_pred = regr.predict(x_o)

        yData = numpy.asarray(y_o)
        xData = numpy.asarray(x_o)

        # diff_evolution completes by calling curve_fit() using param. bounds
        geneticParameters = generate_Initial_Parameters()

        # now call curve_fit without passing bounds from the genetic algorithm,
        # just in case the best fit parameters are aoutside those bounds
        fittedParameters, pcov = scipy.optimize.curve_fit(
            func, xData, yData, geneticParameters)
        print('Fitted parameters:', fittedParameters)
        print()
        modelPredictions = func(xData, *fittedParameters)

        absError = modelPredictions - yData

        SE = numpy.square(absError)  # Squared Errors
        MSE = numpy.mean(SE)  # Mean Squared Errors
        RMSE = numpy.sqrt(MSE)  # Root Mean Squared Error, RMSE
        Rsquared = 1.0 - (numpy.var(absError) / numpy.var(y_o))

        print()
        print('RMSE:', RMSE)
        print('R-squared:', Rsquared)


# Fill up results DataFrame
        df = pd.DataFrame(
            [[name,
              regr.coef_[0, 0], regr.intercept_[0],
              mean_squared_error(y_o, y_pred),
              r2_score(y_o, y_pred)]], columns=columns_results)

        results = results.append(df, ignore_index=True)

    return results

启动-解决方案

正如@jeremy_rutman所建议的,这只是在函数内部全局定义xData和yData的问题。但是,问题是我定义的数组的尺寸不是必需的。

定义它们时要引入的正确代码如下

global xData
global yData

yData = np.asarray(y_eff).reshape(len(y_eff))
xData = np.asarray(x).reshape(len(x)) 

(对于我来说,问题是在全局定义时返回:    值错误:对象对于所需数组而言太深    错误:函数调用的结果不是正确的浮点数组 )

1 个答案:

答案 0 :(得分:0)

问题可能完全是由于声明

def sumOfSquaredError(parameterTuple):

显然应该是

def sumOfSquaredError(xdata,ydata,parameterTuple):

尽管这里似乎也未声明使用func

相关问题