def predict_function(x, y, model):
            self.avg_error = float(model.sum_error) / float(model.i)
            if self.output:
                print "Average error: ", self.avg_error, "\n"

            X_array = np.array(x).reshape(1, len(x))
            y_array = np.array(y).reshape(1, len(y))
            return evaluate_error(X_array, y_array, model.w) ** 0.5
        def predict_function(x, y, model):
            self.avg_error = float(model.sum_error) / float(model.i)
            if self.output:
                print "Average error: ", self.avg_error, "\n"

            X_array = np.array(x).reshape(1, len(x))
            y_array = np.array(y).reshape(1, len(y))
            return evaluate_error(X_array, y_array, model.w)**0.5
            def train_function(x, y, model, window_state):
                if not model:
                    class Model:
                        w = np.zeros((x.shape[1] + 1, 1))
                        sum_error = 0
                        i = 0
                    model = Model()

                model.w = train(x, y, self.draw)
                self.w = model.w
                error = evaluate_error(x, y, model.w)
                if self.output:
                    print "Error: ", error

                model.sum_error += error
                model.i += 1
                return model
            def train_function(x, y, model, window_state):
                if not model:

                    class Model:
                        w = np.zeros((x.shape[1] + 1, 1))
                        sum_error = 0
                        i = 0

                    model = Model()

                model.w = train(x, y, self.draw)
                self.w = model.w
                error = evaluate_error(x, y, model.w)
                if self.output:
                    print "Error: ", error

                model.sum_error += error
                model.i += 1
                return model
            def train_function(x, y, model, window_state):

                step_size = window_state[3]
                current_window_size = window_state[0]
                max_window_size = window_state[4]

                # Initialize model if not initialized
                if not model:
                    class Model:
                        w = np.zeros((x.shape[1] + 1, 1))
                        sum_error = 0
                        i = 0
                        # Use incremental matrix state if data has 1 feature
                        if x.shape[1] == 1:
                            x_sum = 0
                            y_sum = 0
                            xy_sum = 0
                            xx_sum = 0
                    model = Model()

                    # Set incremental matrix state if data has 1 feature
                    if x.shape[1] == 1:
                        model.x_sum = np.sum(x)
                        model.y_sum = np.sum(y)
                        model.xy_sum = np.sum(x * y)
                        model.xx_sum = np.sum(x ** 2)

                # Model is already initialized

                # If data has 1 feature, add last step_size points from
                # sums
                elif x.shape[1] == 1:
                    for i in range(-step_size, 0):
                        x_value = x[i].tolist()[0]
                        y_value = y[i].tolist()[0]
                        model.x_sum += x_value
                        model.y_sum += y_value
                        model.xy_sum += x_value * y_value
                        model.xx_sum += x_value ** 2

                # If data has 1 feature, compute w with incremental matrix
                if x.shape[1] == 1:

                    n = x.shape[0]
                    model.w[1] = (model.xy_sum - model.x_sum * model.y_sum /
                                  float(n)) / (model.xx_sum - model.x_sum *
                                               model.x_sum / float(n))
                    model.w[0] = (model.y_sum/float(n) - model.w[1] *
                                  model.x_sum/float(n))

                    self.w = model.w

                    if self.draw:
                        plot(x, y, model.w)

                    # If the window has not reached steady state and the next
                    # window will be at steady state, remove points to
                    # correctly update the sums
                    if (max_window_size - current_window_size < step_size and
                            not window_state[1]):
                        for i in range(0, step_size - (max_window_size -
                                                       current_window_size)):
                            x_value = x[i].tolist()[0]
                            y_value = y[i].tolist()[0]
                            model.x_sum -= x_value
                            model.y_sum -= y_value
                            model.xy_sum -= x_value * y_value
                            model.xx_sum -= x_value ** 2

                    # If the window has reached steady state, remove the first
                    # step size points from sums
                    if window_state[1]:

                        for i in range(0, step_size):
                            x_value = x[i].tolist()[0]
                            y_value = y[i].tolist()[0]
                            model.x_sum -= x_value
                            model.y_sum -= y_value
                            model.xy_sum -= x_value * y_value
                            model.xx_sum -= x_value ** 2

                # The data has more than 1 feature, train using SGD
                else:
                    model.w = train_sgd(x, y, self.alpha, model.w)
                    if self.draw:
                        plot(x, y, model.w)
                    self.w = model.w
                error = evaluate_error(x, y, model.w)
                if self.output:
                    print "Error: ", error

                model.sum_error += error
                model.i += 1
                return model
            def train_function(x, y, model, window_state):

                step_size = window_state[3]
                current_window_size = window_state[0]
                max_window_size = window_state[4]

                # Initialize model if not initialized
                if not model:

                    class Model:
                        w = np.zeros((x.shape[1] + 1, 1))
                        sum_error = 0
                        i = 0
                        # Use incremental matrix state if data has 1 feature
                        if x.shape[1] == 1:
                            x_sum = 0
                            y_sum = 0
                            xy_sum = 0
                            xx_sum = 0

                    model = Model()

                    # Set incremental matrix state if data has 1 feature
                    if x.shape[1] == 1:
                        model.x_sum = np.sum(x)
                        model.y_sum = np.sum(y)
                        model.xy_sum = np.sum(x * y)
                        model.xx_sum = np.sum(x**2)

                # Model is already initialized

                # If data has 1 feature, add last step_size points from
                # sums
                elif x.shape[1] == 1:
                    for i in range(-step_size, 0):
                        x_value = x[i].tolist()[0]
                        y_value = y[i].tolist()[0]
                        model.x_sum += x_value
                        model.y_sum += y_value
                        model.xy_sum += x_value * y_value
                        model.xx_sum += x_value**2

                # If data has 1 feature, compute w with incremental matrix
                if x.shape[1] == 1:

                    n = x.shape[0]
                    model.w[1] = (
                        model.xy_sum - model.x_sum * model.y_sum / float(n)
                    ) / (model.xx_sum - model.x_sum * model.x_sum / float(n))
                    model.w[0] = (model.y_sum / float(n) -
                                  model.w[1] * model.x_sum / float(n))

                    self.w = model.w

                    if self.draw:
                        plot(x, y, model.w)

                    # If the window has not reached steady state and the next
                    # window will be at steady state, remove points to
                    # correctly update the sums
                    if (max_window_size - current_window_size < step_size
                            and not window_state[1]):
                        for i in range(
                                0, step_size -
                            (max_window_size - current_window_size)):
                            x_value = x[i].tolist()[0]
                            y_value = y[i].tolist()[0]
                            model.x_sum -= x_value
                            model.y_sum -= y_value
                            model.xy_sum -= x_value * y_value
                            model.xx_sum -= x_value**2

                    # If the window has reached steady state, remove the first
                    # step size points from sums
                    if window_state[1]:

                        for i in range(0, step_size):
                            x_value = x[i].tolist()[0]
                            y_value = y[i].tolist()[0]
                            model.x_sum -= x_value
                            model.y_sum -= y_value
                            model.xy_sum -= x_value * y_value
                            model.xx_sum -= x_value**2

                # The data has more than 1 feature, train using SGD
                else:
                    model.w = train_sgd(x, y, self.alpha, model.w)
                    if self.draw:
                        plot(x, y, model.w)
                    self.w = model.w
                error = evaluate_error(x, y, model.w)
                if self.output:
                    print "Error: ", error

                model.sum_error += error
                model.i += 1
                return model