<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def add_noise(data, sigma=1.0, noise_type='gauss'):
 r"""Add noise to data This method adds Gaussian or Poisson noise to the input data Parameters data : np.ndarray, list or tuple Input data array sigma : float or list, optional Standard deviation of the noise to be added ('gauss' only) noise_type : str {'gauss', 'poisson'} Type of noise to be added (default is 'gauss') Returns ------- np.ndarray input data with added noise Raises ------ ValueError If `noise_type` is not 'gauss' or 'poisson' ValueError If number of `sigma` values does not match the first dimension of the input data Examples -------- array([[ 0., 1., 2.], [ 3., 4., 5.], [ 6., 7., 8.]]) array([[ 0., 2., 2.], [ 4., 5., 10.], [ 11., 15., 18.]]) array([ 0., 0., 0., 0., 0.]) array([ 3.24869073, -1.22351283, -1.0563435 , -2.14593724, 1.73081526]) """


    data = np.array(data)

    if noise_type not in ('gauss', 'poisson'):
        raise ValueError('Invalid noise type. Options are "gauss" or'
                         '"poisson"')

    if isinstance(sigma, (list, tuple, np.ndarray)):
        if len(sigma) != data.shape[0]:
            raise ValueError('Number of sigma values must match first '
                             'dimension of input data')

    if noise_type is 'gauss':
        random = np.random.randn(*data.shape)

    elif noise_type is 'poisson':
        random = np.random.poisson(np.abs(data))

    if isinstance(sigma, (int, float)):
        return data + sigma * random

    else:
        return data + np.array([s * r for s, r in zip(sigma, random)])