|
@@ -9,49 +9,78 @@ The class SimpleGan is a simple standard Generative Adversarial Network.
|
|
|
|
|
|
|
|
|
|
|
|
|
import numpy as np
|
|
import numpy as np
|
|
|
-import tensorflow as tf
|
|
|
|
|
|
|
+import math
|
|
|
|
|
|
|
|
from library.interfaces import GanBaseClass
|
|
from library.interfaces import GanBaseClass
|
|
|
|
|
|
|
|
|
|
+def square(x):
|
|
|
|
|
+ return (x*x)
|
|
|
|
|
+
|
|
|
|
|
+def fold0(f, xs):
|
|
|
|
|
+ if xs == []:
|
|
|
|
|
+ return None
|
|
|
|
|
+
|
|
|
|
|
+ s = xs[0]
|
|
|
|
|
+ for x in xs[1:]:
|
|
|
|
|
+ s = f(s, x)
|
|
|
|
|
+ return s
|
|
|
|
|
+
|
|
|
|
|
+def fold1(f, s0, xs):
|
|
|
|
|
+ if xs == []:
|
|
|
|
|
+ return None
|
|
|
|
|
+
|
|
|
|
|
+ s = s0
|
|
|
|
|
+ for x in xs:
|
|
|
|
|
+ s = f(s, x)
|
|
|
|
|
+ return s
|
|
|
|
|
|
|
|
def dist(x, y):
|
|
def dist(x, y):
|
|
|
- return tf.sqrt(tf.reduce_sum(tf.square(x - y)))
|
|
|
|
|
|
|
+ return math.sqrt(fold1(lambda s, a: s + square(a[0] - a[1]), 0, list(zip(x, y))))
|
|
|
|
|
|
|
|
def minDistPointToSet(x, setB):
|
|
def minDistPointToSet(x, setB):
|
|
|
- m = None
|
|
|
|
|
- for y in setB:
|
|
|
|
|
- d = dist(x,y)
|
|
|
|
|
- if m is None or m > d:
|
|
|
|
|
- m = d
|
|
|
|
|
- return m
|
|
|
|
|
|
|
+ return fold0(lambda m,y: min(m,y), [dist(x,y) for y in setB])
|
|
|
|
|
|
|
|
def minDistSetToSet(setA, setB):
|
|
def minDistSetToSet(setA, setB):
|
|
|
- m = None
|
|
|
|
|
- for x in setA:
|
|
|
|
|
- d = minDistPointToSet(x,setB)
|
|
|
|
|
- if m is None or m > d:
|
|
|
|
|
- m = d
|
|
|
|
|
- return m
|
|
|
|
|
|
|
+ return fold0(lambda m,x: min(m, minDistPointToSet(x,setB)), setA)
|
|
|
|
|
+
|
|
|
|
|
+def normInf(xs):
|
|
|
|
|
+ return fold0(lambda m, x: max(m, abs(x)), xs)
|
|
|
|
|
+
|
|
|
|
|
+def norm2Sq(xs):
|
|
|
|
|
+ return fold0(lambda s, x: s + (x*x), xs)
|
|
|
|
|
+
|
|
|
|
|
+def norm2(xs):
|
|
|
|
|
+ return math.sqrt(norm2Sq(xs))
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+def minmax(xs):
|
|
|
|
|
+ if xs == []:
|
|
|
|
|
+ return None
|
|
|
|
|
+
|
|
|
|
|
+ (mi, mx) = (xs[0][1], xs[0][1])
|
|
|
|
|
+ for x in xs[1:]:
|
|
|
|
|
+ mi = min(mi, x[1])
|
|
|
|
|
+ mx = max(mx, x[1])
|
|
|
|
|
+ return (mi, mx)
|
|
|
|
|
+
|
|
|
|
|
|
|
|
def createSquare(pointCount, noiseSize):
|
|
def createSquare(pointCount, noiseSize):
|
|
|
- noise = []
|
|
|
|
|
- while len(noise) < pointCount:
|
|
|
|
|
- nPointsToAdd = max(100, pointCount - len(noise))
|
|
|
|
|
- noiseDimension = [nPointsToAdd, noiseSize]
|
|
|
|
|
- noise.extend(list(filter(
|
|
|
|
|
- lambda x: tf.reduce_max(tf.square(x)) < 1,
|
|
|
|
|
- np.random.normal(0, 1, noiseDimension))))
|
|
|
|
|
- return np.array(noise[0:pointCount])
|
|
|
|
|
|
|
+ noise = [
|
|
|
|
|
+ [np.random.uniform(-1.0, 1.0) for n in range(noiseSize)]
|
|
|
|
|
+ for m in range(pointCount)
|
|
|
|
|
+ ]
|
|
|
|
|
+ return np.array(noise)
|
|
|
|
|
|
|
|
def createDisc(pointCount, noiseSize):
|
|
def createDisc(pointCount, noiseSize):
|
|
|
noise = []
|
|
noise = []
|
|
|
- while len(noise) < pointCount:
|
|
|
|
|
- nPointsToAdd = max(100, pointCount - len(noise))
|
|
|
|
|
- noiseDimension = [nPointsToAdd, noiseSize]
|
|
|
|
|
- noise.extend(list(filter(
|
|
|
|
|
- lambda x: tf.reduce_sum(tf.square(x)) < 1,
|
|
|
|
|
- np.random.normal(0, 1, noiseDimension))))
|
|
|
|
|
- return np.array(noise[0:pointCount])
|
|
|
|
|
|
|
+ for n in range(pointCount):
|
|
|
|
|
+ p = [np.random.uniform(-1.0, 1.0)]
|
|
|
|
|
+ for m in range(noiseSize - 1):
|
|
|
|
|
+ d = norm2Sq(p)
|
|
|
|
|
+ d = math.sqrt(1.0 - d)
|
|
|
|
|
+ p.append(np.random.uniform(0.0 - d, d))
|
|
|
|
|
+ noise.append(p)
|
|
|
|
|
+ return np.array(noise)
|
|
|
|
|
|
|
|
class SpheredNoise(GanBaseClass):
|
|
class SpheredNoise(GanBaseClass):
|
|
|
"""
|
|
"""
|
|
@@ -71,6 +100,7 @@ class SpheredNoise(GanBaseClass):
|
|
|
self.nextId = 0
|
|
self.nextId = 0
|
|
|
self.numPoints = 0
|
|
self.numPoints = 0
|
|
|
self.nextDiscPoint = 0
|
|
self.nextDiscPoint = 0
|
|
|
|
|
+ self.minDist = 0.0
|
|
|
|
|
|
|
|
def train(self, dataset):
|
|
def train(self, dataset):
|
|
|
majoritySet = dataset.data0
|
|
majoritySet = dataset.data0
|
|
@@ -78,30 +108,30 @@ class SpheredNoise(GanBaseClass):
|
|
|
trainDataSize = minoritySet.shape[0]
|
|
trainDataSize = minoritySet.shape[0]
|
|
|
numOfFeatures = minoritySet.shape[1]
|
|
numOfFeatures = minoritySet.shape[1]
|
|
|
|
|
|
|
|
|
|
+ print(f"Train {majoritySet.shape[0]}/{trainDataSize} points")
|
|
|
|
|
+
|
|
|
if minoritySet.shape[0] <= 0 or majoritySet.shape[0] <= 0:
|
|
if minoritySet.shape[0] <= 0 or majoritySet.shape[0] <= 0:
|
|
|
raise AttributeError("Train: Expected each data class to contain at least one point.")
|
|
raise AttributeError("Train: Expected each data class to contain at least one point.")
|
|
|
|
|
|
|
|
if numOfFeatures <= 0:
|
|
if numOfFeatures <= 0:
|
|
|
raise AttributeError("Train: Expected at least one feature.")
|
|
raise AttributeError("Train: Expected at least one feature.")
|
|
|
|
|
|
|
|
|
|
+ print("-> new disc")
|
|
|
self.disc = createDisc(self.noiseSize, minoritySet.shape[1])
|
|
self.disc = createDisc(self.noiseSize, minoritySet.shape[1])
|
|
|
- self.pointDists = [(x, minDistPointToSet(x, majoritySet)) for x in minoritySet]
|
|
|
|
|
|
|
+ print("-> calc distances")
|
|
|
|
|
+ self.pointDists = list(filter(lambda x: x[1] > 0.0, [(x, minDistPointToSet(x, majoritySet)) for x in minoritySet]))
|
|
|
|
|
+ print("-> statistics")
|
|
|
self.nextId = 0
|
|
self.nextId = 0
|
|
|
self.numPoints = len(self.pointDists)
|
|
self.numPoints = len(self.pointDists)
|
|
|
self.isTrained = True
|
|
self.isTrained = True
|
|
|
- minD = None
|
|
|
|
|
- maxD = None
|
|
|
|
|
- for (x, d) in self.pointDists:
|
|
|
|
|
- if minD is None or minD > d:
|
|
|
|
|
- minD = d
|
|
|
|
|
- if maxD is None or maxD < d:
|
|
|
|
|
- maxD = d
|
|
|
|
|
|
|
+ (minD, maxD) = minmax(self.pointDists)
|
|
|
|
|
+ self.minDist = minD
|
|
|
print(f"trained {trainDataSize} points min:{minD} max:{maxD}")
|
|
print(f"trained {trainDataSize} points min:{minD} max:{maxD}")
|
|
|
|
|
|
|
|
def generateDataPoint(self):
|
|
def generateDataPoint(self):
|
|
|
(x, d) = self.pointDists[self.nextId]
|
|
(x, d) = self.pointDists[self.nextId]
|
|
|
self.nextId = (self.nextId + 1) % self.numPoints
|
|
self.nextId = (self.nextId + 1) % self.numPoints
|
|
|
- disc = (0.5 * d) * self.disc
|
|
|
|
|
|
|
+ disc = (0.5 * self.minDist) * self.disc
|
|
|
p = disc[self.nextDiscPoint]
|
|
p = disc[self.nextDiscPoint]
|
|
|
self.nextDiscPoint = (self.nextDiscPoint + 1) % disc.shape[0]
|
|
self.nextDiscPoint = (self.nextDiscPoint + 1) % disc.shape[0]
|
|
|
return p
|
|
return p
|