Source code for pyFTS.common.FuzzySet

import numpy as np
from pyFTS import *
from pyFTS.common import Membership


[docs]class FuzzySet(object): """ Fuzzy Set """ def __init__(self, name : str, mf, parameters : list, centroid : float, alpha : float=1.0, **kwargs): """ Create a Fuzzy Set """ self.name : str = name """The fuzzy set name""" self.mf = mf """The membership function""" self.parameters : list = parameters """The parameters of the membership function""" self.centroid : float = centroid """The fuzzy set center of mass (or midpoint)""" self.alpha : float = alpha """The alpha cut value""" self.type : str = kwargs.get('type', 'common') """The fuzzy set type (common, composite, nonstationary, etc)""" self.variable = kwargs.get('variable', None) """In multivariate time series, indicate for which variable this fuzzy set belogs""" self.Z = None """Partition function in respect to the membership function""" if parameters is not None: if self.mf == Membership.gaussmf: self.lower = parameters[0] - parameters[1] * 3 self.upper = parameters[0] + parameters[1] * 3 elif self.mf == Membership.sigmf: k = (parameters[1] / (2 * parameters[0])) self.lower = parameters[1] - k self.upper = parameters[1] + k else: self.lower = min(parameters) self.upper = max(parameters) self.metadata = {}
[docs] def transform(self, x): """ Preprocess the data point for non native types :param x: :return: return a native type value for the structured type """ return x
[docs] def membership(self, x): """ Calculate the membership value of a given input :param x: input value :return: membership value of x at this fuzzy set """ return self.mf(self.transform(x), self.parameters) * self.alpha
[docs] def partition_function(self, uod=None, nbins=100): """ Calculate the partition function over the membership function. :param uod: :param nbins: :return: """ if self.Z is None and uod is not None: self.Z = 0.0 for k in np.linspace(uod[0], uod[1], nbins): self.Z += self.membership(k) return self.Z
def __str__(self): return self.name + ": " + str(self.mf.__name__) + "(" + str(self.parameters) + ")"
def __binary_search(x, fuzzy_sets, ordered_sets): """ Search for elegible fuzzy sets to fuzzyfy x :param x: input value to be fuzzyfied :param fuzzy_sets: a dictionary where the key is the fuzzy set name and the value is the fuzzy set object. :param ordered_sets: a list with the fuzzy sets names ordered by their centroids. :return: A list with the best fuzzy sets that may contain x """ max_len = len(fuzzy_sets) - 1 first = 0 last = max_len while first <= last: midpoint = (first + last) // 2 fs = ordered_sets[midpoint] fs1 = ordered_sets[midpoint - 1] if midpoint > 0 else ordered_sets[0] fs2 = ordered_sets[midpoint + 1] if midpoint < max_len else ordered_sets[max_len] if fuzzy_sets[fs1].centroid <= fuzzy_sets[fs].transform(x) <= fuzzy_sets[fs2].centroid: return (midpoint - 1, midpoint, midpoint + 1) elif midpoint <= 1: return [0] elif midpoint >= max_len: return [max_len] else: if fuzzy_sets[fs].transform(x) < fuzzy_sets[fs].centroid: last = midpoint - 1 else: first = midpoint + 1
[docs]def fuzzyfy(data, partitioner, **kwargs): """ A general method for fuzzyfication. :param data: input value to be fuzzyfied :param partitioner: a trained pyFTS.partitioners.Partitioner object :param kwargs: dict, optional arguments :keyword alpha_cut: the minimal membership value to be considered on fuzzyfication (only for mode='sets') :keyword method: the fuzzyfication method (fuzzy: all fuzzy memberships, maximum: only the maximum membership) :keyword mode: the fuzzyfication mode (sets: return the fuzzy sets names, vector: return a vector with the membership values for all fuzzy sets, both: return a list with tuples (fuzzy set, membership value) ) :returns a list with the fuzzyfied values, depending on the mode """ alpha_cut = kwargs.get('alpha_cut', 0.) mode = kwargs.get('mode', 'sets') method = kwargs.get('method', 'fuzzy') if isinstance(data, (list, np.ndarray)): if mode == 'vector': return fuzzyfy_instances(data, partitioner.sets, partitioner.ordered_sets) elif mode == 'both': mvs = fuzzyfy_instances(data, partitioner.sets, partitioner.ordered_sets) fs = [] for mv in mvs: fsets = [(partitioner.ordered_sets[ix], mv[ix]) for ix in np.arange(len(mv)) if mv[ix] >= alpha_cut] fs.append(fsets) return fs else: return fuzzyfy_series(data, partitioner.sets, method, alpha_cut, partitioner.ordered_sets) else: if mode == 'vector': return fuzzyfy_instance(data, partitioner.sets, partitioner.ordered_sets) elif mode == 'both': mv = fuzzyfy_instance(data, partitioner.sets, partitioner.ordered_sets) fsets = [(partitioner.ordered_sets[ix], mv[ix]) for ix in np.arange(len(mv)) if mv[ix] >= alpha_cut] return fsets else: return get_fuzzysets(data, partitioner.sets, partitioner.ordered_sets, alpha_cut)
[docs]def set_ordered(fuzzy_sets): """ Order a fuzzy set list by their centroids :param fuzzy_sets: a dictionary where the key is the fuzzy set name and the value is the fuzzy set object. :return: a list with the fuzzy sets names ordered by their centroids. """ if len(fuzzy_sets) > 0: tmp1 = [fuzzy_sets[k] for k in fuzzy_sets.keys()] return [k.name for k in sorted(tmp1, key=lambda x: x.centroid)]
[docs]def fuzzyfy_instance(inst, fuzzy_sets : dict , ordered_sets : list =None): """ Calculate the membership values for a data point given fuzzy sets :param inst: data point :param fuzzy_sets: a dictionary where the key is the fuzzy set name and the value is the fuzzy set object. :param ordered_sets: a list with the fuzzy sets names ordered by their centroids. :return: array of membership values """ if ordered_sets is None: ordered_sets = set_ordered(fuzzy_sets) mv = np.zeros(len(fuzzy_sets)) for ix in __binary_search(inst, fuzzy_sets, ordered_sets): mv[ix] = fuzzy_sets[ordered_sets[ix]].membership(inst) return mv
[docs]def fuzzyfy_instances(data : list, fuzzy_sets : dict, ordered_sets=None) -> list: """ Calculate the membership values for a data point given fuzzy sets :param inst: data point :param fuzzy_sets: a dictionary where the key is the fuzzy set name and the value is the fuzzy set object. :param ordered_sets: a list with the fuzzy sets names ordered by their centroids. :return: array of membership values """ ret = [] if ordered_sets is None: ordered_sets = set_ordered(fuzzy_sets) for inst in data: mv = fuzzyfy_instance(inst, fuzzy_sets, ordered_sets) ret.append(mv) return ret
[docs]def get_fuzzysets(inst, fuzzy_sets : dict, ordered_sets : list =None, alpha_cut : float =0.0) -> list: """ Return the fuzzy sets which membership value for a inst is greater than the alpha_cut :param inst: data point :param fuzzy_sets: a dictionary where the key is the fuzzy set name and the value is the fuzzy set object. :param ordered_sets: a list with the fuzzy sets names ordered by their centroids. :param alpha_cut: Minimal membership to be considered on fuzzyfication process :return: array of membership values """ if ordered_sets is None: ordered_sets = set_ordered(fuzzy_sets) try: fs = [ordered_sets[ix] for ix in __binary_search(inst, fuzzy_sets, ordered_sets) if fuzzy_sets[ordered_sets[ix]].membership(inst) > alpha_cut] return fs except Exception as ex: raise ex
[docs]def get_maximum_membership_fuzzyset(inst, fuzzy_sets, ordered_sets=None) -> FuzzySet: """ Fuzzify a data point, returning the fuzzy set with maximum membership value :param inst: data point :param fuzzy_sets: a dictionary where the key is the fuzzy set name and the value is the fuzzy set object. :param ordered_sets: a list with the fuzzy sets names ordered by their centroids. :return: fuzzy set with maximum membership """ if ordered_sets is None: ordered_sets = set_ordered(fuzzy_sets) mv = np.array([fuzzy_sets[key].membership(inst) for key in ordered_sets]) key = ordered_sets[np.argwhere(mv == max(mv))[0, 0]] return fuzzy_sets[key]
[docs]def get_maximum_membership_fuzzyset_index(inst, fuzzy_sets) -> int: """ Fuzzify a data point, returning the fuzzy set with maximum membership value :param inst: data point :param fuzzy_sets: dict of fuzzy sets :return: fuzzy set with maximum membership """ mv = fuzzyfy_instance(inst, fuzzy_sets) return np.argwhere(mv == max(mv))[0, 0]
[docs]def fuzzyfy_series_old(data, fuzzy_sets, method='maximum'): fts = [] for item in data: fts.append(get_maximum_membership_fuzzyset(item, fuzzy_sets).name) return fts
[docs]def fuzzyfy_series(data, fuzzy_sets, method='maximum', alpha_cut=0.0, ordered_sets=None): fts = [] if ordered_sets is None: ordered_sets = set_ordered(fuzzy_sets) for t, i in enumerate(data): mv = fuzzyfy_instance(i, fuzzy_sets, ordered_sets) if len(mv) == 0: sets = check_bounds(i, fuzzy_sets.items(), ordered_sets) else: if method == 'fuzzy': ix = np.ravel(np.argwhere(mv > alpha_cut)) sets = [fuzzy_sets[ordered_sets[i]].name for i in ix] elif method == 'maximum': mx = max(mv) ix = np.ravel(np.argwhere(mv == mx)) sets = fuzzy_sets[ordered_sets[ix[0]]].name fts.append(sets) return fts
[docs]def grant_bounds(data, fuzzy_sets, ordered_sets): if data < fuzzy_sets[ordered_sets[0]].lower: return fuzzy_sets[ordered_sets[0]].lower elif data > fuzzy_sets[ordered_sets[-1]].upper: return fuzzy_sets[ordered_sets[-1]].upper else: return data
[docs]def check_bounds(data, fuzzy_sets, ordered_sets): if data < fuzzy_sets[ordered_sets[0]].lower: return fuzzy_sets[ordered_sets[0]] elif data > fuzzy_sets[ordered_sets[-1]].upper: return fuzzy_sets[ordered_sets[-1]]
[docs]def check_bounds_index(data, fuzzy_sets, ordered_sets): if data < fuzzy_sets[ordered_sets[0]].get_lower(): return 0 elif data > fuzzy_sets[ordered_sets[-1]].get_upper(): return len(fuzzy_sets) - 1