def generate_MFs(inp, outp): """ Generates input MFs from input data in the form: {'var': {'ling':[Xvals_MF1], 'ling':[Xvals_MF2], ...}, 'var': {'ling':[Xvals_MF1], 'ling':[Xvals_MF2], ...}, ... } """ inParams = copy.deepcopy(inp) outParams = copy.deepcopy(outp) for var in inParams: #x_min = min([min(inParams[var][ling]) for ling in inParams[var]]) #x_max = max([max(inParams[var][ling]) for ling in inParams[var]]) #x = np.arange(x_min,x_max,float((x_max-x_min)/100.0)) #generage x values for MF for ling in inParams[var]: #for each MF #if len(inParams[var][ling]) == 3: y = fuzz.trimf( x, inParams[var][ling]) #if 3 values -> triangular #elif len(inParams[var][ling]) == 4: y = fuzz.trapmf(x, sorted(inParams[var][ling])) #if 4 values -> trapezoidal inParams[var][ling] = fuzzyOps.paramsToMF(inParams[var][ling]) for var in outParams: #x_min = min([min(outParams[var][ling]) for ling in outParams[var]]) #x_max = max([max(outParams[var][ling]) for ling in outParams[var]]) #x = np.arange(x_min,x_max,float((x_max-x_min)/100.0)) #generage x values for MF for ling in outParams[var]: #for each MF #if len(outParams[var][ling]) == 3: y = fuzz.trimf( x, outParams[var][ling]) #if 3 values -> triangular #elif len(outParams[var][ling]) == 4: y = fuzz.trapmf(x, sorted(outParams[var][ling])) #if 4 values -> trapezoidal outParams[var][ling] = fuzzyOps.paramsToMF(outParams[var][ling])#[x,y] return inParams, outParams
def generate_MFs(inp, outp): """ Generates input MFs from input data in the form: {'var': {'ling':[Xvals_MF1], 'ling':[Xvals_MF2], ...}, 'var': {'ling':[Xvals_MF1], 'ling':[Xvals_MF2], ...}, ... } """ inParams = copy.deepcopy(inp) outParams = copy.deepcopy(outp) for var in inParams: #x_min = min([min(inParams[var][ling]) for ling in inParams[var]]) #x_max = max([max(inParams[var][ling]) for ling in inParams[var]]) #x = np.arange(x_min,x_max,float((x_max-x_min)/100.0)) #generage x values for MF for ling in inParams[var]: #for each MF #if len(inParams[var][ling]) == 3: y = fuzz.trimf( x, inParams[var][ling]) #if 3 values -> triangular #elif len(inParams[var][ling]) == 4: y = fuzz.trapmf(x, sorted(inParams[var][ling])) #if 4 values -> trapezoidal inParams[var][ling] = fuzzyOps.paramsToMF(inParams[var][ling]) for var in outParams: #x_min = min([min(outParams[var][ling]) for ling in outParams[var]]) #x_max = max([max(outParams[var][ling]) for ling in outParams[var]]) #x = np.arange(x_min,x_max,float((x_max-x_min)/100.0)) #generage x values for MF for ling in outParams[var]: #for each MF #if len(outParams[var][ling]) == 3: y = fuzz.trimf( x, outParams[var][ling]) #if 3 values -> triangular #elif len(outParams[var][ling]) == 4: y = fuzz.trapmf(x, sorted(outParams[var][ling])) #if 4 values -> trapezoidal outParams[var][ling] = fuzzyOps.paramsToMF( outParams[var][ling]) #[x,y] return inParams, outParams
def plotMF_OPT(MFstructIn, MFstructOut, varList, inRanges, outRanges, varMins=None, varMaxs=None): """ Plot membership functions in optimization problem """ inMFsMin, outMFsMin = None, None inMFsMax, outMFsMax = None, None inMFs, outMFs = deparameterize(list(MFstructIn), list(MFstructOut), list(varList)) if not varMins == None: inMFsMin, outMFsMin = deparameterize(list(MFstructIn), list(MFstructOut), list(varMins)) if not varMaxs == None: inMFsMax, outMFsMax = deparameterize(list(MFstructIn), list(MFstructOut), list(varMaxs)) #plot #plt.close('all') #plt.clf() #start a fresh figure if one is open plt.figure(figsize=(10, 6)) i = 1 for inp in inMFs: plt.subplot(len(inMFs) + len(outMFs), 1, i) for mf in inMFs[inp]: vals = fuzzyOps.paramsToMF(inMFs[inp][mf]) plt.plot(vals[0], vals[1], lw=2.0) if inMFsMin <> None: vals = fuzzyOps.paramsToMF(inMFsMin[inp][mf]) plt.plot(vals[0], vals[1], '--', lw=0.8) if inMFsMax <> None: vals = fuzzyOps.paramsToMF(inMFsMax[inp][mf]) plt.plot(vals[0], vals[1], ':', lw=0.8) plt.plot([inRanges[inp][0], inRanges[inp][0]], [0.,1.], '-k', lw=3.0) plt.plot([inRanges[inp][1], inRanges[inp][1]], [0.,1.], '-k', lw=3.0) plt.ylabel('INPUT'+ str(inRanges[inp])) i = i+1 plt.yticks([0.0,1.0]) for otp in outMFs: plt.subplot(len(inMFs) + len(outMFs), 1, i) for mf in outMFs[otp]: vals = fuzzyOps.paramsToMF(outMFs[otp][mf]) plt.plot(vals[0], vals[1], lw=2.0) if outMFsMin <> None: vals = fuzzyOps.paramsToMF(outMFsMin[otp][mf]) plt.plot(vals[0], vals[1], '--', lw=0.8, ) if outMFsMax <> None: vals = fuzzyOps.paramsToMF(outMFsMax[otp][mf]) plt.plot(vals[0], vals[1], ':', lw=0.8, ) plt.plot([outRanges[otp][0], outRanges[otp][0]], [0.,1.], '-k', lw=3.0) plt.plot([outRanges[otp][1], outRanges[otp][1]], [0.,1.], '-k', lw=3.0) plt.ylabel('OUTPUT') i = i+1
elif point[2] < min(outRange): err = point[2] - min(outRange) elif point[2] > max(outRange): err = point[2] - max(outRange) truthRange = point[2] error.append([truthRange, outRange, err]) return error if __name__ == '__main__': #testerror functions import matplotlib.pyplot as plt A = fuzzyOps.paramsToMF([6.,7.,8.]) B = fuzzyOps.paramsToMF([5.5,7.4,8.7]) C = fuzzyOps.paramsToMF([1.5,2.8,4.1]) D = fuzzyOps.paramsToMF([12.,14.,16.]) A_A_int = fuzErrorInt(A, A) A_B_int = fuzErrorInt(A, B) A_C_int = fuzErrorInt(A, C) A_D_int = fuzErrorInt(A, D) print "INT ERRORS:", A_A_int, A_B_int, A_C_int, A_D_int #A = fuzzyOps.paramsToMF([3.,4.,5.]) #B = fuzzyOps.paramsToMF([3.5,4.2,5.7]) #C = fuzzyOps.paramsToMF([1.5,2.8,4.1]) #D = fuzzyOps.paramsToMF([16.,17.,19.])
def plotMF_OPT(MFstructIn, MFstructOut, varList, inRanges, outRanges, varMins=None, varMaxs=None): """ Plot membership functions in optimization problem """ inMFsMin, outMFsMin = None, None inMFsMax, outMFsMax = None, None inMFs, outMFs = deparameterize(list(MFstructIn), list(MFstructOut), list(varList)) if not varMins == None: inMFsMin, outMFsMin = deparameterize(list(MFstructIn), list(MFstructOut), list(varMins)) if not varMaxs == None: inMFsMax, outMFsMax = deparameterize(list(MFstructIn), list(MFstructOut), list(varMaxs)) #plot #plt.close('all') #plt.clf() #start a fresh figure if one is open plt.figure(figsize=(10, 6)) i = 1 for inp in inMFs: plt.subplot(len(inMFs) + len(outMFs), 1, i) for mf in inMFs[inp]: vals = fuzzyOps.paramsToMF(inMFs[inp][mf]) plt.plot(vals[0], vals[1], lw=2.0) if inMFsMin <> None: vals = fuzzyOps.paramsToMF(inMFsMin[inp][mf]) plt.plot(vals[0], vals[1], '--', lw=0.8) if inMFsMax <> None: vals = fuzzyOps.paramsToMF(inMFsMax[inp][mf]) plt.plot(vals[0], vals[1], ':', lw=0.8) plt.plot([inRanges[inp][0], inRanges[inp][0]], [0., 1.], '-k', lw=3.0) plt.plot([inRanges[inp][1], inRanges[inp][1]], [0., 1.], '-k', lw=3.0) plt.ylabel('INPUT' + str(inRanges[inp])) i = i + 1 plt.yticks([0.0, 1.0]) for otp in outMFs: plt.subplot(len(inMFs) + len(outMFs), 1, i) for mf in outMFs[otp]: vals = fuzzyOps.paramsToMF(outMFs[otp][mf]) plt.plot(vals[0], vals[1], lw=2.0) if outMFsMin <> None: vals = fuzzyOps.paramsToMF(outMFsMin[otp][mf]) plt.plot( vals[0], vals[1], '--', lw=0.8, ) if outMFsMax <> None: vals = fuzzyOps.paramsToMF(outMFsMax[otp][mf]) plt.plot( vals[0], vals[1], ':', lw=0.8, ) plt.plot([outRanges[otp][0], outRanges[otp][0]], [0., 1.], '-k', lw=3.0) plt.plot([outRanges[otp][1], outRanges[otp][1]], [0., 1.], '-k', lw=3.0) plt.ylabel('OUTPUT') i = i + 1
def feedforward(self, inputs): """ ------INPUTS------ inputs : dict the set of outputs from previous nodes in form {nodeName: value, nodeName: value, ...} (or inputs for input nodes) """ #INPUT FEED FORWARD (fuzzify inputs) for inp in self.layer1: try: if inp in inputs: #check if input is given if not isinstance(inputs[inp], list): MF = fuzzOps.paramsToMF([inputs[inp]]) #get fuzzy MF for singleton self.layer1[inp] = MF else: self.layer1[inp] = inputs[inp] else: print "Not all inputs given!!!" self.layer3[self.layer3.keys()[0]] = None #set system output to None except: raise StandardError("NEFPROX input error!") #RULE FEED FORWARD (gets min (t-norm) firing strength of weights/MFterms and inputs) for rule in self.layer2: #for each rule for inp in self.connect1to2[rule]: #for each input in antecedent fs = max(fuzz.fuzzy_and(self.inputMFs[inp][0], self.inputMFs[inp][1], self.layer1[inp[0]][0], self.layer1[inp[0]][1])[1]) self.connect1to2[rule][inp] = fs self.layer2[rule] = min([self.connect1to2[rule][inp] for inp in self.connect1to2[rule]]) #OUTPUT FEED FORWARD (apply minimum of firing strength and output MF (reduce output MF), then aggregate) outMFs = [] for rule in self.connect2to3: #for each rule cons = self.connect2to3[rule].keys()[0] #get consequent for single output if self.layer2[rule] > 0.0: #only for active rules (save time) outMF = copy.deepcopy(self.outputMFs[cons][:2]) outMF[1] = np.asarray([ min(self.layer2[rule], outMF[1][i]) for i in range(len(outMF[1])) ]) #apply minimum of firing strength and output MF (reduce output MF) self.connect2to3[rule][cons] = outMF outMFs.append(outMF) else: #for inactive rules, applied MF is 0.0 for all self.connect2to3[rule][cons] = [np.asarray([0.0, 0.0]), np.asarray([0.0,0.0])] #once all rules are reduced with MFs aggregate if len(outMFs) > 0: #check for no rules fired while len(outMFs) > 1: #get maximum (union) of all MFs (aggregation) outMFs0 = outMFs.pop(0) outMFs[0][0], outMFs[0][1] = fuzz.fuzzy_or(outMFs0[0], outMFs0[1], outMFs[0][0], outMFs[0][1]) if self.defuzz == None: pass elif self.defuzz == 'centroid': outMFs[0] = fuzz.defuzz(outMFs[0][0],outMFs[0][1],'centroid') elif self.defuzz == 'bisector': outMFs[0] = fuzz.defuzz(outMFs[0][0],outMFs[0][1],'bisector') elif self.defuzz == 'mom': outMFs[0] = fuzz.defuzz(outMFs[0][0],outMFs[0][1],'mom') #mean of maximum elif self.defuzz == 'som': outMFs[0] = fuzz.defuzz(outMFs[0][0],outMFs[0][1],'som') #min of maximum elif self.defuzz == 'lom': outMFs[0] = fuzz.defuzz(outMFs[0][0],outMFs[0][1],'lom') #max of maximum self.layer3[cons[0]] = outMFs[0] else:#if no rules fire, then output is None if self.defuzz == None: self.layer3[cons[0]] = [[0.0,0.0],[0.0,0.0]] #result 0.0 in fuzzy MF form else: self.layer3[cons[0]] = 0.0 #result 0.0 as crisp if some defuzz method specified return True
def backpropagate(self, error, LR, data, inRanges, outRanges): """ ------INPUTS------ """ #BACKPROP THROUGH OUTPUT NODE: if not isinstance(data, list): dataFuzz = fuzzOps.paramsToMF[[data]] #get fuzzy version of data for FS else: dataFuzz = copy.deepcopy(data) data = fuzz.defuzz(data[0], data[1], 'centroid') #get crisp version of data for rule in self.connect2to3: #for each rule to output connectionMF if self.layer2[rule] > 0.0: #if rule is firing > 0.0 outKey = self.connect2to3[rule].keys()[0] #get connection (outName,ling) fs = max(fuzz.fuzzy_and(self.outputMFs[outKey][0], self.outputMFs[outKey][1], dataFuzz[0], dataFuzz[1])[1]) #get "firing strength" of individual MF (result of MF for data: W(R,y_i)(t_i)) #GET CONSTRAINTS: #Triangular: MFs must overlap (or touch other MFs) [minP, maxP] = outRanges[outKey[0]] if len(self.outputMFs[outKey][2]) == 2: raise StandardError("haven't programmed this") if len(self.outputMFs[outKey][2]) == 3: all_params = [self.outputMFs[ling][2] for ling in self.outputMFs] all_params.sort(key=lambda x: x[1]) #sort params by orderer of b value min_ps = all_params[max(0, all_params.index(self.outputMFs[outKey][2]) - 1)] #get MF just < the one changing if min_ps == self.outputMFs[outKey][2]: min_op = [minP, minP, minP] #adjust if MF is minimum one max_ps = all_params[min(len(all_params) - 1, all_params.index(self.outputMFs[outKey][2]) + 1)]#get MF just > the one changing if max_ps == self.outputMFs[outKey][2]: max_op = [maxP, maxP, maxP] #adjust if MF is maximum one else: raise StandardError("haven't programmed this") if fs > 0: #for W(R,y_i)(t_i) > 0 if len(self.outputMFs[outKey][2]) == 2: #gaussian MF adjustment raise StandardError("haven't programmed this") elif len(self.outputMFs[outKey][2]) == 3: #triangular MF adjustment [a,b,c] = self.outputMFs[outKey][2][:] #get params del_b = LR*error*(c - a)*self.layer2[rule]*(1-fs) del_a = LR*(c - a)*self.layer2[rule] + del_b del_c = -1*LR*(c - a)*self.layer2[rule] + del_b b = min( max(b+del_b, min_ps[1]), max_ps[1] ) #bound b by nearest b's a = min(b, min( max(a+del_a, min_ps[0]), min_ps[2] )) #bound a by nearest a and c and keep a < b c = max(b, min( max(c+del_c, max_ps[0]), max_ps[2] )) #bound c by nearest a and c and keep c > b self.outputMFs[outKey][2] = [a,b,c] #update params elif len(self.outputMFs[outKey][2]) == 4: #trapezoidal MF adjustment raise StandardError("haven't programmed this") else: #for W(R,y_i)(t_i) = 0 if len(self.outputMFs[outKey][2]) == 2: #gaussian MF adjustment raise StandardError("haven't programmed this") elif len(self.outputMFs[outKey][2]) == 3: #triangular MF adjustment [a,b,c] = self.outputMFs[outKey][2][:] #get params del_b = LR*error*(c - a)*self.layer2[rule]*(1-fs) del_a = np.sign(data-b)*LR*(c - a)*self.layer2[rule] + del_b del_c = np.sign(data-b)*LR*(c - a)*self.layer2[rule] + del_b b = min( max(b+del_b, min_ps[1]), max_ps[1] ) #bound b by nearest b's a = min(b, min( max(a+del_a, min_ps[0]), min_ps[2] )) #bound a by nearest a and c and keep a < b c = max(b, min( max(c+del_c, max_ps[0]), max_ps[2] )) #bound c by nearest a and c and keep c > b self.outputMFs[outKey][2] = [a,b,c] #update params elif len(self.outputMFs[outKey][2]) == 4: #trapezoidal MF adjustment raise StandardError("haven't programmed this") newMF = fuzzOps.paramsToMF(self.outputMFs[outKey][2]) #get updated MF self.outputMFs[outKey][0] = newMF[0] #update MF self.outputMFs[outKey][1] = newMF[1] #update MF #BACKPROP THROUGH RULE NODES: for rule in self.layer2: #get Rule Error: E_R = o_R(1-o_R) * sum(2*W(R,y)(t_i) - 1) * abs(error) # note: only one output node: outKey = self.connect2to3[rule].keys()[0] #get connection (outName,ling) fs = max(fuzz.fuzzy_and(self.outputMFs[outKey][0], self.outputMFs[outKey][1], dataFuzz[0], dataFuzz[1])[1]) E_R = self.layer2[rule]*(1-self.layer2[rule]) * (2*fs-1) * abs(error) #rule error for input in self.connect1to2[rule]: o_x = fuzz.defuzz(self.layer1[input[0]][0], self.layer1[input[0]][1], 'centroid') #crisp version of input if self.connect1to2[rule][input] > 0.0: #if FS from that input > 0 if fs > 0: #for W(R,y_i)(t_i) > 0 if len(self.outputMFs[outKey][2]) == 2: #gaussian MF adjustment raise StandardError("haven't programmed this") elif len(self.outputMFs[outKey][2]) == 3: #triangular MF adjustment [a,b,c] = self.inputMFs[input][2][:] #get params del_b = LR*E_R*(c - a)*(1-self.connect1to2[rule][input])*np.sign(o_x - b) del_a = -LR*E_R*(c - a)*(1-self.connect1to2[rule][input])+del_b del_c = LR*E_R*(c - a)*(1-self.connect1to2[rule][input])+del_b #print 'LR', LR, 'E_R', E_R, 'c-a', c-a, '1-W(x,R)(ox)', (1-self.connect1to2[rule][input]) #print 'rule dels:', [del_a, del_b, del_c] self.inputMFs[input][2] = [min(self.inputMFs[input][2][0]+del_a, self.inputMFs[input][2][1]+del_b), self.inputMFs[input][2][1]+del_b, max(self.inputMFs[input][2][2]+del_c, self.inputMFs[input][2][1]+del_b) ] #update params elif len(self.outputMFs[outKey][2]) == 4: #trapezoidal MF adjustment raise StandardError("haven't programmed this") newMF = fuzzOps.paramsToMF(self.inputMFs[input][2]) #get updated MF self.inputMFs[input][0] = newMF[0] #update MF self.inputMFs[input][1] = newMF[1] #update MF