Add subtractive clustering technique as partitioning method
This commit is contained in:
parent
039dca9d5d
commit
00da89d806
96
pyFTS/partitioners/SubClust.py
Normal file
96
pyFTS/partitioners/SubClust.py
Normal file
@ -0,0 +1,96 @@
|
||||
"""
|
||||
Chiu, Stephen L. "Fuzzy model identification based on cluster estimation." Journal of Intelligent & fuzzy systems 2.3 (1994): 267-278.
|
||||
"""
|
||||
|
||||
import numpy as np
|
||||
import math
|
||||
import random as rnd
|
||||
import functools, operator
|
||||
from pyFTS.common import FuzzySet, Membership
|
||||
from pyFTS.partitioners import partitioner
|
||||
|
||||
|
||||
def imax(vec):
|
||||
i = np.argmax(vec)
|
||||
return (i, vec[i])
|
||||
|
||||
|
||||
def subclust(data, ra, rb, eps_sup, eps_inf):
|
||||
if len(data.shape) == 1:
|
||||
data = np.reshape(data, (data.shape[0], 1))
|
||||
|
||||
centers = np.zeros((0, data.shape[1]))
|
||||
|
||||
# Initial potentials
|
||||
alpha = 4/ra**2
|
||||
beta = 4/rb**2
|
||||
|
||||
pot = np.zeros(data.shape[0])
|
||||
for i in range(data.shape[0]):
|
||||
pot[i] = np.sum(np.exp(-alpha*np.linalg.norm(data - data[i,:], axis=1)**2))
|
||||
|
||||
pot_max_i, pot_max = imax(pot)
|
||||
|
||||
current_pot_max = pot_max
|
||||
while current_pot_max:
|
||||
x_star = data[pot_max_i,:]
|
||||
accept = False
|
||||
if current_pot_max > eps_sup * pot_max:
|
||||
# Accept xk as a cluster center and continue
|
||||
accept = True
|
||||
elif current_pot_max <= eps_inf * pot_max:
|
||||
# Reject xk and end the clustering process
|
||||
break
|
||||
else:
|
||||
d_min = np.min(np.linalg.norm(x_star - centers))
|
||||
if d_min/ra + current_pot_max/pot_max >= 1:
|
||||
accept = True
|
||||
else:
|
||||
pot[pot_max_i] = 0
|
||||
pot_max_i, current_pot_max = imax(pot)
|
||||
if accept:
|
||||
centers = np.vstack((centers, x_star))
|
||||
# Recompute potentials
|
||||
for i in range(data.shape[0]):
|
||||
new_pot = pot[i] - current_pot_max*np.exp(-beta*np.linalg.norm(x_star - data[i,:])**2)
|
||||
new_pot = max(0, new_pot)
|
||||
pot[i] = new_pot
|
||||
pot_max_i, current_pot_max = imax(pot)
|
||||
return centers
|
||||
|
||||
|
||||
class SubClustPartitioner(partitioner.Partitioner):
|
||||
"""SubClust Partitioner"""
|
||||
def __init__(self, **kwargs):
|
||||
self.ra = kwargs.get('ra', 0.8)
|
||||
self.rb = kwargs.get('rb', self.ra * 1.5)
|
||||
self.eps_sup = kwargs.get('eps_sup', 0.5)
|
||||
self.eps_inf = kwargs.get('eps_inf', 0.15)
|
||||
super(SubClustPartitioner, self).__init__(name="SubClust", **kwargs)
|
||||
|
||||
def build(self, data):
|
||||
sets = {}
|
||||
|
||||
kwargs = {'type': self.type, 'variable': self.variable}
|
||||
|
||||
partitions = subclust(data, self.ra, self.rb, self.epssup, self.epsinf)
|
||||
partitions = list(np.reshape(partitions, partitions.shape[0]))
|
||||
partitions.append(self.min)
|
||||
partitions.append(self.max)
|
||||
partitions = list(set(partitions))
|
||||
partitions.sort()
|
||||
self.partitions = len(partitions)
|
||||
for c in np.arange(1, len(partitions)-1):
|
||||
_name = self.get_name(c-1)
|
||||
if self.membership_function == Membership.trimf:
|
||||
sets[_name] = FuzzySet.FuzzySet(_name, Membership.trimf,
|
||||
[partitions[c - 1], partitions[c], partitions[c + 1]],partitions[c], **kwargs)
|
||||
elif self.membership_function == Membership.trapmf:
|
||||
b1 = (partitions[c] - partitions[c - 1])/2
|
||||
b2 = (partitions[c + 1] - partitions[c]) / 2
|
||||
sets[_name] = FuzzySet.FuzzySet(_name, Membership.trapmf,
|
||||
[partitions[c - 1], partitions[c] - b1,
|
||||
partitions[c] + b2, partitions[c + 1]],
|
||||
partitions[c], **kwargs)
|
||||
|
||||
return sets
|
Loading…
Reference in New Issue
Block a user