import math, random
import numpy as np
[docs]class Bidirectional:
"""
Calculates perturbations for positive and negative changes.
:type delta: float
:param delta: Percetage of positive and negative change as 1+delta or 1-delta
:rtype: 4d array
:return: Both of perturbated arrays
"""
def __init__(self, delta=0.1):
self.delta = delta
def apply(self, x, row, col, window, bias):
x2 = x.copy()
x[0, row:row+window[0], col:col+window[1], 0] = (x[0, row:row+window[0], col:col+window[1], 0] + bias) * (1 + self.delta)
x2[0, row:row+window[0], col:col+window[1], 0] = (x2[0, row:row+window[0], col:col+window[1], 0] + bias) * (1 - self.delta)
return x, x2
[docs]class Positive:
"""
Applies a positive perturbation to the input array.
:type delta: float
:param delta: Percentage of positive change as 1+delta
:rtype: 4d array
:return: Perturbated array
"""
def __init__(self, delta=0.1):
self.delta = delta
def apply(self, x, row, col, window, bias):
x[0, row:row+window[0], col:col+window[1], 0] = (x[0, row:row+window[0], col:col+window[1], 0] + bias) * (1 + self.delta)
return x, None
[docs]class Negative:
"""
Applies a negative perturbation to the input array.
:type delta: float
:param delta: Percentage of negative change as 1-delta
:rtype: 4d array
:return: Perturbated array
"""
def __init__(self, delta=0.1):
self.delta = delta
def apply(self, x, row, col, window, bias):
x[0, row:row+window[0], col:col+window[1], 0] = (x[0, row:row+window[0], col:col+window[1], 0] + bias) * (1 - self.delta)
return x, None
[docs]class Log:
"""
Applies a logarithmic perturbation to the input array.
:type base: int
:param base: The base of the logarithm.
:rtype: 4d array
:return: Perturbated array
"""
def __init__(self, base=10):
self.base = base
def apply(self, x, row, col, window, bias):
x[0, row:row+window[0], col:col+window[1], 0] = math.log(x[0, row:row+window[0], col:col+window[1], 0] + bias, self.base)
return x, None
[docs]class RandomPtn:
"""
Applies a random perturbation to the input array.
:type r: tuple
:param r: The range of random values for perturbation.
:rtype: 4d array
:return: Perturbated array
"""
def __init__(self, r=(0, 1)):
self.r = r
def apply(self, x, row, col, window, bias):
x[0, row:row+window[0], col:col+window[1], 0] = (x[0, row:row+window[0], col:col+window[1], 0] + bias) * random.uniform(self.r[0], self.r[1])
return x, None
[docs]class Exp:
"""
Applies an exponential perturbation to the input array.
:type exp: float
:param exp: The exponent for the perturbation.
:rtype: 4d array
:return: Perturbated array
"""
def __init__(self, exp=2):
self.exp = exp
def apply(self, x, row, col, window, bias):
x[0, row:row+window[0], col:col+window[1], 0] = (x[0, row:row+window[0], col:col+window[1], 0] + bias) ** self.exp
return x, None
[docs]class Binary:
"""
Applies a binary perturbation to the input array based on a threshold.
:type th: float
:param th: Threshold value for binary perturbation.
:type upper: float
:param upper: Value to set if input is above the threshold.
:type lower: float
:param lower: Value to set if input is below the threshold.
:rtype: 4d array
:return: Perturbated array
"""
def __init__(self, th=0, upper=1, lower=0):
self.th = th
self.upper = upper
self.lower = lower
def apply(self, x, row, col, window, bias):
if np.all(x[0, row, col, 0]) > self.th:
x[0, row:row+window[0], col:col+window[1], 0] = self.upper
else:
x[0, row:row+window[0], col:col+window[1], 0] = self.lower
return x, None
[docs]class Sinusoidal:
"""
Applies a sinusoidal perturbation to the input array.
:type freq: float
:param freq: Frequency of the sine wave.
:type amp: float
:param amp: Amplitude of the sine wave.
:rtype: 4d array
:return: Perturbated array
"""
def __init__(self, freq=30, amp=1):
self.freq = freq
self.amp = amp
def apply(self, x, row, col, window, bias):
x[0, row:row+window[0], col:col+window[1], 0] = (x[0, row:row+window[0], col:col+window[1], 0] + bias) * math.sin(self.freq * x[0, row:row+window[0], col:col+window[1], 0]) + self.amp
return x, None
[docs]class Gaussian:
"""
Applies a Gaussian perturbation to the input array.
:type mean: float
:param mean: Mean of the Gaussian distribution.
:type stdv: float
:param stdv: Standard deviation of the Gaussian distribution.
:rtype: 4d array
:return: Perturbated array
"""
def __init__(self, mean=1, stdv=1):
self.mean = mean
self.stdv = stdv
def apply(self, x, row, col, window, bias):
x[0, row:row+window[0], col:col+window[1], 0] = (x[0, row:row+window[0], col:col+window[1], 0] + bias) * math.exp(-((x[0, row:row+window[0], col:col+window[1], 0] - self.mean) ** 2) / (2 * self.stdv ** 2))
return x, None
[docs]class Tanh:
"""
Applies a hyperbolic tangent perturbation to the input array.
:type sf: float
:param sf: Scale factor to apply before the tanh function.
:rtype: 4d array
:return: Perturbated array
"""
def __init__(self, sf=1):
self.sf = sf # scale factor
def apply(self, x, row, col, window, bias):
x[0, row:row+window[0], col:col+window[1], 0] = math.tanh(self.sf * (x[0, row:row+window[0], col:col+window[1], 0] + bias))
return x, None
[docs]class Sigmoid:
"""
Applies a sigmoid perturbation to the input array.
:type sf: float
:param sf: Scale factor to apply before the sigmoid function.
:rtype: 4d array
:return: Perturbated array
"""
def __init__(self, sf=1):
self.sf = sf
def apply(self, x, row, col, window, bias):
x[0, row:row+window[0], col:col+window[1], 0] = 1 / (1 + math.exp(-self.sf * (x[0, row:row+window[0], col:col+window[1], 0] + bias)))
return x, None
[docs]class ReLU:
"""
Applies a Rectified Linear Unit (ReLU) perturbation to the input array.
:rtype: 4d array
:return: Perturbated array
"""
def apply(self, x, row, col, window, bias):
x[0, row:row+window[0], col:col+window[1], 0] = max(0, x[0, row:row+window[0], col:col+window[1], 0] + bias)
return x, None
[docs]class LeakyReLU:
"""
Applies a Leaky Rectified Linear Unit (LeakyReLU) perturbation to the input array.
:type alpha: float
:param alpha: Coefficient for negative inputs in LeakyReLU.
:rtype: 4d array
:return: Perturbated array
"""
def __init__(self, alpha=1):
self.alpha = alpha
def apply(self, x, row, col, window, bias):
if x[0, row, col, 0] < 0:
x[0, row:row+window[0], col:col+window[1], 0] = (x[0, row:row+window[0], col:col+window[1], 0] + bias) * self.alpha
return x, None
[docs]class Softplus:
"""
Applies a Softplus perturbation to the input array.
:type sf: float
:param sf: Scale factor to apply before the Softplus function.
:rtype: 4d array
:return: Perturbated array
"""
def __init__(self, sf=1):
self.sf = sf
def apply(self, x, row, col, window, bias):
x[0, row:row+window[0], col:col+window[1], 0] = math.log(1 + math.exp(self.sf * (x[0, row:row+window[0], col:col+window[1], 0] + bias)))
return x, None
[docs]class Inverse:
"""
Applies an inverse perturbation to the input array.
:rtype: 4d array
:return: Perturbated array
"""
def apply(self, x, row, col, window, bias):
x[0, row:row+window[0], col:col+window[1], 0] = (1 / (x[0, row:row+window[0], col:col+window[1], 0] + bias))
return x, None
[docs]class GaussianNoise:
"""
Applies Gaussian noise to the input array.
:type mean: float
:param mean: Mean of the Gaussian distribution.
:type stdv: float
:param stdv: Standard deviation of the Gaussian distribution.
:rtype: 4d array
:return: Perturbated array
"""
def __init__(self, mean=1, stdv=1):
self.mean = mean
self.stdv = stdv
def apply(self, x, row, col, window, bias):
x[0, row:row+window[0], col:col+window[1], 0] = x[0, row:row+window[0], col:col+window[1], 0] + bias + random.gauss(self.mean, self.stdv)
return x, None
[docs]class Offset:
"""
Applies an offset to the input array.
:type offset: float
:param offset: The value to be added to the input array.
:rtype: 4d array
:return: Perturbated array
"""
def __init__(self, offset=1):
self.offset = offset
def apply(self, x, row, col, window, bias):
x[0, row:row+window[0], col:col+window[1], 0] = x[0, row:row+window[0], col:col+window[1], 0] + bias + self.offset
return x, None
[docs]class Constant:
"""
Replaces all values in the input array with a constant.
:type c: float
:param c: The constant value.
:rtype: 4d array
:return: Perturbated array
"""
def __init__(self, c=0):
self.c = c
def apply(self, x, row, col, window, bias):
x[0, row:row+window[0], col:col+window[1], 0] = self.c
return x, None
[docs]class Custom:
"""
Applies a custom function as a perturbation to the array.
:type func: callable
:param func: A function that takes a single argument and returns a single value.
:rtype: 4d array
:return: Custom perturbated array
"""
def __init__(self, custom):
self.custom = custom
def apply(self, x, row, col, window, bias):
x[0, row:row+window[0], col:col+window[1], 0] = x[0, row:row+window[0], col:col+window[1], 0]*self.custom[0, row:row+window[0], col:col+window[1], 0]
return x, None
[docs]class UpperThreshold:
"""
Sets values above a certain threshold to a specified value.
:type threshold: float
:param threshold: Threshold above which values will be set to a specific value.
:type value: float
:param value: Value to which entries above the threshold will be set.
:rtype: 4d array
:return: Array with upper threshold applied
"""
def __init__(self, th=0, c=0):
self.th = th
self.c = c
def apply(self, x, row, col, window, bias):
if x[0, row, col, 0] <= self.th:
x[0, row:row+window[0], col:col+window[1], 0] = self.c
return x, None
[docs]class LowerThreshold:
"""
Sets values below a certain threshold to a specified value.
:type threshold: float
:param threshold: Threshold below which values will be set to a specific value.
:type value: float
:param value: Value to which entries below the threshold will be set.
:rtype: 4d array
:return: Array with lower threshold applied
"""
def __init__(self, th=0, c=0):
self.th = th
self.c = c
def apply(self, x, row, col, window, bias):
if x[0, row, col, 0] >= self.th:
x[0, row:row+window[0], col:col+window[1], 0] = self.c
return x, None