Pesquisar este blog

domingo, 28 de outubro de 2018

Machine Learning no Python

Aqui iremos mostrar como fazer o uso de Machine Learning no python
sudo pip install matplotlib
sudo pip install scipy
sudo pip install pandas
sudo pip install sklearn
Para testar as versões dos pacotes instalados utilize o código a seguir:
import sys
print('Python: {}'.format(sys.version))
# scipy
import scipy
print('scipy: {}'.format(scipy.__version__))
# numpy
import numpy
print('numpy: {}'.format(numpy.__version__))
# matplotlib
import matplotlib
print('matplotlib: {}'.format(matplotlib.__version__))
# pandas
import pandas
print('pandas: {}'.format(pandas.__version__))
# scikit-learn
import sklearn
print('sklearn: {}'.format(sklearn.__version__))
O que na minha máquina atualmente imprime o seguinte:
Python: 2.7.12 (default, Nov 19 2016, 06:48:10)
[GCC 5.4.0 20160609]
scipy: 0.19.0
numpy: 1.12.1
matplotlib: 2.0.1
pandas: 0.20.1
sklearn: 0.18.1

Importando as bibliotecas

Para importar as bibliotecas que serão utilizadas no nosso exemplo, utilize o código a seguir:



import pandas

from pandas.tools.plotting import scatter_matrix

import matplotlib.pyplot as plt

from sklearn import model_selection

from sklearn.metrics import classification_report

from sklearn.metrics import confusion_matrix

from sklearn.metrics import accuracy_score

from sklearn.linear_model import LogisticRegression

from sklearn.tree import DecisionTreeClassifier

from sklearn.neighbors import KNeighborsClassifier

from sklearn.discriminant_analysis import LinearDiscriminantAnalysis

from sklearn.naive_bayes import GaussianNB

from sklearn.svm import SVC

Carregando os dados

Como exemplo aqui será utilizado um dataset de classificação de flores provido pela UCI, e você pode conseguir mais detalhes sobre ele na wikipedia, a leitura deste dataset é feita utilizando a lib panda com o código mostrado a seguir:

url = "https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data"
nomes = ['comp-sepalo', 'larg-sepalo', 'comp-petala', 'larg-petala', 'classe']
dataset = pandas.read_csv(url, names=nomes)


Caso você tenha algum problema com a sua rede você pode baixar o dataset e usá-lo de algum diretório local.

Analisando os dados

Para saber se está tudo certo com os dados, vamos imprimir as primeiras 10 linhas e isto é feito com o seguinte código
print(dataset.head(1))
    comp-sepalo  larg-sepalo  comp-petala  larg-petala       classe
0          5.1                 3.5              1.4               0.2           Iris-setosa
O próximo passo é dar uma olhada no resumo estatístico destes dados, isto será feito com o comando describe
print(dataset.describe())
Que irá imprimir o seguinte:
comp-sepalo  larg-sepalo  comp-petala  larg-petala
count          150.000000      150.000000       150.000000      150.000000
mean             5.843333        3.054000            3.758667        1.198667
std              0.828066        0.433594            1.764420        0.763161
min              4.300000        2.000000            1.000000        0.100000
25%              5.100000        2.800000            1.600000        0.300000
50%              5.800000        3.000000            4.350000        1.300000
75%              6.400000        3.300000            5.100000        1.800000
max              7.900000        4.400000            6.900000        2.500000
Podemos avaliar quantos dados temos em cada classe agrupando os dados pela coluna classe, isto é feito com o seguinte código:
print(dataset.groupby('classe').size())

Execução de algorítmos

O primeiro passo para iniciar um algoritmo de machine learning é dividir o dataset em dois, um para o treino e um outro para teste.
Por que fazemos isto?
Bom inicialmente  esta divisão ocorre para termos uma parte do nosso dataset para validação dos dados, ou seja, usamos parte do que temos como treinamento para validar o quanto o algoritmo está acertando. Esta divisão é feita da seguinte forma:

array = dataset.values
X = array[:,0:4]
Y = array[:,4]
validation_size = 0.20
seed = 7
X_train, X_validation, Y_train, Y_validation = model_selection.train_test_split(X, Y, test_size=validation_size, random_state=seed)
Note que usamos uma divisão randômica dos dados e isto é feito para que o nosso treino não seja direcionado pelos dados.

Criando um modelo

scoring='accuracy' 
models = []
models.append(('LR', LogisticRegression()))
models.append(('LDA', LinearDiscriminantAnalysis()))
models.append(('KNN', KNeighborsClassifier()))
models.append(('CART', DecisionTreeClassifier()))
models.append(('NB', GaussianNB()))
models.append(('SVM', SVC()))
# evaluate each model in turn
results = []
names = []
for name, model in models:
    kfold = model_selection.KFold(n_splits=10, random_state=seed)
    cv_results = model_selection.cross_val_score(model, X_train, Y_train, cv=kfold, scoring=scoring)
    results.append(cv_results)
    names.append(name)
    msg = "%s: %f (%f)" % (name, cv_results.mean(), cv_results.std())
    print(msg)

A execução dos modelos:

 O que ao ser executado, produz o seguinte resultado:
LR: 0.966667 (0.040825)
LDA: 0.975000 (0.038188)
KNN: 0.983333 (0.033333)
CART: 0.966667 (0.040825)
NB: 0.975000 (0.053359)
SVM: 0.991667 (0.025000)

Note que estes resultados podem variar dentre uma execução e outra, já que os algorítmos usados tem uma certa randomicidade.
Pelo resultado mostrado acima, dos algorítmos utilizados, o que produziu o melhor resultado foi o SVM, pois ele teve o melhor resultado de acurácia, além de ter o menor desvio padrão dos resultados produzidos.
Para comparar o resultado dos algorítmos, vamos plotar um gráfico com a média dos resultados
fig = plt.figure()
fig.suptitle('Algorithm Comparison')
ax = fig.add_subplot(111)
plt.boxplot(results)
ax.set_xticklabels(names)
plt.show()
Isto produz o gráfico abaixo:
No gráfico acima temos, uma caixa com o valores de acurácia, do menor para o maior, mais uma linha marcando a mediana. Veja que tanto o KNN, quando NB e o SVM tiveram um resultado bem próximos, segundo o gráfico, mas voltando a análise do resultado, lembramos que o SVM produziu o melhor resultado.

Fazendo Previsões

Como vimos que o SVM foi o melhor algorítmo, agora chegou a hora de comparar os resultados obtidos, com o nosso dataset de teste, nele iremos executar a previsão com a melhor configuração do algorítmo e comparar o resultado com o obtido anteriormente.
svm = SVC()
svm.fit(X_train, Y_train)
predictions = svm.predict(X_validation)
print(accuracy_score(Y_validation, predictions))
print(confusion_matrix(Y_validation, predictions))
print(classification_report(Y_validation, predictions))
Ao executar esta predição, temos como resultado a seguinte:
curácia0.9333333333333333
Matriz de Confusão[ [ 7  0  0]
  [ 0 10  2]
  [ 0  0 11]]
Relatório de ClassificaçãoIris-setosa             1.00      1.00      1.00         7
Iris-versicolor       1.00      0.83      0.91        12
Iris-virginica         0.85      1.00      0.92        11
    avg / total       0.94      0.93      0.93        30
Acurária, é o quão perto do esperado, o nosso resultado ficou, então estamos com 93% de acerto, o que é algo muto bom.
A Matriz de confusão, é um termo estatístico, utilizado no campo de Machine Learning e ele serve para plotar os resultados e acertos de um algorítmo de classificação, neste caso temos:
                     S   VC  VI
Setosa         [ 7    0      0]
Versicolor   [ 0   10     2]
Virginica     [ 0    0    11] 
Na linha de cima, no cabeçalho, S representa Setosa, VC representa Versicolor e VI representa Virginica. Nesta matrix, temos que das 7 Setosa, o algorítmo acertou todas, das 10 Versicolor, ele acertou todas e finalmente, das 11 Virginicas, ele aertou 11 e classificou 2 delas como Versicolor.
Já no relatório de classificação temos:
                           precision    recall  f1-score   support    Iris-setosa              1.00      1.00        1.00             7Iris-versicolor            1.00      0.83        0.91           12 Iris-virginica             0.85      1.00        0.92           11    avg / total               0.94      0.93        0.93          30Precisão é o cálculo da porcentagem de acertos dos Verdadeiramente Positivos, dividido pelos falso positivos, já Recall é o cálculo dos Verdadeiramente Positivos, dividido pelos falso negativos.
F1-score é um cálculo envolvendo a divisao dos Verdadeiramente Positivos, dividido pela soma dos Verdadeiramente positivos, mais os falso negativos mais os falso positivos.
Support é a ocorrência de cada valor em cada um dos tipos dos atributos.

Conclusão

Neste post foi mostrado como fazer previsão de classificação, de um dataset de flores, em uma predição supervisionada, ou seja, sabíamos qual era o resultado esperado, e por isto, conseguimos quantificar exatamente a quantidade de acertos.
A partir daqui, você pode pegar outros datasets, e executar outros testes dos algorítmos, este post foi uma exposição bem simples de como fazer previsões, usando o python.
Consideramos aqui, que é uma operação de classificação, já que estamos tentando definir, a partir dos dados, qual é o tipo de flor.

Bibliografia

Texto original

Apresentação
Apresentação2