Code snippets for page Gradient Descent and the Newton MethodΒΆ
Download gradnewton.py
.
Browse the code snippet index.
# -*- coding: utf-8 -*-
# Generated by codesnippet sphinx extension on 2020-12-16
import mdp
import numpy as np
np.random.seed(0)
import bimdp
class NewtonNode(bimdp.nodes.IdentityBiNode):
"""Node to implement gradient descent with the Newton method.
:param sender_id: id of the SenderBiNode that is at the front of
the flow, or at the point where the x value should be optimized.
"""
def __init__(self, sender_id, **kwargs):
self.sender_id = sender_id
super(NewtonNode, self).__init__(**kwargs)
@bimdp.binode_coroutine(["grad", "msg_x", "msg"])
def _newton(self, y_goal, n_iterations, x_start, msg):
"""Try to reach the given y value with gradient descent.
The Newton method is used to calculate the next point.
"""
# can't use function decorator, since this is a coroutine
with mdp.extension("gradient"):
# get the y value for the output
msg = {self.node_id + "->method": "newton", "method": "gradient"}
y, grad, x, _ = yield x_start, msg.copy(), self.sender_id
for _ in xrange(n_iterations):
# use Newton's method to get the new data point
error = np.sum((y - y_goal) ** 2, axis=1)
error_grad = np.sum(2 * (y - y_goal)[:,:,np.newaxis] * grad,
axis=1)
err_grad_norm = np.sqrt(np.sum(error_grad**2, axis=1))
unit_error_grad = error_grad / err_grad_norm[:,np.newaxis]
# x_{n+1} = x_n - f(x_n) / f'(x_n)
x = x - (error / err_grad_norm)[:,np.newaxis] * unit_error_grad
y, grad, x, _ = yield x, msg.copy(), self.sender_id
raise StopIteration(x, None, "exit")
n_iterations = 3
show_inspection = True
sfa_node = bimdp.nodes.SFA2BiNode(input_dim=4*4, output_dim=5)
switchboard = bimdp.hinet.Rectangular2dBiSwitchboard(
in_channels_xy=8,
field_channels_xy=4,
field_spacing_xy=2)
flownode = bimdp.hinet.BiFlowNode(bimdp.BiFlow([sfa_node]))
sfa_layer = bimdp.hinet.CloneBiLayer(flownode,
switchboard.output_channels)
flow = bimdp.BiFlow([switchboard, sfa_layer])
train_data = [np.random.random((10, switchboard.input_dim))
for _ in range(3)]
flow.train([None, train_data])
sender_node = bimdp.nodes.SenderBiNode(node_id="sender", recipient_id="newton")
newton_node = NewtonNode(sender_id="sender", input_dim=sfa_layer.output_dim,
node_id="newton")
flow = sender_node + flow + newton_node
x_goal = np.random.random((2, switchboard.input_dim))
goal_y, msg = flow.execute(x_goal)
x_start = np.random.random((2, switchboard.input_dim))
y_start, _ = flow.execute(x_start)
msg = {"method": "newton", "n_iterations": n_iterations, "x_start": x_start}
if show_inspection:
_, (x, msg) = bimdp.show_execution(flow, x=goal_y, msg=msg, target="newton")
else:
x, msg = flow.execute(goal_y, msg, "newton")
y, _ = flow.execute(x)
print ("errors before optimization: %s" %
np.sum((y_start - goal_y)**2, axis=1))
# Expected:
## errors before optimization: [ 196.49202899 241.31524993]
print ("errors after optimization : %s" %
np.sum((y - goal_y)**2, axis=1))
# Expected:
## errors after optimization : [ 39.01372025 34.84160123]