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

Using genetic algorithm in a function (locally) - minimizing function

我一直在尝试使用遗传算法,以便在不同的实验中拟合我的幂律。问题是我并不真正完全理解它。我想除了 sumOfSquaredError(parameterTuple) 函数我什么都懂。

我一直在努力理解和使用的代码,它是社区中普遍共享的代码,它是由以下函数构建的:

然后我要做的是使用具有 pandas.DataFrame 作为输入的 main 函数。此函数 select 数据框中的特定行和列(为了获得单个实验)并对其进行处理。

我与发布的一般代码不同的是,我有这个函数和一个 pandas 数据框输入,它只不过是一个索引数据集。然后,我对其施加一些条件,以便从数据集中提取特定数据,以便每次迭代只对整个数据集进行一次实验,并尝试将其定义为 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)

它returns:

文件“/home/josep/programa.py”,第 361 行,在 get_Results 遗传参数 = generate_Initial_Parameters(xData, yData)

文件“/home/josep/programa.py”,第 267 行,在 generate_Initial_Parameters 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 行,在求解 self.population)

文件“/home/josep/anaconda3/lib/python3.7/site-packages/scipy/optimize/_differentialevolution.py”,第 794 行,在 _calculate_population_energies 提高 RuntimeError("The map-like callable must be of the"

RuntimeError: 类似地图的可调用函数必须采用 f(func, iterable) 形式,返回与 'iterable'

长度相同的数字序列

我遇到的错误是:

我想我在函数内部调用 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 和 select 特定行的代码中调用的主要函数。 (如果有人需要的话,我也在这里写进口)

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)) 

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

问题可能完全是声明的问题

def sumOfSquaredError(parameterTuple):

显然应该是

def sumOfSquaredError(xdata,ydata,parameterTuple):

虽然这里似乎也没有声明使用func