import numpy as np
class AdalineGD(object):
    """ADAptive LInear NEuron classifier.
    Parameters
    ----------
    eta: float
    Learning rate (between 0.0 and 1.0)
    n_iter : int
    Passes over the training dataset
    random_state:int
    Random number generator seed for random weight
    initialization.

    Attributes
    ------------
    w_: Id-array
    Weights after fitting
    cost_: list
    Sum-of-squares cost function value in each epoch
    """
    def __init__(self,eta = 0.01, n_iter = 50,random_state=1):
        self.eta = eta
        self.n_iter = n_iter
        self.random_state = random_state
    def fit(self,X,y):
        """

        :param X: {array_like},shape = {n_samples,n_features}
        Training vectors,where n_samples is the number of samples
        and n_features is the number of features.
        :param y: array-like,shape = [n_sample]
        Target value
        :return:
        self:object
        """
        rgen = np.random.RandomState(self.random_state)
        self.w_ = rgen.normal(loc = 0.0,scale = 0.01,size = 1+X.shape[1])#loc everage scale sdandard size
        self.cost_ = []
        for i in range(self.n_iter):
            net_input = self.net_input(X)
            output = self.activation(net_input)
            errors = (y - output)
            self.w_[1:]+=self.eta*X.T.dot(errors)   #this step differ from Perceptron error*X .T is convert
            self.w_[0] += self.eta * errors.sum()
            cost = (errors**2).sum() / 2.0
            self.cost_.append(cost)


    def net_input(self,X):
        """Caluculate net input"""
        return np.dot(X,self.w_[1:])+self.w_[0]
    def activation(self,X):
        """Compute linear activation"""
        return X
    def predict(self,X):
        """Return class label after unit step"""
        return np.where(self.activation(self.net_input(X)) >= 0.0,1,-1)
