Documento de estudo da US08
Introdução
Antes da criação das intents, actions e stories de cada tema selecionado são gerados documentos pela equipe de desenvolvimento que possuem abrangentemente do que aquele ele se trata. Selecionamos um breve conhecimento do tema, possíveis bibliotecas e até mesmo a forma de implementação.
Objetivo
Tendo em vista que os dados passados para o treinamento do bot devem ser bem claros e ter uma quantidade reduzida de informação para não poluir a caixa de mensagens do usuário, o desenvolvedor responsável pelo tema tem como objetivo extrair o máximo de informação e simplifica-la antes de passar para o usuário final. Isso torna a criação das intents, actions e stories mais rápidas e objetivas.
1. Generalized Linear Models
Em estatística, o modelo linear generalizado é uma generalização flexível da regressão linear ordinária que permite variáveis de resposta que possuem modelos de distribuição de erro diferentes de uma distribuição normal. O GLM generaliza a regressão linear permitindo que o modelo linear seja relacionado à variável de resposta por meio de uma função de link e permitindo que a magnitude da variância de cada medida seja uma função de seu valor previsto.
1.1 Logistic regression
A regressão logística, apesar de seu nome, é um modelo linear para classificação em vez de regressão. A regressão logística também é conhecida na literatura como regressão logit, classificação de máxima entropia (MaxEnt) ou o classificador log-linear. Nesse modelo, as probabilidades que descrevem os resultados possíveis de um único teste são modeladas usando uma função logística.
from sklearn import svm
X = [[0, 0], [1, 1]]
y = [0, 1]
clf = svm.SVC(gamma='scale')
clf.fit(X, y)
Output:
SVC(C=1.0, cache_size=200, class_weight=None, coef0=0.0,
decision_function_shape='ovr', degree=3, gamma='scale', kernel='rbf',
max_iter=-1, probability=False, random_state=None, shrinking=True,
tol=0.001, verbose=False)
2. Support Vector Machines
A máquina de vetores de suporte (SVM) é um conjunto de métodos do aprendizado supervisionado que analisam os dados e reconhecem padrões, usado para classificação e análise de regressão. O SVM padrão toma como entrada um conjunto de dados e prediz, para cada entrada dada, qual de duas possíveis classes a entrada faz parte, o que faz do SVM um classificador linear binário não probabilístico. Um modelo SVM é uma representação de exemplos como pontos no espaço, mapeados de maneira que os exemplos de cada categoria sejam divididos por um espaço claro que seja tão amplo quanto possível.
2.1 Classificação
SVC, NuSVC e LinearSVC são classes capazes de executar classificações de várias classes em um conjunto de dados.
O SVC e o NuSVC são métodos semelhantes, mas aceitam conjuntos de parâmetros ligeiramente diferentes e têm diferentes formulações matemáticas. Por outro lado, o LinearSVC é outra implementação do Support Vector Classification para o caso de um kernel linear.
Como outros classificadores, SVC, NuSVC e LinearSVC tomam como entrada duas matrizes: uma matriz X de tamanho [n_samples, n_features] contendo as amostras de treinamento, e uma matriz y de rótulos de classe (strings ou inteiros), tamanho [n_samples]:
Depois de ajustado, o modelo pode ser usado para prever novos valores:
clf.predict([[2., 2.]])
Output:
array([1])
A função de decisão de SVMs depende de algum subconjunto dos dados de treinamento, chamados de vetores de suporte. Algumas propriedades destes vetores de suporte podem ser encontradas nos membros support_vectors_, support_ e n_support:
# get support vectors
clf.support_vectors_
Output:
array([[0., 0.],
[1., 1.]])
# get indices of support vectors
clf.support_
Output:
array([0, 1]...)
# get number of support vectors for each class
clf.n_support_
Output:
array([1, 1]...)
2.1.1 Multi-class classification
O SVC e o NuSVC implementam a abordagem “um-contra-um” para classificação de várias classes. Se n_class é o número de classes, os classificadores n_class * (n_class - 1) / 2 são construídos e cada um treina os dados de duas classes. Para fornecer uma interface consistente com outros classificadores, a opção decision_function_shape permite agregar os resultados dos classificadores “um contra um” a uma função de decisão de forma (n_samples, n_classes):
X = [[0], [1], [2], [3]]
Y = [0, 1, 2, 3]
clf = svm.SVC(gamma='scale', decision_function_shape='ovo')
clf.fit(X, Y)
Output:
SVC(C=1.0, cache_size=200, class_weight=None, coef0=0.0,
decision_function_shape='ovo', degree=3, gamma='scale', kernel='rbf',
max_iter=-1, probability=False, random_state=None, shrinking=True,
tol=0.001, verbose=False)
dec = clf.decision_function([[1]])
dec.shape[1] # 4 classes: 4*3/2 = 6
Output:
6
clf.decision_function_shape = "ovr"
dec = clf.decision_function([[1]])
dec.shape[1] # 4 classes
Output:
4
Por outro lado, o LinearSVC implementa uma estratégia multi-classe “one to the rest”, treinando assim modelos n_class. Se houver apenas duas classes, apenas um modelo é treinado:
lin_clf = svm.LinearSVC()
lin_clf.fit(X, Y)
Output:
LinearSVC(C=1.0, class_weight=None, dual=True, fit_intercept=True,
intercept_scaling=1, loss='squared_hinge', max_iter=1000,
multi_class='ovr', penalty='l2', random_state=None, tol=0.0001,
verbose=0)
dec = lin_clf.decision_function([[1]])
dec.shape[1]
Output:
4
3. Stochastic Gradient Descent
O Descentramento Estocástico de Gradiente (SGD) é uma abordagem simples, mas muito eficiente, para a aprendizagem discriminativa de classificadores lineares sob funções de perda convexa, como Máquinas de Vetores de Suporte (lineares) e Regressão Logística. O SGD tem sido aplicado com sucesso em problemas de aprendizado de máquina em grande escala e esparsos, freqüentemente encontrados na classificação de textos e processamento de linguagem natural.
3.1 Classification
A classe SGDClassifier implementa uma rotina de aprendizado de descida gradiente estocástica que suporta diferentes funções de perda e penalidades para classificação.
Como outros classificadores, o SGD deve ser equipado com duas matrizes: uma matriz X de tamanho [n_samples, n_features] contendo as amostras de treinamento e uma matriz Y de tamanho [n_samples] contendo os valores de destino (rótulos de classe) para as amostras de treinamento:
from sklearn.linear_model import SGDClassifier
X = [[0., 0.], [1., 1.]]
y = [0, 1]
clf = SGDClassifier(loss="hinge", penalty="l2", max_iter=5)
clf.fit(X, y)
Output:
SGDClassifier(alpha=0.0001, average=False, class_weight=None,
early_stopping=False, epsilon=0.1, eta0=0.0, fit_intercept=True,
l1_ratio=0.15, learning_rate='optimal', loss='hinge', max_iter=5,
n_iter=None, n_iter_no_change=5, n_jobs=None, penalty='l2',
power_t=0.5, random_state=None, shuffle=True, tol=None,
validation_fraction=0.1, verbose=0, warm_start=False)
Depois de ajustado, o modelo pode ser usado para prever novos valores:
clf.predict([[2., 2.]])
Output:
array([1])
O SGD ajusta um modelo linear aos dados de treinamento. O membro coef_ contém os parâmetros do modelo:
clf.coef_
Output:
array([[9.9..., 9.9...]])
Membro intercept_ detém a interceptação (deslocamento ou polarização):
clf.intercept_
Output:
array([-9.9...])
Se o modelo deve ou não usar uma interceptação, ou seja, um hiperplano enviesado, é controlado pelo parâmetro fit_intercept.
Para obter a distância assinada para o hiperplano use SGDClassifier.decision_function:
clf.decision_function([[2., 2.]])
Output:
array([29.6...])
A função de perda de concreto pode ser definida através do parâmetro de perda. O SGDClassifier suporta as seguintes funções de perda:
loss = "hinge": (soft-margin) linear Máquina de Vetores de Suporte
loss = "modified_huber": perda da dobradiça alisada
loss = "log": regressão logística
E todas as perdas de regressão abaixo
Usando loss = "log" ou loss = "modified_huber" habilita o método predict_proba, que fornece um vetor de estimativas de probabilidade por amostra:
clf = SGDClassifier(loss="log", max_iter=5).fit(X, y)
clf.predict_proba([[1., 1.]])
Output:
array([[0.00..., 0.99...]])
4. Nearest Neighbors
Nearest Neighbors e a base de muitos outros métodos de aprendizado. O pricípio por trás do método nearest neighbors é encontrar um número predefinido de amostras de treinamento mais próximas da distancia do novo ponto e prever a label a partir delas. O número de amostras pode ser uma constante definida pelo usuário (k-neighbor learning) ou variar com base na densidade local dos pontos (radius-based neighbor learning). A distancia pode ser qualquer medida métrica. Sendo um método não paramêtrico, é bem sucedido em situações de classificação em que os limites de decisão são muito irregulares.
4.1 Unsurpevised nearest neighbors
NearestNeighbors atua como uma interface uniforme para três tipos de algoritmos nearest neighbors: BallTree, KDTree, e um algoritmo de força bruta baseado nas rotinas da sklearn.metrics.pairwise
. A escolha dos algoritmos é controlada através do parâmetro algorithm
, que deve ser ['auto', 'ball_tree', 'kd_tree', 'brute']
. Quando o valor default 'auto'
e passado, o algoritmo tenta determinar a melhor abordagem a partir dos dados de treinamento.
4.1.1 Achando o Nearest Neighbors
Exemplo de como achar nearest neighbors entre dois conjuntos de dados:
from sklearn.neighbors import NearestNeighbors
import numpy as np
X = np.array([[-1, -1], [-2, -1], [-3, -2], [1, 1], [2, 1], [3, 2]])
nbrs = NearestNeighbors(n_neighbors=2, algorithm='ball_tree').fit(X)
distances, indices = nbrs.kneighbors(X)
Out:
indices array([[0, 1],
[1, 0],
[2, 1],
[3, 4],
[4, 3],
[5, 4]]...)
distances array([[0. , 1. ],
[0. , 1. ],
[0. , 1.41421356],
[0. , 1. ],
[0. , 1. ],
[0. , 1.41421356]])
4.1.2 Classes KDTree e BallTree
Outra alternativa é usar diretamente as classes KDTree e BallTree para achar os nearest neighbors. As duas classes tem a mesma interface:
from sklearn.neighbors import KDTree
import numpy as np
X = np.array([[-1, -1], [-2, -1], [-3, -2], [1, 1], [2, 1], [3, 2]])
kdt = KDTree(X, leaf_size=30, metric='euclidean')
kdt.query(X, k=2, return_distance=False)
array([[0, 1],
[1, 0],
[2, 1],
[3, 4],
[4, 3],
[5, 4]]...)
4.2 Classisficação Nearest Neighbors
A classificação usando nearest neighbors é calculada a partir de uma simples votação por maioria dos nearest neighbors mais próximos de cada ponto: um ponto de consulta é atribuido à classe de dados que possui mais representantes dentro dos nearest neighbors mais próximos.
O scikit-learn implementa dois classificadores de nearest neighbors: KNeighborsClassifier implementa o aprendizado baseado no k nearest neighbors de cada ponto de consulta,onde k é um valor inteiro especificado pelo usuário. RadiusNeighborsClassifier implementa a aprendizagem com base no número de neighbors dentro de um raio fixo r de cada ponto de treinamento, onde r é um valor de ponto flutuante especificado pelo usuário.
A classificação de vizinhos KNeighborsClassifier é a técnica mais usada. A escolha ideal do valor k é altamente dependente dos dados: em geral, um k muito grande suprime os efeitos do ruído, mas torna os limites de classificação menos distintos.
Nos casos em que os dados não são uniformemente amostrados, a classificação dos neighbors baseados no raio RadiusNeighborsClassifierpode ser uma escolha melhor. O usuário especifica um raio fixo r, de modo que pontos em vizinhanças mais esparsas usem menos vizinhos mais próximos para a classificação.
A classificação básica de vizinhos mais próximos usa pesos uniformes: isto é, o valor atribuído a um ponto de consulta é calculado a partir de uma votação por maioria simples dos vizinhos mais próximos. Em algumas circunstâncias, é melhor ponderar os vizinhos de tal forma que os vizinhos mais próximos contribuam mais para o ajuste. Isso pode ser feito através do parametro weights
. O valor padrão weights = 'uniform'
, atribui pesos uniformes a cada vizinho.weights = 'distance'
atribui pesos proporcionais ao inverso da distância do ponto de consulta. Alternativamente, uma função definida pelo usuário da distância pode ser fornecida para calcular os pesos.
Exemplo:
```python
import numpy as np import matplotlib.pyplot as plt from matplotlib.colors import ListedColormap from sklearn import neighbors, datasets
n_neighbors = 15
import some data to play with
iris = datasets.load_iris()
we only take the first two features. We could avoid this ugly
slicing by using a two-dim dataset
X = iris.data[:, :2] y = iris.target
h = .02 # step size in the mesh
Create color maps
cmap_light = ListedColormap(['#FFAAAA', '#AAFFAA', '#AAAAFF']) cmap_bold = ListedColormap(['#FF0000', '#00FF00', '#0000FF'])
for weights in ['uniform', 'distance']: # we create an instance of Neighbours Classifier and fit the data. clf = neighbors.KNeighborsClassifier(n_neighbors, weights=weights) clf.fit(X, y)
# Plot the decision boundary. For that, we will assign a color to each
# point in the mesh [x_min, x_max]x[y_min, y_max].
x_min, x_max = X[:, 0].min() - 1, X[:, 0].max() + 1
y_min, y_max = X[:, 1].min() - 1, X[:, 1].max() + 1
xx, yy = np.meshgrid(np.arange(x_min, x_max, h),
np.arange(y_min, y_max, h))
Z = clf.predict(np.c_[xx.ravel(), yy.ravel()])
# Put the result into a color plot
Z = Z.reshape(xx.shape)
plt.figure()
plt.pcolormesh(xx, yy, Z, cmap=cmap_light)
# Plot also the training points
plt.scatter(X[:, 0], X[:, 1], c=y, cmap=cmap_bold,
edgecolor='k', s=20)
plt.xlim(xx.min(), xx.max())
plt.ylim(yy.min(), yy.max())
plt.title("3-Class classification (k = %i, weights = '%s')"
% (n_neighbors, weights))
plt.show() ```
## 5. Naive Bayes
GaussianNB implementa o algoritmo Gaussian Naive Bayes para classificação. A probabilidade das features assume ser gaussiana:
Os parâmetros σy e μy são estimados usando a maior probabilidade.
from sklearn import datasets
iris = datasets.load_iris()
from sklearn.naive_bayes import GaussianNB
gnb = GaussianNB()
y_pred = gnb.fit(iris.data, iris.target).predict(iris.data)
print("Number of mislabeled points out of a total %d points : %d"
% (iris.data.shape[0],(iris.target != y_pred).sum()))
6. Decision Trees
DecisionTreeClassifier e a classe capaz de realizar classificações de varias classes em um dataset.
O parâmetro de entrada são dois arrays: um array X, esparso ou denso, de tamanho [n_samples, n_features]
contendo os dados de treino; e um array Y de valores inteiros de tamanho [n_samples]
, contendo as labels de classes para os dados de treino:
from sklearn import tree
X = [[0, 0], [1, 1]]
Y = [0, 1]
clf = tree.DecisionTreeClassifier()
clf = clf.fit(X, Y)
Depois de ajustada, a model pode ser usada para prever os dados:
clf.predict([[2., 2.]])
Saida:
array([1])