數據包絡(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)