Scipy - 优化. 找到两个变量之间的比例
我有三个变量:市场价格(Market_Price)、小时数(Hours)和年龄(Age)。
通过优化的方法,我找到了这些变量和市场价格之间的关系。
数据:
hours = [1000, 10000, 11000, 11000, 15000, 18000, 37000, 24000, 28000, 28000, 42000, 46000, 50000, 34000, 34000, 46000, 50000, 56000, 64000, 64000, 65000, 80000, 81000, 81000, 44000, 49000, 76000, 76000, 89000, 38000, 80000, 69000, 46000, 47000, 57000, 72000, 77000, 68000]
market_Price = [30945, 28974, 27989, 27989, 36008, 24780, 22980, 23997, 25957, 27847, 36000, 25588, 23980, 25990, 25990, 28995, 26770, 26488, 24988, 24988, 17574, 12995, 19788, 20488, 19980, 24978, 16000, 16400, 18988, 19980, 18488, 16988, 15000, 15000, 16998, 17499, 15780, 8400]
age = [2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 7, 8, 8, 8, 8, 8, 13,]
我得出的关系是:
小时数与市场价格的关系 = log(h)*h1 + h2,
年龄与市场价格的关系 = log(a)*a1 + a2
这里的h1、h2、a1和a2是通过使用Scipy的优化曲线拟合找到的。
现在,我想把这三个变量结合在一起,利用年龄和小时数来计算市场价格。
到目前为止,我的方法是通过找出这两个变量之间的比例,确定哪个组合的标准差最小。
std_divs = []
for ratio in ratios:
n = 0
price_difference_final = []
while n < len(prices):
predicted_price = (log(h)*h1+h1)*ratio + (log(a)*a1+a1)*(1-ratio)
price_difference_final.append(prices[n] - predicted_price)
n += 1
data = np.array(price_difference_final)
std_divs.append(np.std(data))
std_div = min(std_divs)
optimum_ratio = ratios[std_divs.index(min(std_divs))]
正如你所看到的,我是通过蛮力的方法来实现这个目标,这并不是一个优雅的解决方案。
而且,现在我发现这三个变量之间的关系不能用一个单一的比例来表达,反而这个比例需要是动态变化的。随着年份的增加,小时数与年龄的比例会减少,这意味着年龄在市场价格中的影响会越来越大。
不幸的是,我还没能用Scipy的曲线拟合来实现这一点,因为它只接受一对数组。
有没有什么好的想法可以实现这个目标呢?
2 个回答
2
这是一个多元回归的问题,你不需要自己写代码,因为已经有现成的代码可以用:
http://wiki.scipy.org/Cookbook/OLS
注意:最后你并不是有5个参数,h1, h2, a1, a2, ratio
。你实际上只有三个参数:h2*ratio+a2*(1-ratio)
、h1*ratio
和 a1*(1-ratio)
。
In [26]:
y=np.array(market_Price)
x=np.log(np.array([hours, age])).T
In [27]:
mymodel=ols(y, x, 'Market_Price', ['Hours', 'Age'])
In [28]:
mymodel.p # return coefficient p-values
Out[28]:
array([ 1.32065700e-05, 3.06318351e-01, 1.34081122e-05])
In [29]:
mymodel.summary()
==============================================================================
Dependent Variable: Market_Price
Method: Least Squares
Date: Mon, 24 Mar 2014
Time: 15:40:00
# obs: 38
# variables: 3
==============================================================================
variable coefficient std. Error t-statistic prob.
==============================================================================
const 45838.261850 9051.125823 5.064371 0.000013
Hours -1023.097422 985.498239 -1.038152 0.306318
Age -8862.186475 1751.640834 -5.059363 0.000013
==============================================================================
Models stats Residual stats
==============================================================================
R-squared 0.624227 Durbin-Watson stat 1.301026
Adjusted R-squared 0.602754 Omnibus stat 2.999547
F-statistic 29.070664 Prob(Omnibus stat) 0.223181
Prob (F-statistic) 0.000000 JB stat 1.807013
Log likelihood -366.421766 Prob(JB) 0.405146
AIC criterion 19.443251 Skew 0.376021
BIC criterion 19.572534 Kurtosis 3.758751
==============================================================================
2
你可以创建一个多维数组,也就是说这个数组可以有多个层次。在这种情况下,你可以把你的hours
(小时)和age
(年龄)数据一起传递给curve_fit
这个函数。下面是一个例子:
import numpy as np
from scipy.optimize import curve_fit
hours = [1000, 10000, 11000, 11000, 15000, 18000, 37000, 24000,
28000, 28000, 42000, 46000, 50000, 34000, 34000, 46000,
50000, 56000, 64000, 64000, 65000, 80000, 81000, 81000,
44000, 49000, 76000, 76000, 89000, 38000, 80000, 69000,
46000, 47000, 57000, 72000, 77000, 68000]
market_Price = [30945, 28974, 27989, 27989, 36008, 24780, 22980,
23997, 25957, 27847, 36000, 25588, 23980, 25990,
25990, 28995, 26770, 26488, 24988, 24988, 17574,
12995, 19788, 20488, 19980, 24978, 16000, 16400,
18988, 19980, 18488, 16988, 15000, 15000, 16998,
17499, 15780, 8400]
age = [2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 4, 4, 4,
4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 6, 6, 7,
8, 8, 8, 8, 8, 13]
combined = np.array([hours, market_Price])
def f():
# Some function which uses combined where
# combined[0] = hours and combined[1] = market_Price
pass
popt, pcov = curve_fit(f, combined, market_Price)