This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def fn(x): | |
return x**2 + 0.2*(x-2)**5 + 2*x**3 | |
# initialization | |
x = Variable(3.) | |
target = 42. | |
print('---- Initial Value ----') | |
print('fn(x): {}'.format(fn(x))) | |
print('Target: {}'.format(target)) | |
print('intial guess for x: {}'.format(x)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def forward_fn(x): | |
for n in range(5): | |
if n % 2 == 0: | |
x = 3.*x | |
else: | |
x = x**(1./n) + 1./n | |
return x | |
x = Variable(2.) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
for x in [-1., 0.5, 3.]: | |
print('Function Input: {}'.format(x)) | |
print('Function Value: {}'.format(super_complicated_function(x))) | |
print('Function Symbolic Derivative: {}'.format(d_super_complicated_function(x))) | |
x_v = Variable(x) | |
L = super_complicated_function(x_v) | |
print('Variable Function Output Value: {}'.format(L)) | |
L.backward() | |
print('Input value: {}'.format(x_v)) | |
print('-'*32) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def __add__(self, other): | |
if isinstance(other, self.__class__): | |
return Variable(lambda a,b : a+b, (self, other)) | |
else: | |
return Variable(lambda a,b : a+b, (self, Variable(other))) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def backward(self, output_gradient=1.): | |
# combine gradients from other paths and propagate to children | |
self.gradient += output_gradient | |
local_gradient = self.derivative_op(*self.calc_input_values()) | |
for differential, input_variable in zip(local_gradient, self.input_variables): | |
input_variable.backward(differential * output_gradient) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def calc_input_values(self): | |
# calculate the real-valued input to operation | |
return [v.value for v in self.input_variables] | |
def forward(self): | |
# calculate the real-valued output of operation | |
return self.forward_op(*self.calc_input_values()) | |
@property | |
def value(self): |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Variable: | |
def __init__(self, operation, input_variables=[]): | |
# note the setter for @property value below | |
self.value = operation | |
self.input_variables = input_variables | |
self.gradient = 0. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# compose a graph of nodes | |
x = Variable(10.01) | |
y = Variable(0.05) | |
z = x * y | |
m = 1.3 | |
q = m+y | |
L = (q - (z**(m/2.) + z**2. - 1./z))**2 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def create_diff_fn(fn): | |
def diff_fn(*argv): | |
jacobian = [] | |
Dual_arguments = [Dual(x, 0.) for x in argv] | |
for input_arg in Dual_arguments: | |
input_arg.derivative = 1. | |
result = fn(*Dual_arguments) | |
jacobian.append(result.derivative) | |
input_arg.derivative = 0. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
def super_complicated_function(x): | |
return x * sin(x+6.)**2. / 2. - 2. / 2.**x | |
# symbolic derivative by running the above in mathematica (wolfram alpha) | |
def d_super_complicated_function(x): | |
return 2**(1 - x) * math.log(2) + 0.5 * sin(x + 6)**2 + x * math.sin(x + 6) * math.cos(x + 6) | |
for x in [-1., 0.5, 3., 2.]: | |
print('Function Input: {}'.format(x)) | |
print('Function Value: {}'.format(super_complicated_function(x))) |
NewerOlder