数据包络(DEA)分析法python实现
数据包络分析法
企业管理者如何评估一所快餐分销店、银行支行、健康诊所或初等学校的生产力?衡量生产力有三重困难:第一,什么是系统适当的投入(如劳动力时间、材料金额)及其度量方法?第二,什么是系统适当的产出(如现金支票、存款凭证)及其度量方法?第三,正确衡量这些投入产出之间关系的方法是什么?
- 衡量服务生产力
从工程学角度看,衡量组织的生产力和衡量系统的效率相似。它可以表述为产出和投入的比率。
例如,再评估一个银行支行的运营效率时,可以用一个会计比率,如每笔出纳交易的成本。相对于其他支行,一个支行的比率较高,则可以认为其效率较低,但是较高的比率可能是源于一个更复杂的交易组合。运用简单比率的问题就在于产出组合没有明确。关于投入组合,也能作出同样的评论。广泛基础上的指标,如赢利性和投资回报,和全面绩效评估高度相关。但它们不足以评估一个服务单位的运营效率。比如,你不能得到以下的结论:一个赢利的支行必定在雇员和其他投入的使用上是有效的。赢利性业务的比率高于平均水平比资源运用的成本效率更能解释其赢利性。 - DEA模型
目前,开发出一种技术,通过明确地考虑多种投入(即资源)的运用和多种产出(即服务)的产生,它能够用来比较提供相似服务的多个服务单位之间的效率,这项技术被称为数据包络线分析(DEA)。它避开了计算每项服务的标准成本,因为它可以把多种投入和多种产出转化为效率比率的分子和分母,而不需要转换成相同的货币单位。因此,用DEA衡量效率可以清晰地说明投入和产出的组合,从而,它比一套经营比率或利润指标更具有综合性并且更值得信赖。
DEA是一个线形规划模型,表示为产出对投入的比率。通过对一个特定单位的效率和一组提供相同服务的类似单位的绩效的比较,它试图使服务单位的效率最大化。在这个过程中,获得100%效率的一些单位被称为相对有效率单位,而另外的效率评分低于100%的单位本称为无效率单位。
这样,企业管理者就能运用DEA来比较一组服务单位,识别相对无效率单位,衡量无效率的严重性,并通过对无效率和有效率单位的比较,发现降低无效率的方法。
python实现算法
输入输出可以在主函数中看到,最后输出的为矩阵
import numpy as np
from scipy.optimize import fmin_slsqp
class DEA(object):
def __init__(self, inputs, outputs):
# supplied data
self.inputs = inputs
self.outputs = outputs
# parameters
self.n = inputs.shape[0]
self.m = inputs.shape[1]
self.r = outputs.shape[1]
# iterators
self.unit_ = range(self.n)
self.input_ = range(self.m)
self.output_ = range(self.r)
# result arrays
self.output_w = np.zeros((self.r, 1), dtype=np.float) # output weights
self.input_w = np.zeros((self.m, 1), dtype=np.float) # input weights
self.lambdas = np.zeros((self.n, 1), dtype=np.float) # unit efficiencies
self.efficiency = np.zeros_like(self.lambdas) # thetas
def __efficiency(self, unit):
# compute efficiency
denominator = np.dot(self.inputs, self.input_w)
numerator = np.dot(self.outputs, self.output_w)
return (numerator/denominator)[unit]
def __target(self, x, unit):
in_w, out_w, lambdas = x[:self.m], x[self.m:(self.m+self.r)], x[(self.m+self.r):] # unroll the weights
denominator = np.dot(self.inputs[unit], in_w)
numerator = np.dot(self.outputs[unit], out_w)
return numerator/denominator
def __constraints(self, x, unit):
in_w, out_w, lambdas = x[:self.m], x[self.m:(self.m+self.r)], x[(self.m+self.r):] # unroll the weights
constr = [] # init the constraint array
# for each input, lambdas with inputs
for input in self.input_:
t = self.__target(x, unit)
lhs = np.dot(self.inputs[:, input], lambdas)
cons = t*self.inputs[unit, input] - lhs
constr.append(cons)
# for each output, lambdas with outputs
for output in self.output_:
lhs = np.dot(self.outputs[:, output], lambdas)
cons = lhs - self.outputs[unit, output]
constr.append(cons)
# for each unit
for u in self.unit_:
constr.append(lambdas[u])
return np.array(constr)
def __optimize(self):
d0 = self.m + self.r + self.n
# iterate over units
for unit in self.unit_:
# weights
x0 = np.random.rand(d0) - 0.5
x0 = fmin_slsqp(self.__target, x0, f_ieqcons=self.__constraints, args=(unit,))
# unroll weights
self.input_w, self.output_w, self.lambdas = x0[:self.m], x0[self.m:(self.m+self.r)], x0[(self.m+self.r):]
self.efficiency[unit] = self.__efficiency(unit)
def fit(self):
self.__optimize() # optimize
return self.efficiency
if __name__ == "__main__":
X = np.array([
[20., 300.],
[30., 200.],
[40., 100.],
[20., 200.],
[10., 400.]
])
y = np.array([
[1000.],
[1000.],
[1000.],
[1000.],
[1000.]
])
dea = DEA(X,y)
rs = dea.fit()
print(rs)