# INF-285 / ILI-285
## Desafío 5 v1.1
### SCT 2020-1

## Instrucciones
* El desafío es individual, por lo cual se considera que todo el código entregado es de elaboración propia y no ha sido compartido de forma alguna.
* Las consultas sobre el desafío se deben realizar por medio de la plataforma Aula. **No está permitido publicar código en consultas de Aula**.
* El desafío debe ser realizado en Jupyter Notebook (Python3) utilizando este archivo como base.
* Debe utilizar arreglos de NumPy junto a las funciones y bibliotecas que se ponen a disposición en este archivo.
* Se debe respetar las firmas de las funciones, sus parámetros y retornos. Para eso se incluye un detalle de cada función tanto de las entregadas como las que deberá implementar. En caso de no seguir estas instrucciones, el desafío no podrá evaluarse.
* Se evaluará la correcta utilización de librerias NumPy, SciPy, entre otras, así como la correcta implementación de algoritmos de forma vectorizada.
* Evitar la impresión de mensajes salvo que se solicite en el enunciado.
* El archivo de entrega debe denominarse **ROL-desafio-numero.ipynb**. **De no respetarse este formato existirá un descuento de 50 puntos**.
* La fecha de entrega es el **4 de agosto a las 12:00 hrs**.


```python
import numpy as np
import scipy.linalg as spla
import matplotlib.pyplot as plt
```

## Introducción

El objetivo de este desafío es evaluar su capacidad de "analista de datos" con un problema de regresión. 
Suponga que tiene el conjunto de datos $\{(x_1,y_1), (x_2, y_2), \dots, (x_m, y_m)\}$ para los cuales necesitamos ajustar un modelo del tipo $f(x, \boldsymbol{\beta})$ con $\boldsymbol{\beta}=\beta_1, \beta_2, \dots, \beta_n$, los parámetros del modelo. Considere por ejemplo que un modelo lineal sería:

\begin{equation}
    f(x, \boldsymbol{\beta})=\beta_1 + \beta_2\,x.
\end{equation}

Los datos provienen de algun instrumento de medición desconocido y se encuentran en la siguiente dirección: **[datos](https://github.com/sct-utfsm/INF-285/tree/master/desafios/data)**

## Tarea

La tarea es utilizar su creatividad para construir un modelo que se ajuste a los datos entregados. Para explorar visualmente los datos y posteriormente analizar su ajuste se pone a disposición la función ```plot(x_i, y_i, y_fit)``` que recibe los datos $x_i$, $y_i$, y en el caso que tenga su ajuste $y_{fit}$. 


```python
def plot(x_i, y_i, y_fit=None):
    """
    Plot data

    Parameters
    -----------
    x_i     : (m, ) array
             Data x_i to fit
    y_i     : (m, ) array
             Data y_i to fit
    y_fit   : (m, ) array or None
             Model output

    Returns
    -------
    None
    """
    plt.figure(figsize=(12, 6))
    plt.plot(x_i, y_i, 'r.', label='Data')
    if y_fit is not None:
        plt.plot(x_i, y_fit, 'b-', label='Model')
    plt.xlabel(r'$x$')
    plt.ylabel(r'$y$')
    plt.grid(True)
    plt.legend()
    plt.show()
```

### Evaluación

Para evaluar su modelo, utilizaremos el *error cuadrático relativo* definido como:
\begin{equation}
    SE_{rel} = \frac{\displaystyle \sum_{i=1}^m (y_i - f(x_i, \boldsymbol{\beta}))^2}{\displaystyle \sum_{i=1}^{m}y_i^2} = \frac{\displaystyle\sum_{i=1}^m (y_i - \hat{y}_i)^2}{\displaystyle \sum_{i=1}^{m}y_i^2}.
\end{equation}

Implemente la función ```SErel(y_i, y_fit)``` que reciba los valores de $y_i$ y los datos ajustados por su modelo $\hat{y}_i$ y retorne el valor del error relativo indicado.


```python
def SErel(y_i, y_fit):
    """
    Relative SE computation

    Parameters
    -----------
    y_i     : (m, ) array
             Data y_i to fit
    y_fit   : (n, ) array 
             Model output

    Returns
    -------
    SE_rel  : float
             Relative SE value
    """
    ...
```

Su nota se calculará utilizando el valor obtenido por el $SE_{rel}$ asociado a su modelo de la siguiente manera:

\begin{equation}
    nota(SE_{rel}) = 
    \begin{cases}
        100 & \text{si} \quad 0.08 \leq SE_{rel} \leq 0.15 \\
        round\left(\frac{835 - 900\,SE_{rel} }{7}\right) & \text{si} \quad SE_{rel} > 0.15\\
        0 & \text{si} \quad SE_{rel} < 0.08
    \end{cases}
\end{equation}

Se considera un ajuste deficiente si utiliza simplemente una función lineal para el ajuste, así que entre mejor sea su modelo, mejor será su nota ;). En el caso que el *error relativo* sea muy pequeño se puede considerar casi una interpolación, por lo tanto se evalúa con nota mínima. Puede utilizar la función adjunta para analizar la capacidad de su modelo.


```python
def nota(se_rel):
    if se_rel < 0.08: # Are you sure it's not an interpolation?
        return 0
    elif 0.08 <= se_rel <= 0.15:
        return 100
    else:
        return np.round((835 - 900 * se_rel) / 7)
```

### Ajuste

Como hemos revisado en clases, podemos ajustar los parámetros de un modelo utilizando mínimos cuadrados. Para esto tenemos dos opciones: 

####  Resolver las ecuaciones normales: 

\begin{equation}
    A^*\, A \mathbf{x} = A^*\, \mathbf{b}
\end{equation}

#### Utilizar $QR$:

1. Aplicar $QR$ reducido para obtener $A = \hat{Q}\,\hat{R}$
2. Resolver $\hat{R}\,\mathbf{x}=\hat{Q}^*\,\mathbf{b}$

Para ambos casos recuerde que $A$ dependerá del modelo que usted proponga, $\mathbf{x}=\boldsymbol{\beta}$ y $\mathbf{b}$ es el vector asociado a $y_i$. Implemente la función ```modelFit(A, b, method)``` que reciba $A$, $\mathbf{b}$ y ```method``` para indicar si se utilizarán las *ecuaciones normales* o $QR$, y retorne los parámetros $\boldsymbol{\beta}$ del modelo que está ajustando.


```python
def modelFit(A, b, method):
    """
    Curve fitting

    Parameters
    -----------
    A        : (m, n) array
              A matrix of overdetermined system of equations
    b        : (m, ) array
              b vector of overdetermined system of equations
    method   : string {'NE', 'QR'}
              Solving method with Normal Equations 'NE' or QR factorization'QR'

    Returns
    -------
    beta     : (n, ) array
              Model parameters 
    """
    ...
```

----

## Desarrollo

### Cargar datos


```python
# Load data
x_i = ...
y_i = ...
```

### Modelo

Como ejemplo se incluye un modelo lineal... Confiamos en que usted será más creativo en la construcción de su propuesta. Puede hacer uso de combinaciones de modelos vistos en clases, por ejemplo:
\begin{equation}
    f(x, \beta_1, \beta_2, \dots) = \beta_1 + \beta_2\,x^2 + \beta_2\,x\,\cos(2\pi x) + \dots
\end{equation}


```python
# Modify this function. It is only an example
def model(b1, b2, x):
    return b1 + b2 * x
```

Construcción de $A$ y $\mathbf{b}$


```python
A = ...
b = ...
```

Obtención de parámetros...


```python
beta = ...
```


```python
y_fit = ...
```


```python
# plot(x_i, y_i, y_fit)
```

Evaluación de su propuesta


```python
se = 0
```


```python
print(se, nota(se))
```

6d3b8a937ebc8a39d13be5a6862cbff192154f5e
ipynb
Jupyter Notebook
desafios/desafio_5.ipynb
fitoxgs2/INF-285
f7d547c2480aea7eb1242b873ab1135a0873834f
BSD-3-Clause
2020-04-24T01:25:24.000Z
2021-05-10T01:08:37.000Z
desafios/desafio_5.ipynb
fitoxgs2/INF-285
f7d547c2480aea7eb1242b873ab1135a0873834f
BSD-3-Clause
2020-04-22T00:57:29.000Z
2020-04-23T23:59:28.000Z
desafios/desafio_5.ipynb
fitoxgs2/INF-285
f7d547c2480aea7eb1242b873ab1135a0873834f
BSD-3-Clause
2020-04-20T01:15:09.000Z
2020-07-27T22:53:59.000Z
Qwen/Qwen-72B
1. YES
2. YES