我一直在尝试使用遗传算法来适应我在不同实验中的幂律。问题是我并不完全理解它。我想我了解除了 sumOfSquaredError(parameterTuple) 函数之外的所有内容。
我一直在尝试理解和使用的代码,它是社区中常用的代码,它是由以下函数构建的:
func(x, a, b) - 拟合我们的实验数据的模型函数
sumOfSquaredError(parameterTuple) - 通过遗传算法最小化的函数
generate_Initial_Parameters() - 根据 SciPy 的遗传算法生成初始参数
然后我要做的是使用具有 pandas.DataFrame 作为输入的 main 函数。此函数从数据框中选择特定的行和列(以便获得单个实验)并对其进行处理。
我与发布的一般代码的不同之处在于,我有一个带有 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)
它返回:
文件“/home/josep/programa.py”,第 361 行,在 get_ResultsgeneticParameters = 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 行,在different_evolution ret = solver.solve()
文件“/home/josep/anaconda3/lib/python3.7/site-packages/scipy/optimize/_differentialevolution.py”,第 688 行,在解决 self.population 中)
_calculate_population_energies 中的文件“/home/josep/anaconda3/lib/python3.7/site-packages/scipy/optimize/_differentialevolution.py”,第 794 行引发 RuntimeError(“类似地图的可调用对象必须属于”
RuntimeError:类似地图的可调用对象必须是 f(func, iterable) 的形式,返回与“可迭代”长度相同的数字序列
我面临的错误是:
- NameError: name 'xData' is not defined File "/home/josep/programa.py", line 245, in 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))
(在我的情况下,问题是在全局定义时它返回:值错误:对象太深,无法满足所需的数组错误:函数调用的结果不是正确的浮点数组)