Auto Machine Learning: O que é, aplicações e desafios

Bruno Borges
Ensina.AI
Published in
18 min readMar 14, 2020

O crescente sucesso do machine learning em diversas aplicações, como finanças, publicidade, saúde, sistemas de recomendação, people analytics etc, tem atraído a atenção de pesquisadores e empresas que buscam aproveitar o poder de grandes quantidades de dados produzidos todos os dias em nosso mundo digital. Em geral, o processo de construção de um modelo de machine learning de alta qualidade é um processo iterativo, complexo e demorado (veja a figura abaixo), e envolve a tentativa de diferentes algoritmos (SVC, Random Forest, Redes Neurais e muitos outros) e técnicas de pré-processamento, além de ter uma boa experiência com o ajuste eficaz de seus hiperparâmetros.

Pipeline de machine learning

Com o objetivo de automatizar partes, ou até mesmo toda a pipeline de construção de um modelo de machine learning, foi desenvolvido o conceito de Auto Machine Learning. Existem diversas ferramentas de AutoML como Auto-sklearn, TPOT, Autokeras, H2O AutoML, AutoWeka dentre outros, que estão em ativo desenvolvimento atualmente. O AutoML é uma tecnologia de AI bastante promissora para os próximos anos (como pode ser observado no gráfico de tendências de AI da Gartner) e com certeza terá papel fundamental na ciência de dados nos próximos anos.

Como observado no gráfico de tendências de ferramentas de Ai para 2019, o AutoMl está no pico de expectativas infladas e a tecnologia em seu estado pleno deve ser alcançada entre 2 e 5 anos.

Neste texto iremos estudar:

  1. O problema CASH (seleção combinada de algoritmos e otimização de hiperparâmetros), problema fundamental do AutoML, onde serão comparadas as técnicas de otimização bayesiana, algoritmos genéticos, Grid e Random Search;
  2. Aplicar as principais ferramentas de AutoML;
  3. Compreender limitações atuais e desafios para implementação de tal ferramenta.

Tuning de hiperparâmetros

Nos últimos anos, várias técnicas foram introduzidas para enfrentar o desafio de automatizar o processo de CASH no domínio de aprendizado de máquina. O problema de CASH é encontrar um algoritmo e a versão otimizada de tal algoritmo, de tal forma que o modelo alcance o mais alto desempenho de generalização na base de treino e o mais alta avaliação na base de teste.

Técnicas de CASH geralmente são formulados como um problema de otimização que pode ser resolvido por uma ampla variedade de técnicas. Com objetivo de avaliá-las, vamos aplicá-las numa base de dados reais, a base Breast Cancer Wisconsin (Diagnostic) Data Set. Usando a linguagem python, vamos primeiramente importar todas as bibliotecas necessárias e fazer a divisão entre base de treino e teste.

import pandas as pd #leitura e manipulação de dataframes
import numpy as np
from sklearn.preprocessing import LabelEncoder,StandardScaler #normalização
from tpot import TPOTClassifier, TPOTRegressor #ferramente de autoML TPOT
from deap.gp import Primitive
import time
import tensorflow.keras as keras
from kerastuner.tuners import BayesianOptimization #tuning de redes neurais
from keras.callbacks import ModelCheckpoint, TensorBoard, EarlyStopping
from sklearn import metrics
import tensorflow as tf
from sklearn.svm import SVC
import warnings
warnings.filterwarnings(“ignore”)
from sklearn.ensemble import RandomForestClassifier
base = pd.read_csv(‘https://archive.ics.uci.edu/ml/machine-learning-databases/breast-cancer-wisconsin/wdbc.data', sep=’,’, header=None)#colunas da base
preditores = [‘id’,’diagnostic’,’ radius_mean’, ‘ texture_mean’, ‘ perimeter_mean’, ‘ area_mean’,
‘ smoothness_mean’, ‘ compactness_mean’, ‘ concavity_mean’,
‘concave_points_mean’, ‘ symmetry_mean’, ‘ fractal_dimension_mean’,
‘ radius_se’, ‘ texture_se’, ‘ perimeter_se’, ‘ area_se’,
‘ smoothness_se’, ‘ compactness_se’, ‘ concavity_se’,
‘ concave_points_se’, ‘ symmetry_se’, ‘ fractal_dimension_se’,
‘ radius_worst’, ‘ texture_worst’, ‘ perimeter_worst’, ‘ area_worst’,
‘ smoothness_worst’, ‘ compactness_worst’, ‘ concavity_worst’,
‘ concave_points_worst’, ‘ symmetry_worst’, ‘ fractal_dimension_worst’]
base.columns = preditores
#y é a classe e X as variáveis dependentes
X = base.drop([‘id’,’diagnostic’], axis=1).values
classe = base[‘diagnostic’].values
labelencoder_classe = LabelEncoder() #converte para zeros e uns
y = labelencoder_classe.fit_transform(classe)
#normalização dos dados
scaler = StandardScaler()
X = scaler.fit_transform(X)
pd.DataFrame(X).describe()
#divisão entre treino (80%) e teste (20%)
from sklearn.model_selection import train_test_split
X_treinamento, X_teste, y_treinamento, y_teste = train_test_split(X, y,
test_size = 0.2,
random_state = 42)

Grid Search e Random Search

São métodos de busca exaustiva. No Grid Search, o cientista de dados configura um conjunto de hiperparâmetros em que o algoritmo deverá procurar o conjunto que leva ao melhor score. Cada combinação de valores é testada, o que pode ser bastante ineficiente se o número de configurações de hiperparâmetros for muito grande. Já o Random Search configura uma grade de valores de hiperparâmetros e seleciona combinações aleatórias para treinar o modelo. Isso permite controlar explicitamente o número de combinações de hiperparâmetros que são testadas. O número de iterações a ser pesquisada é baseado no tempo ou recursos configurados.

O Random Search geralmente pega resultados tão bons quando o Grid Search, em uma fração do tempo que leva este último. O motivo é que o Random Search costuma explorar diferentes “lugares” na grade de hiperparâmetros configurados, como pode ser visto na figura abaixo.

Grid Search e Random Search

O scikit-learn oferece os dois métodos que vimos para otimização por busca exaustiva, o RandomSearchCV e GridSearchCV. Vamos utilizá-los para otimizar os hiperparâmetros do algoritmo Random Forest, onde o objetivo é maximizar a acurácia de previsão.

#conjunto de hiperparâmetros a ser utilizado
n_estimators = [int(x) for x in np.linspace(start = 200, stop = 2000, num = 10)]
max_features = ['auto', 'sqrt']
max_depth = [int(x) for x in np.linspace(10, 110, num = 11)]
max_depth.append(None)
min_samples_split = [2, 5, 10]
min_samples_leaf = [1, 2, 4]
bootstrap = [True, False]
random_grid = {'n_estimators': n_estimators,
'max_features': max_features,
'max_depth': max_depth,
'min_samples_split': min_samples_split,
'min_samples_leaf': min_samples_leaf,
'bootstrap': bootstrap}

#usando um método de cross-validation com 5 partes. Número de iteraçãos =100
RandomizedSearchCV(cv=5, estimator=rfc, param_distributions=random_grid,
n_iter=100, verbose=2, n_jobs=-1)

clf_RS = RandomizedSearchCV(rfc, random_grid, random_state=42).fit(X,y)

GridSearchCV(cv=5, estimator=rfc, param_grid=random_grid, verbose=2, n_jobs=-1)
clf_GS = RandomizedSearchCV(rfc, random_grid, random_state=42).fit(X,y)

#exibindo e aplicando os melhores parâmetros
params_RS = clf_RS.best_params_
params_GS = clf_GS.best_params_
clf1 = RandomForestClassifier(**params_RS)
clf2 = RandomForestClassifier(**params_GS)

Fazendo o ajuste dos modelos otimizados para a base de treino, chegamos a uma acurácia de 96,49% para ambos otimizados via Random e Grid Search. Como Random Search é mais eficiente, seu tempo de execução foi relativamente menor que o segundo, levando menos de 2 minutos de execução contra 10 minutos do Grid Search.

Otimização Bayesiana

É um algoritmo de otimização baseado no teorema de Bayes. Tem como objetivo encontrar o ótimo global de uma função de maneira eficiente. Para otimização de hiperparâmtros, segue-se da seguinte maneira:

  1. Pelo teorema de Bayes, a probabilidade condicional do evento A, dado que ocorreu o evento B, pode ser calculado como P(A|B) = P(B|A)*P(A)/P(B). A probabilidade condicional P(A|B) é conhecida como probabilidade a posteriori, P(B|A) a função de verossimilhança e P(A) como a probabilidade a priori;
  2. Coletamos amostras (x1, x2, … ,xn) que serão um conjunto de configuração dos hiperparâmetros do modelo e calculamos o valor da função f para estas amostras, que retornará o score do modelo avaliada por uma determinada métrica. As amostras e resultados da função são coletados sequencialmente e definem nossos dados D.
  3. A ideia é que devemos estimar a probabilidade a posteriori P(f|D), ou seja, a probabilidade da função estimada f ser a função que minimiza (ou maximiza) o score do modelo.
  4. Para construir uma distribuição a posteriori, usamos uma função substituto (surrogate function). A função substituto é uma técnica usada para melhor aproximar o mapeamento de exemplos de entrada a um score de saída. Um método conhecido é o Processo Gaussiano (GP), que melhor descreve a função que você deseja otimizar. À medida que o número de observações aumenta (conjunto D), a distribuição a posteriori melhora e o algoritmo torna-se mais certo de quais regiões no espaço de parâmetros valem a pena explorar e quais não são, como pode ser visto na figura abaixo.
Otimização Bayesiana em diversas épocas

A biblioteca skopt pode ser utilizada para minimizar (ou maximizar) funções complexas de maneira eficiente. Da mesma maneira que fizemos anteriormente, vamos otimizar o algoritmo Random Forest com a abordagem Bayesiana, utilizando o método gp_minimize, que usa o processo gaussiano para construir a distribuição a posterior.

model = RandomForestClassifier()
# definindo o espaço de hiperparâmetros para procurar
search_space = [Integer(200, 2000, name='n_estimators'),
Categorical(['auto', 'sqrt'], name='max_features'),
Integer(10, 110, name='max_depth'),
Integer(2, 10, name='min_samples_split'),
Integer(1, 4, name='min_samples_leaf'),
Categorical([True, False], name='bootstrap')]


# definindo a função para ser otimizada
@use_named_args(search_space)
def evaluate_model(**params):
model.set_params(**params)
# calculando o cross-validation com 5 folds
model.fit(X_treinamento,y_treinamento)
y_hat = model.predict(X_teste)
# calculando a média dos scores
estimate = metrics.accuracy_score(y_pred=y_hat, y_true=y_teste)
return 1.0 - estimate

# aplicando a otimização via processo gaussiano
result = gp_minimize(evaluate_model, search_space)

# resumindo os resultados:
print('Best Accuracy: %.5f' % (1.0 - result.fun))
print({'n_estimators': result.x[0], 'max_features': result.x[1], 'max_depth': result.x[2], 'min_samples_split':result.x[3],
'min_samples_leaf': result.x[4], 'bootstrap': result.x[5]})

A acurácia foi a mesma que obtivemos pelos métodos de busca exaustiva que vimos acima. O tempo de execução do algoritmo foi o menor até agora, o que demonstra a eficiência da otimização bayesiana.

Vamos agora fazer outra aplicação para otimizar arquiteturas de redes neurais. O kerasTuner é uma biblioteca bastante flexível, permitindo configurar todos os hiperparâmetros da rede neural, inclusive números de camadas e neurônios por camada. A função do código abaixo retorna o modelo compilado:

def tune_nn_model(hp):
modelo = keras.Sequential()
#configurando o número de neurônios na primeira camada
units1 = hp.Int(
'units_' + str(1),
min_value=8,
max_value=64,
step=8)
modelo.add(keras.layers.Dense(units=units1,
activation="relu",
input_shape=[X_treinamento.shape[1]]))

#configurando o número de camadas ocultas e neurônios por camada
for i in range(hp.Int('num_layers', 2, 6)):
units = hp.Int(
'units_' + str(i),
min_value=8,
max_value=64,
step=8
)
modelo.add(keras.layers.Dense(units=units, activation='relu'))
#configurando a taxa de dropout
drop_rate = hp.Choice('drop_rate_' + str(i),
[
0.0, 0.1, 0.2, 0.3, 0.4,
])
modelo.add(keras.layers.Dropout(rate=drop_rate))

#configurando o otimizador
modelo.add(keras.layers.Dense(1, activation='sigmoid'))
optimizers = hp.Choice('optimizers' + str(i), ['Adam','Nadam'])

#compilando o modelo com a métrica acurácia
modelo.compile(
optimizer=optimizers,
loss = 'binary_crossentropy',
metrics = ['accuracy'])
return modelo

Utilizaremos o método BayesianOptimization com no máximo 40 épocas e 6 execuções por época:

#tuning via otimização bayesiana
b_tuner = BayesianOptimization(
tune_nn_model,
objective='accuracy',
max_trials=40,
directory='test_dir10',
project_name='b_tune_nn',
executions_per_trial=6,
seed=42)

# callback earlystopping com 10 épocas de paciência
earlyStopping=EarlyStopping(monitor='val_loss', patience=10, verbose=1, mode='auto')
a=time.time()

#procura da melhor arquitetura
b_tuner.search(X_treinamento, y_treinamento,
epochs=100, callbacks=[earlyStopping],
validation_data=(X_teste, y_teste))

#seleciona-se as três melhores arquiteturas
modelos = b_tuner.get_best_models(num_models=3)

$resumindo os resultados
prediction = modelos[1].predict(X_teste)
prediction = prediction>0.5
score_BNN = metrics.accuracy_score(y_pred=prediction, y_true=y_teste)
print('O score é:', score_BNN)

modelos[0].summary()

O tempo de execução foi de aproximadamente 10 min. A figura abaixo contém um resumo da rede neural otimizada, com 5 camadas ocultas e 40, 32, 40, 56 e 16 neurônios, respectivamente. A acurácia obtida foi de 98,24%. o melhor resultado até agora.

Rede neural otimizada via abordagem bayesiana

Algoritmo genético

É um algoritmo de otimização via meta-heurística, da mesma classe de algoritmos como otimização de colônias de formigas, recozimento simulado, busca tabu e otimização de enxame de partículas (seria interessante dizer ao seu chefe que usou colônia de formigas para otimizar seu modelo). Uma heurística é um método iterativo que busca boas soluções viáveis para um problema, mas não garante a obtenção de uma solução global. Algoritmos heurísticos que têm a capacidade de explorar diferentes regiões do espaço da solução, com o objetivo de escapar de ótimos locais, são chamados de meta-heurísticas. As meta-heurísticas são usadas quando se tem poucas informações a respeito da função, ou são muito complexas (não é diferenciável ou contínua, por exemplo). Nesse caso, métodos tradicionais de otimização não são aplicáveis .

O algoritmo genético abduz o processo de seleção natural de Darwin e funciona da seguinte maneira:

  1. Initial Population — É inicializado aleatoriamente um conjunto de indivíduos que formará nossa população. No nosso caso, os indivíduos são os modelos com parâmetros escolhidos aleatoriamente;
  2. Fitness — Devemos testar essa população em um ambiente hostil. Somente alguns indivíduos vão sobreviver. Você pode criar um ambiente hostil simplesmente estabelecendo um mínimo para o score do modelo;
  3. Crossover e Mutation Define os critérios para a próxima geração. Na etapa de crossover, os genes (hiperparâmetros) dos pais serão recombinados, para produzir filhos, cada filho herdando alguns genes de cada pai. Para manter a diversidade, adicionamos um pouco de mutação nos filhos;
  4. OffspringA próxima geração conterá os pais sobreviventes e os filhos, mantemos os pais sobreviventes para manter os melhores genes, caso o valor dos genes do filho seja pior que os pais. O processo é repetido até que os indivíduos da última geração sejam os mais bem evoluídos.
Esquema gráfico do funcionamento de um algoritmo genético

A biblioteca mais amigável para a implementação de algoritmos genéticos é a TPOT, que avalia todos os tipos de pipelines possíveis de forma automática e eficiente usando algoritmo genético. Pode ser considerado um método de auto-ml tal como o auto-sklearn e auto-keras. Para efeitos de comparação, vamos criar uma aplicação restringindo o espaço de busca para o mesmo que vimos no dois métodos de busca anteriores. Iniciaremos com uma população de 50 indivíduos e, com fator de mutação 0.7 e taxa crossover 0.3, deve gerar 250 descendentes a cada geração, até a quinta geração:

#configurando os parâmetros do algoritmo genétio
tpot_classifier = TPOTClassifier(generations=5, population_size=50, offspring_size=250,
early_stop=8,
config_dict={'sklearn.ensemble.RandomForestClassifier': random_grid},
cv = 5, scoring = 'accuracy', mutation_rate = 0.7,
crossover_rate=0.3, verbosity=2, max_eval_time_mins=2, n_jobs=-1)

#aplicando o classificador na base de dados
tpot_classifier.fit(X,y.ravel())

A otimização via meta-heurística genética apesar de ter sido lenta (20 minutos de execução), teve resultado melhor que os outros métodos para otimizar o Random Forest, obtendo uma acurácia de 97,36%, o que confirma a capacidade dos algoritmos genéticos de encontrar máximos globais.

Com relação à arquiteturas de redes neurais, podemos usar a biblioteca NeuroEvolution que, apesar de não ser tão flexível quanto o KerasTuner, é relativamente mais simples de configurar.

#definido os parâmetros da rede
params = {
"epochs": [50],
"batch_size": [4,8,16,32,64],
"n_layers": [3, 4, 5, 6, 7],
"n_neurons": [10, 20, 40, 60, 80],
"dropout": [0,0.1, 0.2],
"optimizers": ["nadam", "adam"],
"activations": ["relu", "sigmoid"],
"last_layer_activations": ["sigmoid"],
"losses": ["binary_crossentropy"],
"metrics": ["accuracy"]
}



'''aplicando um algoritmo genético com 20 gerações e população inicial com 30 indívduos'''

search = evolution.NeuroEvolution(generations = 20, population = 30, params=params)
search.evolve(X_treinamento, y_treinamento, X_teste, y_teste)

Após 20 gerações e 30 minutos de execução, obtemos uma rede neural com 4 camadas ocultas, 20 neurônios por camada, tamanho do batch =16, taxa de dropout = 0.2, otimizador Adam e funções de ativação sigmoide. A acurácia obtida foi de 99.1%, um score superior a todos os modelos que vimos até agora.

Auto-sklearn, Auto-keras e TPOT: Machine e Deep learning com 4 linhas de código

As bibliotecas auto-sklearn e auto-keras tem a missão de tornar mais fácil a codificação de algoritmos de machine learning. Basicamente tentam automatizar quase tudo, desde a o pre-processamento dos dados a escolha dos melhores modelos e hiperparâmetros.

Auto-sklearn

O Auto-sklearn é o resultado de uma pesquisa na Universidade de Freiburg e foi introduzido por Feurer et al. em 2015 no NIPS, disponível aqui.Em contraste com o Auto-Keras, ele não se concentra na busca de redes neurais profundas, mas usa a otimização bayesiana para ajuste de hiperparâmetros para algoritmos “tradicionais” de aprendizado de máquina implementados no scikit-learn, além de ter suporte ao XGBoost.

Resumidamente, o auto-sklearn funciona da seguinte maneira:

Esquema gráfico d funcionamento do auto-sklearn
  1. Etapa de meta-aprendizado para iniciar rapidamente o procedimento de otimização bayesiana, o que resulta em um aumento considerável na eficiência. A área de meta-aprendizagem aprende sobre o desempenho dos algoritmos de machine learning, raciocinando sobre o desempenho dos algoritmos de aprendizagem nos conjuntos de dados. O meta-aprendizado é usado para selecionar instâncias de nossa estrutura de aprendizado de máquina que provavelmente apresentem bom desempenho em um novo conjunto de dados. Mais especificamente, para um grande número de conjuntos de dados, são coletados dados de desempenho e um conjunto de meta-features, ou seja, características do conjunto de dados que podem ser computadas com eficiência e que ajudam a determinar qual algoritmo usar em um novo conjunto de dados.
  2. Etapa de construção automatizada do conjunto, permitindo usar todos os classificadores encontrados pela otimização bayesiana. O meta-aprendizado pode sugerir rapidamente algumas instanciações da estrutura de ML que provavelmente têm um desempenho muito bom, mas é incapaz de fornecer informações detalhadas sobre desempenho. Por outro lado, a otimização bayesiana é lenta para iniciar em espaços de hiperparâmetros tão grandes quanto os de estruturas inteiras de ML, mas pode ajustar o desempenho ao longo do tempo. Explorando tal complementariedade, selecionando configurações baseadas em meta-aprendizado e usando esses resultados para propagar a otimização bayesiana.
  3. Etapa de ensemble para armazenar os melhores modelos selecionado pela otimização bayesiana, usando um método eficiente de pós-processamento (que pode ser executado em um segundo processo on-the-fly) para construir um conjunto a partir deles. Essa construção automática do conjunto evita comprometer-se com uma única configuração de hiperparâmetros e, portanto, é mais robusta (e menos propensa a overfitting) do que usar a estimativa pontual (apenas o melhor modelo) que a otimização padrão de hiperparâmetros produz.

O auto-sklearn é licenciado da mesma maneira que o scikit-learn e está apenas disponível para linux. Com apenas 4 linhas é possível codar um modelo de machine learning com essa biblioteca:

import autosklearn.classification
>>> cls = autosklearn.classification.AutoSklearnClassifier()
>>> cls.fit(X_treinamento, y_treinamento)
>>> predictions = cls.predict(X_teste)

Auto-keras

O auto-keras foi criado por François Chollet e foi o primeiro passo sério para facilitar o Deep Learning para todo mundo. O método para otimização é o mesmo para o auto-sklearn, a otimização bayesiana, e também tenta automatizar as etapas de pré e pós processamento. A implementação do auto-keras pode ser feita simplesmente escrevendo

import autokeras as akclf = ak.StructuredDataClassifier(verbose=True, augment=False)
# ajuste do modelo
clf.fit(x_treinamento, y_treinamento, time_limit= 60 * 60)
clf.final_fit(x_treinamento, y_treinamento, x_teste, y_teste, retrain=True)
# resumindo os resultados
y = clf.evaluate(x_teste, y_teste)

Após 5 minutos de processamento, o score obtido pelo Autokeras foi de 96,49%, um valor relativamente baixo comparado ás arquiteturas de redes neurais testadas anteriormente. O Auto-sklearn levou cerca de 30 minutos e resultou em uma acurácia de 97.36%, um resultado também aquém do que já obtivemos em outros algoritmos. Isso demonstra que o auto-sklearn e o autokeras ainda precisam de melhorias e não deve ser usado como única ferramenta de machine learning atualmente, e sim como um método auxiliar.

TPOT

A ferramenta de autoML TPOT (Tree-Based Pipeline Optimization Tool) é de código aberto, bem documentado e em desenvolvimento ativo. Seu desenvolvimento foi liderado por pesquisadores da Universidade da Pensilvânia. Foi criado sobre a biblioteca scikit-learn e usa o otimização via abordagem genética para otimização.

Esquema gráfico do funcionamento do TPOT

O poder do TPOT vem da avaliação de todos os tipos de pipelines possíveis de forma automática e eficiente, automatizando as partes de seleção, processamento e construção de features, além da seleção de modelo e otimização de hiperparâmetros. Pode ser implementado da seguinte maneira:

#configurando os parâmetros do algoritmo genétio
tpot_classifier = TPOTClassifier(generations=5, population_size=50, offspring_size=250, early_stop=8,
cv = 5, scoring = 'accuracy', mutation_rate = 0.7,
crossover_rate=0.3, verbosity=2, max_eval_time_mins=2, n_jobs=-1)
#aplicando o classificador na base de dados
tpot_classifier.fit(X,y.ravel())

Diversas aplicações do TPOT em datasets famosos podem ser encontradas aqui. Para a base de dados Breast Cancer Data, o resultado é uma acurácia de 99,12% (excelente!) e a figura abaixo resume a pipeline otimizada:

O que essa pipeline faz é o seguinte:

  • Ajusta todas as features originais usando GaussianNB (Naive Bayes Gaussiano);
  • Pega as previsões do GaussianNB e cria uma nova feature usando essas previsões;
  • Ajusta as features originais mais a nova “feature” com o SGDClassifier (Classificador de Descida do Gradiente Estocástica) e use suas previsões como as previsões finais do pipeline. Esse processo é chamado de stacking classifier, que é uma tática bastante comum em machine learning.

H2O AutoML

O uso da biblioteca H2O é cada vez maior e facilita a experiência de machine learning e deep learning para não especialistas. Com o objetivo de criar uma ferramenta que consiga automatizar o tuning e seleção de diversos modelos da biblioteca, foi desenvolvido o H2o AutoML. Diferente das outras bibliotecas de autoML apresentadas, o H2o AutoML inclui tanto algoritmos clássicos de ML quanto redes neurais, e até mesmo XGboost, GBM e GLM, tornando-a bastante robusta na seleção de algoritmos.

Usando a linguagem R, vamos fazer uma pipeline desta ferramente usando a base Breast Cancer Data:

library(h2o) #importa a biblioteca h2o
h2o.init() #inicia num servidor local#importando a base de dados
base<-h2o.importFile('https://archive.ics.uci.edu/ml/machine-learning-databases/breast-cancer-wisconsin/wdbc.data')#divindo a base em treino e teste
base.split <- h2o.splitFrame(data=base, ratios=0.75)base.train <- base.split[[1]] #base de treino
base.test <- base.split[[2]] #base de teste
# Para classificação binária, a resposta deve ser um fator
base.train[,'C2'] <- as.factor(base.train[,'C2'])
base.test[,'C2'] <- as.factor(base.test[,'C2'])colunas <-names(base.train)#exclui a coluna resposta nas variáveis preditoras
colunas_treino <-colunas[!colunas %in% c('C2')]#o algoritmo deve processar no máximo 20 modelos
aml <- h2o.automl(x = colunas_treino, y = 'C2',
training_frame = base.train,
max_models = 20,
seed = 42)#tabela dos melhores algoritmos
lb <- aml@leaderboard
print(lb, n = nrow(lb))#medindo a acurácia do melhor modelo
perf <-h2o.performance(aml@leader, base.test)
max(h2o.accuracy(perf)[,2])

Na tabela abaixo obtemos os melhores algoritmos, de acordo com a métrica AUC. Os 4 melhores resultados são arquiteturas de redes neurais. Para fins de comparação, o H2o AutoML levou aproximadamente 1 hora de processamento, e obteve uma acurácia de 98,64%, um resultado bastante expressivo.

Leaderboard de algoritmos

Desafios do Auto Machine Learning

As bibliotecas atuais de auto machine learning ainda não são capazes de superar a avaliação de um modelo criado manualmente por um cientista de dados, mas essas bibliotecas estão em ativo desenvolvimento e devem ter um salto em perfomance e eficiência num futuro próximo. Futuras melhorias devem focar na:

  1. Escalabilidade — Na prática, uma das principais limitações das estruturas centralizadas para automatizar as soluções para o problema CASH é que elas estão fortemente incorporada a uma biblioteca de aprendizado de máquina (por exemplo, Weka, scikit-learn, R ) e tais bibliotecas não são aplicáveis no caso de grandes volumes de dados;
  2. Técnicas de otimização — estruturas diferentes do AutoML usam técnicas diferentes para otimização de hiperparâmetros dos algoritmos de aprendizado de máquina. Na prática, é difícil encontrar um vencedor claro e deve-se avaliar os prós e contras de tais algoritmos antes de fazer o treinamento;
  3. Orçamento de tempo — Um parâmetro importante comum para os sistemas AutoML é o orçamento de tempo do usuário para aguardar antes de obter a pipeline recomendada. Claramente, quanto maior o orçamento de tempo, maior a chance do sistema AutoML explorar várias opções no espaço de pesquisa e maior a probabilidade de obter uma recomendação melhor. No entanto, quanto maior o orçamento de tempo usado, maior o tempo de espera e maior consumo de recursos de computação, que poderiam ser convertidos em uma fatura monetária mais alta no caso de usar recursos baseados em nuvem;
  4. Concordância — Atualmente, várias soluções de aprendizado de máquina se tornaram populares. No entanto, essas soluções de ML variam significativamente em suas técnicas disponíveis (por exemplo, algoritmos de aprendizado, pré-processadores e seletores de recursos) para suportar cada fase do pipeline de aprendizado de máquina. Claramente, a qualidade dos pipelines de aprendizado de máquina que podem ser produzidos por qualquer uma dessas plataformas depende da disponibilidade de várias técnicas que podem ser utilizados em cada etapa do pipeline. Na prática, é muito desafiador ter implementações otimizadas para todos os algoritmos das diferentes etapas da pipeline de machine learning disponíveis em um único pacote ou biblioteca.
  5. Pipeline de entrega contínua — a entrega contínua é definida como a criação de um processo repetível, confiável e de aprimoramento incremental para levar o software do conceito ao cliente. Isto ainda é um desafio para a aplicação do AutoML;
  6. Preparação de dados — Na prática, há uma necessidade crucial de automatizar o processo de extração de features, pois é considerado uma das partes mais demoradas do pipeline (Cientista de dados gastam em média 80% do tempo na preparação de dados). Na prática, a maioria dos sistemas negligencia a automação da transformação de features usando análise de componentes principais (PCA) ou a análise discriminante linear (LDA) e o quanto eles melhoram o desempenho do modelo.

Talvez muitos se perguntem qual será o papel do cientista de dados num cenário em que a IA pode automatizar até mesmo a construção de uma pipeline de ML. Isso não deve eliminar o papel do cientista de dados, e sim levá-lo a tarefas mais criativas. Ser um cientista de dados vai muito além de construir um pipeline de ML. Lembre-se que foram o surgimento de diversas bibliotecas que facilitam o treinamento e a implementação de algoritmos complexos, como redes neurais e random forest, que tornou possível a aplicação de modelos de machine e deep learning no mundo corporativo.

Um cientista de dados ainda terá como tarefas

  • Entender e estruturar um determinado problema relacionado à ciência de dados;
  • Encontrar melhores práticas, ideias e ferramentas para solucionar tal problema;
  • Aperfeiçoar, interpretar e comunicar os resultados com outros membros da equipe.

Tais tarefas dificilmente serão automatizadas num futuro próximo e o uso do AutoML pode gerar um salto na melhoria na generalização e avaliação de futuros modelos, tornando a contratação de um cientista de dados uma ideia ainda mais atrativa.

Futuro da inteligência Artificial

Para finalizar, no livro Superintelligence, Nick Bostrom escreve sobre as diversas maneiras para o surgimento de uma superinteligência artificial. Num dos cenários, os humanos criam uma AI embrionária, uma inteligência que aperfeiçoa a si própria. Esse é um exemplo de meta-aprendizagem, o processo de aprender a partir de uma experiência de aprendizagem anterior, adquirida durante a aplicação de vários algoritmos de aprendizado em diferentes tipos de situações. Atualmente, a AI cresce continuamente, mas o acelerador de desenvolvimento ainda continua sendo humano. Há diversas fontes de dados, e diferentes casos de aplicações de técnicas de ML, que podem usadas como um meta-base para que futuros algoritmos de meta-aprendizagem possam também colaborar para acelerar o desenvolvimento da AI.

Sugestão de leituras

  1. Automated Machine Learning: State-of-The-Art and Open Challenges
  2. How to Implement Bayesian Optimization from Scratch in Python
  3. Hyperparameter tuning in XGBoost using genetic algorithm
  4. AutoML: The Next Wave of Machine Learning
  5. Superintelligence: Paths, Dangers, Strategies. Nick Bostrom, 2014

--

--

Bruno Borges
Ensina.AI

Cientista de dados formado em engenheiria de produção e matemática aplicada.