Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file removed doc/x:y.png
Binary file not shown.
Binary file removed docs/operations/x:y.png
Binary file not shown.
4 changes: 3 additions & 1 deletion ipynb/fuzzy_plots.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,9 @@
{
"cell_type": "code",
"execution_count": 13,
"metadata": {},
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
Expand Down
6 changes: 1 addition & 5 deletions ipynb/sample_points.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,7 @@
"metadata": {},
"outputs": [
{
"data": {
"application/javascript": [
"IPython.notebook.set_autosave_interval(0)"
]
},
"data": {},
"metadata": {},
"output_type": "display_data"
},
Expand Down
1 change: 1 addition & 0 deletions phuzzy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
from phuzzy.shapes import FuzzyNumber, Trapezoid, Triangle, Uniform
from phuzzy.shapes.superellipse import Superellipse
from phuzzy.shapes.truncnorm import TruncGenNorm, TruncNorm
from phuzzy.shapes.skewnorm import Skewnorm

class Analysis(object):
def __init__(self, **kwargs):
Expand Down
9 changes: 9 additions & 0 deletions phuzzy/fuzzification/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# -*- coding: utf-8 -*-

from phuzzy.fuzzification import fuzzy_fitting




if __name__ == "__main__":
pass
188 changes: 188 additions & 0 deletions phuzzy/fuzzification/fuzzy_fitting.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
import numpy as np
import pandas as pd
import scipy.stats as st

import phuzzy.mpl as phm
import phuzzy.mpl.plots

import warnings
import matplotlib.pyplot as plt
plt.style.use('seaborn')




class Data_Fitting(object):

def __init__(self):
pass


def best_fit_distribution(self, data, number_of_alpha_levels=6, bins=False, bootstrap=False, ax=True,
filepath=None):
"""
Routine to determin automatically a suiting membership function to a given data set

:param data: input array
:param number_of_alpha_levels: level of discritization of the membership function
:param bins: number of histogram bins
:param bootstrap: applying / not applying bootstrap algorithm
:param ax: plot command
:param filepath: safe plot

:return: fuzzy parameter
"""

"""Model data by finding best fit distribution to data"""

if bootstrap:
data = self._bootstrap(data)

# Get histogram of original data
if bins:
y, x = np.histogram(data, bins=bins, density=True)
else:
y, x = np.histogram(data, bins='fd', density=True)

y, x = np.histogram(data, density=True)
x = (x + np.roll(x, -1))[:-1] / 2.0
DISTRIBUTIONS = [
st.triang,
st.norm,
st.uniform
]
# Best holders
best_distribution = st.triang
best_params = (0.0, 1.0)
best_sse = np.inf
dists = []
# Estimate distribution parameters from data
for distribution in DISTRIBUTIONS:
# Try to fit the distribution
try:
# Ignore warnings from data that can't be fit
with warnings.catch_warnings():
warnings.filterwarnings('ignore')
# fit dist to data
params = distribution.fit(data)
# Separate parts of parameters
arg = params[:-2]
loc = params[-2]
scale = params[-1]
# Calculate fitted PDF and error with fit in distribution
pdf = distribution.pdf(x, loc=loc, scale=scale, *arg)
sse = np.sum(np.power(y - pdf, 2.0))
dist = distribution(loc=loc, scale=scale, *arg)
dists.append([dist, loc, scale, arg])
# if axis pass in add to plot
#try:
# if ax:
# pd.Series(pdf, x).plot(ax=ax)
#except Exception:
# pass
# identify if this distribution is better
if best_sse > sse > 0:
best_distribution = distribution.name
best_params = params
best_sse = sse
except Exception:
pass

x = np.linspace(data.min(),data.max(), 500)

if best_distribution == 'norm':
dist, loc, scale, args = dists[0]
a = max(abs(loc-data.min()), abs(loc-data.max()))
fuzzy_var = phm.TruncNorm(alpha0=[loc-a, loc+a], alpha1=[data.mean()],
number_of_alpha_levels=number_of_alpha_levels)
#return (tgn, tgn.get_shape())

elif best_distribution == 'triang':
dist, loc, scale, args = dists[0]
y = dist.pdf(x)
y /= y.max()
df = pd.DataFrame({"x":x, "y":y})
loc = df.loc[df.y.idxmax()].x
fuzzy_var = phm.Triangle(alpha0=[data.min(), data.max()], alpha1=[loc],
number_of_alpha_levels=number_of_alpha_levels)
#return (tria, tria.get_shape())

elif best_distribution == 'uniform':
dist, loc, scale, args = dists[1]
fuzzy_var = phm.Uniform(alpha0=[data.min(),data.max()], alpha1=[1.00,1.00],
number_of_alpha_levels=number_of_alpha_levels)
#return (uni, uni.get_shape())
else:
raise ValueError


if ax:
fig, ax = plt.subplots(1,1, figsize=(8,5))
x = np.linspace(data.min(),data.max(), 500)
y = dist.pdf(x)
y /= y.max()
df = pd.DataFrame({"x":x, "y":y})
ax.plot(x,y, label="hist fit", color="g", lw=2, alpha=.8, ls="--")
ax.axvline(data.min(), dashes=[5,2,1,2], c="k", alpha=.5)
ax.axvline(data.max(), dashes=[5,2,1,2], c="k", alpha=.5)
ax.axvline(loc, dashes=[5,2,1,2], c="k", alpha=.5)
ax.scatter(data, np.ones_like(data)*(-.1), color="g", alpha=.4, label="data")
ax.set_ylabel(r"$\alpha$ [$-$]")
fuzzy_var_shape = fuzzy_var.get_shape()
ax.plot(fuzzy_var_shape.x, fuzzy_var_shape.alpha, label="Phuzzy Variable", alpha=.4, color="r")

if bins:
phuzzy.mpl.plots.plot_hist(data, bins=bins, ax=ax, normed=True, color="b",
filled=True, alpha=.3, label='histo data')
else:
phuzzy.mpl.plots.plot_hist(data, ax=ax, bins='fd', normed=True, color="b",
filled=True, alpha=.3, label='histo data')

if best_distribution == 'norm': ax.set_title('TruncNorm')
elif best_distribution == 'triang': ax.set_title('Triangle')
elif best_distribution == 'uniform': ax.set_title('Uniform')

ax.legend(fancybox=True, framealpha=0.5, loc=1)
plt.show()

if filepath:
fig.savefig(filepath, dpi=360)


return fuzzy_var


def _bootstrap(self,data):
"""
Bootstrapping Algorithm for stretching data

:param data: Input Data
:return: Boostrapped Data
"""
xbar = np.zeros(shape=1000)
for i in range(1000):
sample = data[np.random.randint(0,len(data),size=len(data))]
xbar[i] = np.mean(sample)
np.append(xbar,data.min())
np.append(xbar,data.max())
return xbar


def fit_plot(self,data,fuzzy_var,dist):

fig, ax = plt.subplots(1,1, figsize=(10,5))

x = np.linspace(data.min(),data.max(), 500)
y = dist.pdf(x)
y /= y.max()
df = pd.DataFrame({"x":x, "y":y})
# pdf = make_pdf(st.norm, [loc, scale]+args)
ax.plot(x,y, label="hist fit", color="g", lw=2, alpha=.8, ls="--")
dist, loc, scale, args = dist[0]

ax.axvline(data.min(), dashes=[5,2,1,2], c="k", alpha=.5)
ax.axvline(data.max(), dashes=[5,2,1,2], c="k", alpha=.5)
ax.axvline(loc, dashes=[5,2,1,2], c="k", alpha=.5)
ax.scatter(data, np.ones_like(data)*(-.1), color="g", alpha=.4, label="data")


27 changes: 21 additions & 6 deletions phuzzy/mpl/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import numpy as np
import phuzzy


def extend_instance(obj, cls):
"""Apply mixins to a class instance after creation"""
base_cls = obj.__class__
Expand All @@ -25,7 +26,7 @@ def mix_mpl(obj):

class MPL_Mixin():

def plot(self, ax=None, filepath=None, show=False, xlim=None, labels=True, title=False, ppf=None):
def plot(self, ax=None, filepath=None, show=False, xlim=None, labels=True, title=False, ppf=None, defuzzy=None):
"""plots fuzzy number with mpl"""
logging.debug("plots fuzzy number with mpl")
df = self.df
Expand All @@ -43,6 +44,15 @@ def plot(self, ax=None, filepath=None, show=False, xlim=None, labels=True, title
ax.grid(c="gray", alpha=.5, lw=.5, dashes=[1, 3])


if defuzzy is not None:
ax.plot([defuzzy[0], defuzzy[0]], [0, defuzzy[1]], linestyle= ':',color='#3188cb', label=defuzzy[0])

if defuzzy is not None and labels is True:
ax.annotate('%.3g' % defuzzy[0], xy=(defuzzy[0], (defuzzy[1]+0.018)), xycoords='data',
xytext=(-2, -9), textcoords='offset points',
horizontalalignment='right', verticalalignment='bottom', alpha=.4)


xs = np.hstack([df["l"].values, df["r"].values[::-1]])
ys = np.hstack([df["alpha"].values, df["alpha"].values[::-1]])
ax.plot(xs, ys, lw=1, alpha=.7)
Expand All @@ -60,17 +70,17 @@ def plot(self, ax=None, filepath=None, show=False, xlim=None, labels=True, title
ax.set_xlabel('%s' % self.name)
ax.set_ylabel(r'$\alpha$')
ax.grid(c="gray", alpha=.5, lw=.5, dashes=[1, 3])
ax.annotate('%.3g' % a0["l"], xy=(a0["l"], a0["alpha"]), xycoords='data',
ax.annotate('%.5g' % a0["l"], xy=(a0["l"], a0["alpha"]), xycoords='data',
xytext=(-2, 2), textcoords='offset points',
horizontalalignment='right', verticalalignment='bottom', alpha=.4)
ax.annotate('%.3g' % a0["r"], xy=(a0["r"], a0["alpha"]), xycoords='data',
ax.annotate('%.5g' % a0["r"], xy=(a0["r"], a0["alpha"]), xycoords='data',
xytext=(2, 2), textcoords='offset points',
horizontalalignment='left', verticalalignment='bottom', alpha=.4)
a1 = self.alpha1
ax.annotate('%.3g' % a1["l"], xy=(a1["l"], a1["alpha"]), xycoords='data',
ax.annotate('%.5g' % a1["l"], xy=(a1["l"], a1["alpha"]), xycoords='data',
xytext=(-2, 2), textcoords='offset points',
horizontalalignment='right', verticalalignment='bottom', alpha=.4)
ax.annotate('%.3g' % a1["r"], xy=(a1["r"], a1["alpha"]), xycoords='data',
ax.annotate('%.5g' % a1["r"], xy=(a1["r"], a1["alpha"]), xycoords='data',
xytext=(2, 2), textcoords='offset points',
horizontalalignment='left', verticalalignment='bottom', alpha=.4)
dx = abs(self.alpha0["r"] - self.alpha0["l"])
Expand All @@ -89,7 +99,7 @@ def plot(self, ax=None, filepath=None, show=False, xlim=None, labels=True, title
try:
fig.tight_layout()
if filepath:
fig.savefig(filepath, dpi=90)
fig.savefig(filepath, dpi=360)
except UnboundLocalError:
pass

Expand Down Expand Up @@ -206,3 +216,8 @@ class Superellipse(phuzzy.Superellipse, MPL_Mixin):
"""Superellipse fuzzy number with matplotlib mixin"""
def __init__(self, **kwargs):
phuzzy.Superellipse.__init__(self, **kwargs)

class Skewnorm(phuzzy.Skewnorm, MPL_Mixin):
"""Superellipse fuzzy number with matplotlib mixin"""
def __init__(self, **kwargs):
phuzzy.Skewnorm.__init__(self, **kwargs)
16 changes: 16 additions & 0 deletions phuzzy/mpl/plots.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ def plot_xy(x, y, height=100, width=200):

return fig, axs


def plot_xyz(x, y, z, height=70, width=200):
"""plot two fuzzy numbers

Expand Down Expand Up @@ -61,6 +62,7 @@ def plot_xyz(x, y, z, height=70, width=200):

return fig, axs


def plot_xy_3d(x, y, height=200, width=200):
"""plot two fuzzy numbers

Expand Down Expand Up @@ -156,6 +158,7 @@ def plot_3d(x, y, ax=None, show=False, height=200, width=200):

return fig, ax


def plot_hist(x, ax=None, bins=None, normed=1, **kwargs):

if bins is None:
Expand All @@ -179,6 +182,19 @@ def plot_hist(x, ax=None, bins=None, normed=1, **kwargs):

return fig, ax

"""
def plot_bar(x,y,ax=None, **kwargs):

if ax is None:
fig, ax = plt.subplots(1, 1, figsize=(10,5))
else:
fig = plt.gcf()

ax.bar(x,y, label=kwargs.get("label"), color=kwargs.get("color", "r"))

return fig, ax
"""

def plot_cdf(x, method="rossow", ax=None, bins=None, color=None, **kwargs):

df=pd.DataFrame({"x":x})
Expand Down
Loading