# Path: deeppy/feed.py
# class Feed(object):
#     def __init__(self, x, batch_size=None, epoch_size=None):
#         self.x = x
#         self.n_samples = x.shape[0]
#         if batch_size is None:
#             batch_size = 128 if self.n_samples > 512 else self.n_samples
#         if epoch_size is None:
#             epoch_size = int(np.ceil(float(self.n_samples) / batch_size))
#         self.epoch_size = epoch_size
#         self.batch_size = batch_size
#         self.epoch_idx = 0
# 
#     @classmethod
#     def from_any(cls, arg):
#         if isinstance(arg, Feed):
#             arg.reset()
#             return arg
#         elif isinstance(arg, np.ndarray):
#             return cls(arg)
#         elif isinstance(arg, ca.ndarray):
#             return cls(np.array(arg))
#         elif isinstance(arg, tuple):
#             return SupervisedFeed(arg[0], arg[1])
#         raise ValueError('Invalid arguments.')
# 
#     def reset(self):
#         self.epoch_idx = 0
# 
#     def _batch_slices(self):
#         for b in range(self.epoch_size):
#             start = (self.epoch_idx * self.epoch_size + b) * self.batch_size
#             start = start % self.n_samples
#             stop = (start + self.batch_size) % self.n_samples
#             yield start, stop
#         self.epoch_idx += 1
# 
#     def batches(self):
#         x = ca.empty(self.x_shape, dtype=self.x.dtype)
#         for start, stop in self._batch_slices():
#             if stop > start:
#                 x_np = self.x[start:stop]
#             else:
#                 x_np = np.concatenate((self.x[start:], self.x[:stop]))
#             ca.copyto(x, x_np)
#             yield x,
# 
#     @property
#     def x_shape(self):
#         return (self.batch_size,) + self.x.shape[1:]
# 
#     @property
#     def shapes(self):
#         return self.x_shape,
# 
# Path: deeppy/parameter.py
# class SharedParameter(Parameter):
#     def __init__(self, parent):
#         self.parent = parent
#         self._tmp_grad_array = None
# 
#     def setup(self, shape):
#         self.parent.setup(shape)
# 
#     def grad(self):
#         raise RuntimeError('SharedParameter should not be requested a grad()')
# 
#     # Wrap parent Parameter methods
#     def __getattr__(self, attr):
#         if attr in self.__dict__:
#             return getattr(self, attr)
#         return getattr(self.parent, attr)
# 
#     # Pickle support
#     def __getstate__(self):
#         return self.parent
# 
#     def __setstate__(self, state):
#         self.parent = state
#         self._tmp_grad_array = None


import time
import numpy as np
import cudarray as ca
import logging
from ..feed import Feed
from ..parameter import SharedParameter
    def train_patience(self, annealer=None, error_fun=None, min_epochs=5,
                       max_epochs=1000, improvement_thresh=0.995,
                       patience_incr=1.5):
        epoch = 0
        converged = False
        patience = min_epochs
        best_score = np.inf
        start_time = time.clock()
        while epoch < max_epochs and not converged:
            epoch += 1
            self.model.phase = 'train'
            self.model.setup(*self.feed.shapes)
            epoch_loss = self.train_epoch()
            if error_fun is None:
                epoch_error = epoch_loss
            else:
                epoch_error = error_fun()
            if epoch_error < best_score:
                improvement = epoch_error / best_score
                if improvement < improvement_thresh:
                    # increase patience on significant improvement
                    patience = max(patience, epoch*patience_incr)
                best_score = epoch_error
            if error_fun is None:
                log.info('epoch %d/%d, loss %f', epoch, patience, epoch_loss)
            else:
                log.info('epoch %d/%d, loss %f, error %.4f', epoch, patience,
                         epoch_loss, epoch_error)
            for param in self.params:
                param.monitor()

# Path: deeppy/feed.py
# class Feed(object):
#     def __init__(self, x, batch_size=None, epoch_size=None):
#         self.x = x
#         self.n_samples = x.shape[0]
#         if batch_size is None:
#             batch_size = 128 if self.n_samples > 512 else self.n_samples
#         if epoch_size is None:
#             epoch_size = int(np.ceil(float(self.n_samples) / batch_size))
#         self.epoch_size = epoch_size
#         self.batch_size = batch_size
#         self.epoch_idx = 0
# 
#     @classmethod
#     def from_any(cls, arg):
#         if isinstance(arg, Feed):
#             arg.reset()
#             return arg
#         elif isinstance(arg, np.ndarray):
#             return cls(arg)
#         elif isinstance(arg, ca.ndarray):
#             return cls(np.array(arg))
#         elif isinstance(arg, tuple):
#             return SupervisedFeed(arg[0], arg[1])
#         raise ValueError('Invalid arguments.')
# 
#     def reset(self):
#         self.epoch_idx = 0
# 
#     def _batch_slices(self):
#         for b in range(self.epoch_size):
#             start = (self.epoch_idx * self.epoch_size + b) * self.batch_size
#             start = start % self.n_samples
#             stop = (start + self.batch_size) % self.n_samples
#             yield start, stop
#         self.epoch_idx += 1
# 
#     def batches(self):
#         x = ca.empty(self.x_shape, dtype=self.x.dtype)
#         for start, stop in self._batch_slices():
#             if stop > start:
#                 x_np = self.x[start:stop]
#             else:
#                 x_np = np.concatenate((self.x[start:], self.x[:stop]))
#             ca.copyto(x, x_np)
#             yield x,
# 
#     @property
#     def x_shape(self):
#         return (self.batch_size,) + self.x.shape[1:]
# 
#     @property
#     def shapes(self):
#         return self.x_shape,
# 
# Path: deeppy/parameter.py
# class SharedParameter(Parameter):
#     def __init__(self, parent):
#         self.parent = parent
#         self._tmp_grad_array = None
# 
#     def setup(self, shape):
#         self.parent.setup(shape)
# 
#     def grad(self):
#         raise RuntimeError('SharedParameter should not be requested a grad()')
# 
#     # Wrap parent Parameter methods
#     def __getattr__(self, attr):
#         if attr in self.__dict__:
#             return getattr(self, attr)
#         return getattr(self.parent, attr)
# 
#     # Pickle support
#     def __getstate__(self):
#         return self.parent
# 
#     def __setstate__(self, state):
#         self.parent = state
#         self._tmp_grad_array = None


# Path: deeppy/train/gradient_descent.py
import time
import numpy as np
import cudarray as ca
import logging
from ..feed import Feed
from ..parameter import SharedParameter

    def train_patience(self, annealer=None, error_fun=None, min_epochs=5,
                       max_epochs=1000, improvement_thresh=0.995,
                       patience_incr=1.5):
        epoch = 0
        converged = False
        patience = min_epochs
        best_score = np.inf
        start_time = time.clock()
        while epoch < max_epochs and not converged:
            epoch += 1
            self.model.phase = 'train'
            self.model.setup(*self.feed.shapes)
            epoch_loss = self.train_epoch()
            if error_fun is None:
                epoch_error = epoch_loss
            else:
                epoch_error = error_fun()
            if epoch_error < best_score:
                improvement = epoch_error / best_score
                if improvement < improvement_thresh:
                    # increase patience on significant improvement
                    patience = max(patience, epoch*patience_incr)
                best_score = epoch_error
            if error_fun is None:
                log.info('epoch %d/%d, loss %f', epoch, patience, epoch_loss)
            else:
                log.info('epoch %d/%d, loss %f, error %.4f', epoch, patience,
                         epoch_loss, epoch_error)
            for param in self.params:
                param.monitor()

            if patience < epoch: