# -*- coding: utf-8 -*-
"""
Simple 2D Noisy Beale Loss Function:
((1.5 - u + u * v) ** 2 + X * (2.25 - u + u * v ** 2) ** 2 + y * (2.625 - u + u * v ** 3) ** 2)
where X and Y are normally distributed with mean 1.0 and sigma given by the noise_level (default is 3.0).
"""
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import two_d_input
[docs]class set_up:
"""Simple 2D Noisy Beale Loss Function:
:math:`((1.5 - u + u \cdot v)^2 + X \cdot (2.25 - u + u \cdot v ^ 2) ^ 2 + y \cdot (2.625 - u + u \cdot v ^ 3) ^ 2)`
where X and Y are normally distributed with mean 1.0 and sigma given by the noise_level.
Args:
batch_size (int): Batch size of the data points. Defaults to ``128``.
size (int): Size of the training set. Defaults to ``1000``.
noise_level (float): Noise level of the training set. All training points are sampled from a gaussian distribution with the noise level as the standard deviation. Defaults to ``6.0``.
starting_point (list): Coordinates of the starting point of the optimization process. Defaults to ``[-4.5, 4.5]``.
weight_decay (float): Weight decay factor. In this model there is no weight decay implemented. Defaults to ``None``.
Attributes:
data_loading (deepobs.data_loading): Data loading class for 2D functions, :class:`.two_d_input.data_loading`.
losses (tf.Tensor): Tensor of size ``batch_size`` containing the individual losses per data point.
accuracy (tf.Tensor): Tensor containing the accuracy of the model. As there is no accuracy when the loss function is given directly, we set it to ``0``.
train_init_op (tf.Operation): A TensorFlow operation to be performed before starting every training epoch.
train_eval_init_op (tf.Operation): A TensorFlow operation to be performed before starting every training eval epoch.
test_init_op (tf.Operation): A TensorFlow operation to be performed before starting every test evaluation phase.
"""
def __init__(self, batch_size=128, size=1000, noise_level=6, starting_point=[-4.5, 4.5], weight_decay=None):
"""Initializes the problem set_up class.
Args:
batch_size (int): Batch size of the data points. Defaults to ``128``.
size (int): Size of the training set. Defaults to ``1000``.
noise_level (float): Noise level of the training set. All training points are sampled from a gaussian distribution with the noise level as the standard deviation. Defaults to ``6``.
starting_point (list): Coordinates of the starting point of the optimization process. Defaults to ``[-4.5, 4.5]``.
weight_decay (float): Weight decay factor. In this model there is no weight decay implemented. Defaults to ``None``.
"""
self.data_loading = two_d_input.data_loading(batch_size=batch_size, train_size=size, noise_level=noise_level)
self.losses, self.accuracy = self.set_up(starting_point=starting_point, weight_decay=weight_decay)
# Operations to do when switching the phase (the one defined in data_loading initializes the iterator and assigns the phase variable, here you can add more operations)
self.train_init_op = tf.group([self.data_loading.train_init_op])
self.train_eval_init_op = tf.group([self.data_loading.train_eval_init_op])
self.test_init_op = tf.group([self.data_loading.test_init_op])
[docs] def get(self):
"""Returns the losses and the accuray of the model.
Returns:
tupel: Tupel consisting of the losses and the accuracy.
"""
return self.losses, self.accuracy
[docs] def set_up(self, starting_point=[-4.5, 4.5], weight_decay=None):
"""Sets up the test problem.
Args:
starting_point (list): Coordinates of the starting point of the optimization process. Defaults to ``[-4.5, 4.5]``.
weight_decay (float): Weight decay factor. In this model there is no weight decay implemented. Defaults to ``None``.
Returns:
tupel: Tupel consisting of the losses and the accuracy.
"""
if weight_decay is not None:
print "WARNING: Weight decay is non-zero but no weight decay is used for this model."
X, y, phase = self.data_loading.load()
# Set model weights
u = tf.get_variable("weight", shape=(), initializer=tf.constant_initializer(starting_point[0]))
v = tf.get_variable("bias", shape=(), initializer=tf.constant_initializer(starting_point[1]))
losses = ((1.5 - u + u * v) ** 2 + X * (2.25 - u + u * v ** 2) ** 2 + y * (2.625 - u + u * v ** 3) ** 2)
# There is no accuracy here but keep it, so code can be reused
accuracy = tf.zeros([1, 1], tf.float32)
return losses, accuracy
[docs] def beale(self, u, v):
"""Deterministic version of Beale function.
Args:
u (float): Coordinate of the first parameter.
v (float): Coordinate of the second parameter.
Returns:
float: Function value of the deterministic Beale function at ``(u,v)``.
"""
return ((1.5 - u + u * v) ** 2 + (2.25 - u + u * v ** 2) ** 2 + (2.625 - u + u * v ** 3) ** 2)
[docs] def plot_run(self, u_history, v_history, loss_history):
"""Plot the history of weights (u, v) and the corresponding loss of an optimizer. Plot the Deterministic Beale as well.
Args:
u_history (list): List of ``u`` values (first parameter) as passed by the optimizer.
v_history (list): List of ``v`` values (second parameter) as passed by the optimizer.
loss_history (list): List of ``loss`` values as passed by the optimizer. Could be train or test loss.
Returns:
fig: Plot with the deterministic beale and the optimizers trajectory.
"""
# meshgrid
traj_box = [[min(u_history), max(u_history)], [
min(v_history), max(v_history)]]
plot_limits = [[min(-5, traj_box[0][0]), max(5, traj_box[0][1])],
[min(-5, traj_box[1][0]), max(5, traj_box[1][1])]]
u_linsp = np.linspace(plot_limits[0][0], plot_limits[0][1], 20)
v_linsp = np.linspace(plot_limits[1][0], plot_limits[1][1], 20)
u_MG, v_MG = np.meshgrid(u_linsp, v_linsp)
zs = np.array([self.beale(u, v)
for u, v in zip(np.ravel(u_MG), np.ravel(v_MG))])
Z = zs.reshape(u_MG.shape)
fig = plt.figure(figsize=(10, 6))
ax = fig.add_subplot(111, projection='3d')
ax.plot_surface(u_MG, v_MG, Z, rstride=1, cstride=1,
color='b', alpha=0.2, linewidth=0)
ax.contour(u_MG, v_MG, Z, 20, alpha=0.5, offset=0, stride=30)
# Highlight Minimum
ax.scatter(3, 0.5, 0.0, 'r*', marker='*', s=200)
ax.set_xlabel('u')
ax.set_ylabel('v')
ax.set_zlabel('Loss')
ax.view_init(elev=30., azim=30)
ax.plot(u_history, v_history, loss_history, markerfacecolor='r',
markeredgecolor='r', marker='.', markersize=1)
ax.plot(u_history, v_history, markerfacecolor='r',
markeredgecolor='r', marker='.', markersize=2)
return fig
[docs] def anim_run(self, u_history, v_history, loss_history, name="Optimizer Trajectory"):
"""Animate the history of weights (u, v) and the corresponding loss of an optimizer. Plot the deterministic Beale as well.
Args:
u_history (list): List of ``u`` values (first parameter) as passed by the optimizer.
v_history (list): List of ``v`` values (second parameter) as passed by the optimizer.
loss_history (list): List of ``loss`` values as passed by the optimizer. Could be train or test loss.
name (str): Name of the optimizer. Defaults to "Optimizer Trajectory".
Returns:
matplotlib.animation.FuncAnimation: Animation object showing the optimizer's trajectory per iteration.
"""
# meshgrid
traj_box = [[min(u_history), max(u_history)], [
min(v_history), max(v_history)]]
plot_limits = [[min(-5, traj_box[0][0]), max(5, traj_box[0][1])],
[min(-5, traj_box[1][0]), max(5, traj_box[1][1])]]
u_linsp = np.linspace(plot_limits[0][0], plot_limits[0][1], 20)
v_linsp = np.linspace(plot_limits[1][0], plot_limits[1][1], 20)
u_MG, v_MG = np.meshgrid(u_linsp, v_linsp)
zs = np.array([self.beale(u, v)
for u, v in zip(np.ravel(u_MG), np.ravel(v_MG))])
Z = zs.reshape(u_MG.shape)
fig = plt.figure(figsize=(10, 6))
ax = fig.add_subplot(111, projection='3d')
ax.plot_surface(u_MG, v_MG, Z, rstride=1, cstride=1,
color='b', alpha=0.2, linewidth=0)
ax.contour(u_MG, v_MG, Z, 20, alpha=0.5, offset=0, stride=30)
# Highlight Minimum
ax.scatter(3, 0.5, 0.0, 'r*', marker='*', s=200)
# Create animation
line, = ax.plot([], [], [], 'r-', label=name, lw=1.5)
point, = ax.plot([], [], [], 'bo')
display_value = ax.text(2., 2., 27.5, '', transform=ax.transAxes)
def init():
line.set_data([], [])
line.set_3d_properties([])
point.set_data([], [])
point.set_3d_properties([])
display_value.set_text('')
return line, point, display_value
def animate(i):
# Animate line
line.set_data(u_history[:i], v_history[:i])
line.set_3d_properties(loss_history[:i])
# Animate points
point.set_data(u_history[i], v_history[i])
point.set_3d_properties(loss_history[i])
# Animate display value
display_value.set_text('Current Loss = ' + str(
loss_history[i]) + ' at iteration: ' + str(i) + ' / ' + str(len(loss_history) - 1))
return line, point, display_value
ax.legend(loc=1)
anim = animation.FuncAnimation(fig, animate, init_func=init,
frames=len(u_history), interval=120,
repeat_delay=60, blit=True)
return anim