def sqrt(obj): """ Returns the square root of the input object Inputs: obj: Autodiff.Variableiable object or a number Output: Autodiff.Variableiable object or a scalar """ if isinstance(obj, Variable): new_Variable = Variable(obj.val, obj.der) return new_Variable.__pow__(0.5) else: return np.sqrt(obj)
def test_sqrt(): x1 = Variable(1) x2 = fun.sqrt(x1) x3 = 1 assert x2.val == 1 assert x2.der == {'x': 0.5} assert x3 == 1
def arccos(obj): """ Returns the inverse cosine of the input object Inputs: obj: Autodiff.Variable object or a number Output: Autodiff.Variable object or a scalar """ try: pre_der = obj.der pre_val = obj.val if pre_val >= 1 or pre_val <= -1: raise ValueError("arccos does not exist beyond (-1,1)") der = { x: (-(1 - (pre_val)**2)**(-0.5)) * pre_der.get(x, 0) for x in set(pre_der) } val = np.arccos(pre_val) return Variable(val, der=der) except AttributeError: if obj >= 1 or obj <= -1: raise ValueError("arccos does not exist beyond (-1,1)") return np.arccos(obj)
def arccos(obj): """ Returns the inverse cosine of the input object Inputs: obj: Autodiff.Variableiable object or a number Output: Autodiff.Variableiable object """ if isinstance(obj, Variable): values = map(lambda x: -1 <= x <= 1, obj.val) if not all(values): raise ValueError("Domain of arccos is [-1, 1].") val = np.arccos(obj.val) if obj.val == 1: der = np.nan elif obj.val == -1: der = np.nan else: der = -1 / np.sqrt(1 - (obj.val**2)) if len(obj.der.shape) > len(der.shape): der = np.expand_dims(der, 1) der = np.multiply(der, obj.der) return Variable(val, der) else: if obj >= 1 or obj <= -1: raise ValueError("Domain of arccos is [-1, 1].") return np.arccos(obj)
def logistic(obj): """ Return the logistic function evaluation (sigmoid): f(x) = 1 / (1 + e^{-x}) Inputs: obj: Autodiff.Variableiable object or a number Output: Autodiff.Variableiable object or a scalar """ # Case for constant scalar or vector with no derivative if isinstance(obj, Variable): val = 1 / (1 + np.exp(-obj.val)) der = np.exp(obj.val) / ((1 + np.exp(obj.val))**2) if len(obj.der.shape) > 1: new_der = np.reshape(der, [-1, 1]) else: new_der = der final_der = new_der * obj.der return Variable(val, final_der) else: val = 1 / (1 + np.exp(-obj)) return val
def test_exp(): x1 = fun.exp(Variable(1)) # x2 = Variable(1) # x3 = AutoDiff.exp(x1 + x2) x4 = fun.exp(1) assert x1.val == np.exp(1) assert x1.der == {'x': np.exp(1)} # assert x3.der == {'x1': np.exp(1+1), 'x2': np.exp(1+1)} assert x4 == np.exp(1)
def test_inverse_trigonometric(): x1 = fun.arcsin(Variable(0.1)) x2 = fun.arccos(Variable(0.2)) x3 = fun.arctan(Variable(0.3)) # x4 = AutoDiff.arcsin(x1) + AutoDiff.arccos(x2) + AutoDiff.arctan(x3) x5 = 0.1 x6 = 0.2 x7 = 0.3 x8 = fun.arcsin(x5) + fun.arccos(x6) + fun.arctan(x7) assert x1.val == np.arcsin(0.1) assert x2.val == np.arccos(0.2) assert x3.val == np.arctan(0.3) assert x1.der == {'x': 1.005037815259212} assert x2.der == {'x': -1.0206207261596576} assert x3.der == {'x': 0.9174311926605504} # assert x4.val == 1.7610626216439926 # assert x4.der == {'x1': 1.005037815259212, # 'x2': -1.0206207261596576, # 'x3': 0.9174311926605504} assert x8 == 1.7610626216439926
def test_hyberbolic(): x1 = fun.sinh(Variable(1)) x2 = fun.cosh(Variable(1)) x3 = fun.tanh(Variable(1)) # x4 = AutoDiff.sinh(x1) + AutoDiff.cosh(x2) + AutoDiff.tanh(x3) x5 = 1 x6 = 1 x7 = 1 x8 = fun.sinh(x5) + fun.cosh(x6) + fun.tanh(x7) assert x1.val == np.sinh(1) assert x2.val == np.cosh(1) assert x3.val == np.tanh(1) assert x1.der == {'x': np.cosh(1)} assert x2.der == {'x': np.sinh(1)} assert x3.der == {'x': 1 - np.tanh(1)**2} # assert x4.val == np.sinh(1)+np.cosh(1)+np.tanh(1) # assert x4.der == {'x1': np.cosh(1), # 'x2': np.sinh(1), # 'x3': 1-np.tanh(1)**2} assert x8 == np.sinh(1) + np.cosh(1) + np.tanh(1)
def test_log(): x1 = fun.log(Variable(1)) # x2 = Variable(1, name='x2') # x3 = AutoDiff.log(x1 + x2) x4 = fun.log(1) x5 = fun.log2(Variable(1)) x6 = fun.log2(1) x7 = fun.log10(Variable(1)) x8 = fun.log10(1) assert x1.val == np.log(1) assert x1.der == {'x': 1} assert x5.val == np.log2(1) assert x5.der == {'x': 1} assert x7.val == np.log10(1) assert x7.der == {'x': 1} # assert x3.val == np.log(1+1) # assert x3.der == {'x1': 1/2, 'x2': 1/2} assert x4 == np.log(1) assert x6 == np.log2(1) assert x8 == np.log10(1)
def test_trigonometric(): x1 = fun.sin(Variable(np.pi / 4)) x2 = fun.cos(Variable(np.pi / 4)) x3 = fun.tan(Variable(np.pi / 4)) # x4 = AutoDiff.sin(x1) + AutoDiff.cos(x2) + AutoDiff.tan(x3) x5 = np.pi / 4 x6 = np.pi / 4 x7 = np.pi / 4 x8 = fun.sin(x5) + fun.cos(x6) + fun.tan(x7) assert x1.val == np.sin(np.pi / 4) assert x2.val == np.cos(np.pi / 4) assert x3.val == np.tan(np.pi / 4) assert x1.der == {'x': np.cos(np.pi / 4)} assert x2.der == {'x': -np.sin(np.pi / 4)} assert abs(x3.der['x'] - 1 / np.cos(np.pi / 4)**2 < 1e-8) # assert x4.val == 2**0.5 + 1 # assert x4.der == {'x1': np.cos(np.pi/4), # 'x2': -np.sin(np.pi/4), # 'x3': 1/np.cos(np.pi/4)**2} assert x8 == 2**0.5 + 1
def test_error(): try: fun.arcsin(Variable(2)) assert False except ValueError: assert True try: fun.arcsin(Variable(-2)) assert False except ValueError: assert True try: fun.arccos(Variable(2)) assert False except ValueError: assert True try: fun.arccos(Variable(-2)) assert False except ValueError: assert True try: fun.arcsin(2) assert False except ValueError: assert True try: fun.arcsin(-2) assert False except ValueError: assert True try: fun.arccos(2) assert False except ValueError: assert True try: fun.arccos(-2) assert False except ValueError: assert True
def exp(obj): """ Returns e raised to the input object Inputs: obj: Autodiff.Variable object or a number Output: Autodiff.Variable object or a scalar """ try: pre_der = obj.der pre_val = obj.val der = {x: np.exp(pre_val) * pre_der.get(x, 0) for x in set(pre_der)} val = np.exp(pre_val) return Variable(val, der=der) except: return np.exp(obj)
def cosh(obj): """ Returns the hyperbolic cosine of the input object Inputs: obj: Autodiff.Variable object or a number Output: Autodiff.Variable object or a scalar """ try: pre_der = obj.der pre_val = obj.val der = {x: np.sinh(pre_val) * pre_der.get(x, 0) for x in set(pre_der)} val = np.cosh(pre_val) return Variable(val, der=der) except: return np.cosh(obj)
def cosh(obj): """ Returns the hyperbolic cosine of the input object Inputs: obj: Autodiff.Variableiable object or a number Output: Autodiff.Variableiable object """ if isinstance(obj, Variable): val = np.cosh(obj.val) der = np.sinh(obj.val) if len(obj.der.shape) > len(der.shape): der = np.expand_dims(der, 1) der = np.multiply(der, obj.der) return Variable(val, der) else: return np.cosh(obj)
def log10(obj): """ Returns the natrual log of the input object Inputs: obj: Autodiff.Variableiable object or a number Output: Autodiff.Variableiable object """ if isinstance(obj, Variable): val = np.log10(obj.val) der = np.divide(1, obj.val) if len(obj.der.shape) > len(der.shape): der = np.expand_dims(der, 1) der = np.multiply(der, obj.der) return Variable(val, der) else: return np.log10(obj)
def arctan(obj): """ Returns the inverse tangent of the input object Inputs: obj: Autodiff.Variableiable object or a number Output: Autodiff.Variableiable object """ if isinstance(obj, Variable): val = np.arctan(obj.val) der = 1 / (1 + (obj.val)**2) if len(obj.der.shape) > len(der.shape): der = np.expand_dims(der, 1) der = np.multiply(der, obj.der) return Variable(val, der) else: return np.arctan(obj)
def exp(obj): """ Returns e raised to the input object Inputs: obj: Autodiff.Variableiable object or a number Output: Autodiff.Variableiable object or scalar """ if isinstance(obj, Variable): val = np.exp(obj.val) der = np.exp(obj.val) if len(obj.der.shape) > len(der.shape): der = np.expand_dims(der, 1) der = np.multiply(der, obj.der) return Variable(val, der) else: return np.exp(obj)
def log10(obj): """ Returns the natrual log of the input object Inputs: obj: Autodiff.Variable object or a number Output: Autodiff.Variable object or a scalar """ try: pre_der = obj.der pre_val = obj.val der = { x: np.divide(1, pre_val) * pre_der.get(x, 0) for x in set(pre_der) } val = np.log10(pre_val) return Variable(val, der=der) except: return np.log10(obj)
def sqrt(obj): """ Returns the square root of the input object Inputs: obj: Autodiff.Variable object or a number Output: Autodiff.Variable object or a scalar """ try: pre_der = obj.der pre_val = obj.val der = { x: (0.5 * pre_val**(-0.5)) * pre_der.get(x, 0) for x in set(pre_der) } val = np.sqrt(pre_val) return Variable(val, der=der) except: return np.sqrt(obj)
def arctan(obj): """ Returns the inverse tangent of the input object Inputs: obj: Autodiff.Variable object or a number Output: Autodiff.Variable object or a scalar """ try: pre_der = obj.der pre_val = obj.val der = { x: np.divide(1, 1 + (pre_val)**2) * pre_der.get(x, 0) for x in set(pre_der) } val = np.arctan(pre_val) return Variable(val, der=der) except: return np.arctan(obj)
def tanh(obj): """ Returns hyperbolic tangent of the input object Inputs: obj: Autodiff.Variable object or a number Output: Autodiff.Variable object or a scalar """ try: pre_der = obj.der pre_val = obj.val der = { x: (1 - np.tanh(pre_val)**2) * pre_der.get(x, 0) for x in set(pre_der) } val = np.tanh(pre_val) return Variable(val, der=der) except: return np.tanh(obj)