---
presentation
theme: beige.css
slideNumber: true
width: 1024 height: 768
---
## Aprendizado de Máquina
### Dicas práticas
### Prof. Ronaldo Cristiano Prati
[ronaldo.prati@ufabc.edu.br](mailto:ronaldo.prati@ufabc.edu.br)
Bloco A, sala 513-2
### Dicas de SKLearn
- SKlearn é um pacote python muito que implementa vários algoritmos de aprendizado de máquina
- Ele também oforece um conjunto de funções que implementam diversas funcionalidades para utilizar esses algoritmos
### Dicas de SKLearn
- Vamos ver como criar a curva de aprendizado (incrementando o conjunto de dados) e a curva de validação (alteranando os valores do parâmetro livre)
- Pode ser usado para analisar o trade-off bias-variância.
### Pacotes
```python
import matplotlib.pyplot as plt
# data sets
from sklearn.datasets import load_digits, load_iris
# Algoritmos
from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC
from sklearn.model_selection import learning_curve, validation_curve
import numpy as np
```
### Curva de Aprendizado
```python
# Seleciona 2 classes do dataset digits
X,y = load_digits(n_class=2,return_X_y=True)
# cria uma lista de 0.1 a 1, contendo 10 pontos igualmente espaçados
sizes = np.linspace(0.1,1,10)
algs = {'Logistic Regression' : LogisticRegression(solver='lbfgs'),
'SVM - Gaussian' : SVC()}
for name, alg in algs.items():
train_sizes, train_scores, test_scores = learning_curve(
alg, X, y, cv=3, train_sizes=sizes)
plot_learning_curve(train_sizes, train_scores, test_scores,name)
```
### Curva de Aprendizado
### Curva de Validação
```python
X,y = load_digits(return_X_y=True)
# cria pontos exponencialmente expaçados 10^-6 até 10^-1
param_range = np.logspace(-6, -1, 5)
train_scores, test_scores = validation_curve(
SVC(), X, y, param_name="gamma", param_range=param_range,
cv=5, scoring="accuracy", n_jobs=1)
```
### Curva de Validação
## Grid Search
- Em algumas situações queremos variar mais de um parâmetro livre do algoritmo.
- Em SVMs por exemplo, podemos querer ajustar o parâmetro de regularização $C$ e o parâmetro do kernel $\sigma$
- GridSearch faz uma busca combinando todas as possibilidades para esses valores
## Grid Search
```python
X, y = load_iris(return_X_y=True)
# faixa de valores de C
C_range = np.logspace(-2, 10, 13)
# faixa de valores de gamma
gamma_range = np.logspace(-9, 3, 13)
param_grid = dict(gamma=gamma_range, C=C_range)
cv = StratifiedShuffleSplit(y, n_iter=5, test_size=0.2, random_state=42)
grid = GridSearchCV(SVC(), param_grid=param_grid, cv=cv)
grid.fit(X, y)
```
## Grid Search
The best parameters are {'C': 1.0, 'gamma': 0.1} with a score of 0.97
## Grid Search
## Validação cruzada
- Como visto anteriormente, em validação cruzada, dividimos o conjunto em diferentes partes de treino e teste
- Se a base estiver de alguma maneira ordenada, temos que tomar cuidado em como fazemos a divisão
## Validação cruzada
- O Sklearn tem vários metodos que auxiliam a fazer validação cruzada.
- O mais simples deles divide os as linhas da base em blocos igualmente espaçados.
## Validação cruzada
```python
from sklearn.model_selection import KFold
from sklearn.metrics import accuracy_score
X, y = load_iris(return_X_y=True)
alg = LogisticRegression(solver='lbfgs',multi_class='ovr')
accuracies = []
kf = KFold(n_splits=5)
for train, test in kf.split(X):
X_train = X[train]
X_test = X[test]
y_train = y[train]
y_test = y[test]
alg.fit(X_train,y_train)
pred = alg.predict(X_test)
accuracies.append(accuracy_score(y_test,pred))
```
## Validação cruzada
```python
print(accuracies)
[1.0, 0.9, 0.5, 0.9333333333333333, 0.6333333333333333]
print (np.mean(accuracies),np.std(accuracies))
0.7933333333333332 0.19252705437591536
```
### Validação cruzada estratificada
- Esse grande variação vem do fato que, ao fazermos a validação cruzada, pegamos blocos contíguos
- Como a base está agrupada por classes, temos conjuntos com classes não representadas no treino/teste
- Validação cruzada estratificada leva em consideração as classes para fazer a divisão
## Validação cruzada estratificada
```python
from sklearn.model_selection import StratifiedKFold
from sklearn.metrics import accuracy_score
X, y = load_iris(return_X_y=True)
alg = LogisticRegression(solver='lbfgs',multi_class='ovr')
accuracies = []
kf = StratifiedKFold(n_splits=5)
for train, test in kf.split(X,y):
X_train = X[train]
X_test = X[test]
y_train = y[train]
y_test = y[test]
alg.fit(X_train,y_train)
pred = alg.predict(X_test)
accuracies.append(accuracy_score(y_test,pred))
```
### Validação cruzada estratificada
```python
print(accuracies)
[0.8666666666666667, 0.9666666666666667, 0.9333333333333333,
0.9333333333333333, 1.0]
print (np.mean(accuracies),np.std(accuracies))
0.9400000000000001 0.044221663871405324
```
### Validação cruzada agrupada
- Em algumas situações, a base de dados também pode estar organizada em grupos
- Por exemplo, uma prática comum em classificação de imagens, por exemplo, é rotacionar a imagem em $90^o, 180^o, 270^o$ e $360^o$
- Nesse caso, para cada imagem inicial, temos outras 4
- Para esses casos, devemos usar validação cruzada agrupada
### Validação cruzada agrupada
```python
from sklearn.model_selection import GroupKFold
X = [0.1, 0.2, 2.2, 2.4, 2.3, 4.55, 5.8, 8.8, 9, 10]
y = ["a", "b", "b", "b", "c", "c", "c", "d", "d", "d"]
groups = [1, 1, 1, 2, 2, 2, 3, 3, 3, 3]
gkf = GroupKFold(n_splits=3)
for train, test in gkf.split(X, y, groups=groups):
print("%s %s" % (train, test))
[0 1 2 3 4 5] [6 7 8 9]
[0 1 2 6 7 8 9] [3 4 5]
[3 4 5 6 7 8 9] [0 1 2]
```
### Validação cruzada agrupada
## Métrica de avaliação
- Em diversas aplicações, a escolha da métrica de avaliação pode levar a resultados incosistentes
- Por exemplo, quando temos classes desbalanceadas, é fácil ter uma alta acurácia
- Vamos assumir que fraude de cartão só ocorre 0.1% das transações
- Classificador que **nunca** preve fraude acerta 99.9% das vezes!
### Matriz de confusão
### Precisão (precision)
- Avalia cada classe individualmente
- Vamos chamar a nossa classe de interesse positiva
- Quando o algoritmo prediz um exemplo como positivo, com que frequência ele acerta aquela predição?
$$ precision = \frac{TP}{TP+FP} $$
### Revocação (recall)
- Avalia cada classe individualmente
- Vamos chamar a nossa classe de interesse positiva
- Com relação a todos os exemplos positivos do conjunto de teste, quantos o algoritmo acertou?
$$ recall = \frac{TP}{TP+FN}$$
### Métrica de avaliação
- Geralmente escolhemos a classe minoritária como a de interesse
- Doença rara, fraude, etc.
- Calcular precisão e revocação para essa classe nos dá uma ideia melhor do desempenho do algoritmo para aquela classe
- Eventualmente podemos computar para outra(s) classe(s) também
### F1-measure
- A medida $F1$ é muito usada em algumas áreas como um compromisso entre precisão e revocação.
- Média harmônica entre precisão e revocação
$$ F1 = 2 \cdot \frac{precision*recall}{precision + recall} $$
### Trade-off entre precisão e revocação
- Para muitas aplicações, queremos controlar o *trade-off* entre precisão e revocação
- É fácil otimizar um ou outro:
- precisão: só predizar o mais seguro (e.g., o de maior probabilidade)
- revocação: predizer todos os exemplos como positivos
- Entretanto, otimizar os dois pode ser difícil
### Trade-off entre precisão e revocação
- Uma maneira de controlar o trade-off entre essas duas medidas é variar o limiar da fronteira de decisão
- Por exemplo, na regressão logística, o algoritmo dá como saída a probabilidade da classe
- Normalmente assumimos que a fronteira está em predizer classe positiva se $h_\theta(x) > 0.5$.
- Por exemplo, podemos aumentar precisão predizendo positivo se $h_\theta(x) > 0.8$, e aumentar a revocação predizendo positivo se $h_\theta(x) > 0.2$
### Trade-off entre precisão e revocação
- A escolha do limiar é dependente do problema
- Podemos analisar o desempenho de um modelo considerando todos os possíves limiares
- Curva precisão-revocação (precision-recall)
- Precision (eixo $y$)
- Recall (eixo $x$)
- Para cada possível limiar, calcula-se um valor de precision e recall
### Precison-recall curve
```python
from sklearn.metrics import precision_recall_curve
from sklearn.model_selection import train_test_split
from sklearn.datasets import make_classification
from sklearn import svm
X,y = make_classification(class_sep=0.5)
X_train, X_test, y_train, y_test = train_test_split(X, y,
test_size=.5)
alg = svm.LinearSVC()
alg.fit(X_train, y_train)
y_score = alg.decision_function(X_test)
precision, recall, t = precision_recall_curve(y_test, y_score)
```
### Precision recall curve