Introdução
Fico feliz em relatar um novo grande lançamento de lime
pousou em Cran. lime
é uma porta R da biblioteca Python com o mesmo nome de Marco Ribeiro que permite ao usuário retirar os modelos de aprendizado de máquina de máquina preta aberta e explicar seus resultados em base por observação. Ele funciona modelando o resultado da caixa preta no bairro native em torno da observação para explicar e usar esse modelo native para explicar por que (não como) a caixa preta fez o que fez. Para mais informações sobre a teoria de lime
Vou direcioná -lo para o artigo
Apresentando a metodologia.
Novos recursos
A carne deste lançamento centra -se em torno de dois novos recursos que estão um pouco ligados: suporte nativo para modelos Keras e suporte para explicar modelos de imagem.
keras e imagens
JJ Allaire teve a gentileza de nomear lime
Durante sua palestra, introdução do tensorflow
e keras
Pacotes e eu me senti compelido a apoiá -los nativamente. Como Keras é de longe a maneira mais standard de interagir com o TensorFlow, é o primeiro da linha para o suporte a construção. A adição de Keras significa que
lime
Agora suporta modelos diretamente dos pacotes a seguir:
Se você está trabalhando em algo muito obscuro ou de ponta para não poder usar esses pacotes, ainda é possível tornar seu modelo lime
compatível por fornecer predict_model()
e model_type()
Métodos para isso.
Os modelos Keras são usados como qualquer outro modelo, passando -o para o lime()
Função junto com os dados de treinamento para criar um objeto explicador. Como emblem vamos falar sobre modelos de imagens, usaremos um dos modelos Imagenet pré-treinados que estão disponíveis no próprio Keras:
Mannequin
______________________________________________________________________________________________
Layer (sort) Output Form Param #
==============================================================================================
input_1 (InputLayer) (None, 224, 224, 3) 0
______________________________________________________________________________________________
block1_conv1 (Conv2D) (None, 224, 224, 64) 1792
______________________________________________________________________________________________
block1_conv2 (Conv2D) (None, 224, 224, 64) 36928
______________________________________________________________________________________________
block1_pool (MaxPooling2D) (None, 112, 112, 64) 0
______________________________________________________________________________________________
block2_conv1 (Conv2D) (None, 112, 112, 128) 73856
______________________________________________________________________________________________
block2_conv2 (Conv2D) (None, 112, 112, 128) 147584
______________________________________________________________________________________________
block2_pool (MaxPooling2D) (None, 56, 56, 128) 0
______________________________________________________________________________________________
block3_conv1 (Conv2D) (None, 56, 56, 256) 295168
______________________________________________________________________________________________
block3_conv2 (Conv2D) (None, 56, 56, 256) 590080
______________________________________________________________________________________________
block3_conv3 (Conv2D) (None, 56, 56, 256) 590080
______________________________________________________________________________________________
block3_pool (MaxPooling2D) (None, 28, 28, 256) 0
______________________________________________________________________________________________
block4_conv1 (Conv2D) (None, 28, 28, 512) 1180160
______________________________________________________________________________________________
block4_conv2 (Conv2D) (None, 28, 28, 512) 2359808
______________________________________________________________________________________________
block4_conv3 (Conv2D) (None, 28, 28, 512) 2359808
______________________________________________________________________________________________
block4_pool (MaxPooling2D) (None, 14, 14, 512) 0
______________________________________________________________________________________________
block5_conv1 (Conv2D) (None, 14, 14, 512) 2359808
______________________________________________________________________________________________
block5_conv2 (Conv2D) (None, 14, 14, 512) 2359808
______________________________________________________________________________________________
block5_conv3 (Conv2D) (None, 14, 14, 512) 2359808
______________________________________________________________________________________________
block5_pool (MaxPooling2D) (None, 7, 7, 512) 0
______________________________________________________________________________________________
flatten (Flatten) (None, 25088) 0
______________________________________________________________________________________________
fc1 (Dense) (None, 4096) 102764544
______________________________________________________________________________________________
fc2 (Dense) (None, 4096) 16781312
______________________________________________________________________________________________
predictions (Dense) (None, 1000) 4097000
==============================================================================================
Whole params: 138,357,544
Trainable params: 138,357,544
Non-trainable params: 0
______________________________________________________________________________________________
O modelo VGG16 é um modelo de classificação de imagem que foi construído como parte da competição ImageNet, onde o objetivo é classificar as imagens em 1000 categorias com a maior precisão. Como podemos ver, é bastante complicado.
Para criar um explicador, precisaremos passar os dados de treinamento também. Para dados de imagem, os dados de treinamento são realmente usados apenas para dizer ao limão que estamos lidando com um modelo de imagem, portanto, qualquer imagem será suficiente. O formato para os dados de treinamento é simplesmente o caminho para as imagens e, como a Web é executada em fotos de gatinhos, usaremos uma delas:
Como nos modelos de texto, o explicador precisará saber como preparar os dados de entrada para o modelo. Para modelos de Keras, isso significa formatar os dados da imagem como tensores. Felizmente, Keras vem com muitas ferramentas para reformular os dados da imagem:
image_prep <- perform(x) {
arrays <- lapply(x, perform(path) {
img <- image_load(path, target_size = c(224,224))
x <- image_to_array(img)
x <- array_reshape(x, c(1, dim(x)))
x <- imagenet_preprocess_input(x)
})
do.name(abind::abind, c(arrays, listing(alongside = 1)))
}
explainer <- lime(img_path, mannequin, image_prep)
Agora temos um modelo explicador para entender como a rede neural VGG16 faz suas previsões. Antes de irmos, vamos ver o que o modelo pensa de nosso gatinho:
res <- predict(mannequin, image_prep(img_path))
imagenet_decode_predictions(res)
((1))
class_name class_description rating
1 n02124075 Egyptian_cat 0.48913878
2 n02123045 tabby 0.15177219
3 n02123159 tiger_cat 0.10270492
4 n02127052 lynx 0.02638111
5 n03793489 mouse 0.00852214
Então, é muito certo sobre toda a coisa do gato. A razão pela qual precisamos usar
imagenet_decode_predictions()
é que a saída de um modelo Keras é sempre apenas um tensor sem nome:
(1) 1 1000
NULL
Estamos acostumados a classificadores conhecendo os rótulos da classe, mas esse não é o caso das Keras. Motivado por isso, lime
agora tem uma maneira de definir/substituir os rótulos da classe de um modelo, usando o as_classifier()
função. Vamos refazer o nosso explicador:
model_labels <- readRDS(system.file('extdata', 'imagenet_labels.rds', package deal = 'lime'))
explainer <- lime(img_path, as_classifier(mannequin, model_labels), image_prep)
Há também um
as_regressor()
função que dizlime
sem dúvida, o modelo é um modelo de regressão. A maioria dos modelos pode ser introspectada para ver qual tipo de modelo eles são, mas as redes neurais realmente não se importam.lime
adivinha o tipo de modelo da ativação usada na última camada (ativação linear == regressão), mas se essa heurística falhar, então
as_regressor()
/as_classifier()
pode ser usado.
Agora estamos prontos para zombar do modelo e descobrir o que faz pensar que nossa imagem é de um gato egípcio. Mas … primeiro vou ter que falar sobre mais um conceito: superpixels (prometo que vou chegar à parte da explicação daqui a pouco).
Para criar permutações significativas de nossa imagem (lembre -se, essa é a idéia central em lime
), temos que definir como fazê -lo. As permutações precisam ser substanciais o suficiente para ter um impacto na imagem, mas não tanto que o modelo não reconheça completamente o conteúdo em todos os casos – eles devem levar a um resultado interpretável. O conceito de superpixels se presta bem a essas restrições. Em suma, um superpixel é um patch de uma área com alta homogeneidade, e a segmentação de superpixel é um agrupamento de pixels de imagem em vários superpixels. Ao segmentar a imagem para explicar em superpixels, podemos ativar e desativar a área de similaridade contextual durante as permutações e descobrir se essa área é importante. Ainda é necessário experimentar um pouco, pois o número superb de superpixels depende do conteúdo da imagem. Lembre -se, precisamos que eles sejam grandes o suficiente para ter um impacto, mas não tão grande que a probabilidade de classe se torne efetivamente binária. lime
Vem com uma função para avaliar a segmentação de superpixel antes de iniciar a explicação e é recomendável brincar um pouco – com o tempo que você provavelmente terá uma ideia dos valores certos:
# default
plot_superpixels(img_path)
# Altering some settings
plot_superpixels(img_path, n_superpixels = 200, weight = 40)
O padrão é definido como um número bastante baixo de superpixels – se o sujeito de interesse for relativamente pequeno, pode ser necessário aumentar o número de superpixels para que o assunto completo não acabe em um ou alguns superpixels. O weight
O parâmetro permitirá que você torne os segmentos mais compactos, ponderando a distância espacial maior que a distância da cor. Para este exemplo, seguiremos os padrões.
Esteja ciente de que a explicação de modelos de imagem é muito mais pesada que os dados tabulares ou de texto. De fato, criará 1000 novas imagens por explicação (tamanho de permutação padrão para imagens) e as executará através do modelo. Como os modelos de classificação de imagens geralmente são bastante pesados, isso resultará no tempo de computação medido em minutos. A permutação é em lotes (padrão para 10 permutações por lote), portanto, você não deve ter medo de ficar sem RAM ou espaço de tração rígida.
clarification <- clarify(img_path, explainer, n_labels = 2, n_features = 20)
A saída de uma explicação de imagem é um quadro de dados do mesmo formato que a dos dados tabulares e de texto. Cada recurso será um superpixel e a linha Pixel do superpixel será usada como sua descrição. Geralmente a explicação só faz sentido no contexto da própria imagem, então a nova versão de
lime
também vem com um plot_image_explanation()
função para fazer exatamente isso. Vamos ver o que nossa explicação tem para nos dizer:
plot_image_explanation(clarification)
Podemos ver que o modelo, para as principais courses previstas, se concentra no gato, o que é bom, pois ambos são raças de gatos diferentes. A função da plotagem obteve algumas funções diferentes para ajudá -lo a ajustar o visible e filtra superpixels de baixa pontuação por padrão. Uma visão alternativa que coloca mais foco nos superpixels relevantes, mas take away o contexto pode ser visto usando
show = 'block'
:
plot_image_explanation(clarification, show = 'block', threshold = 0.01)
Embora não seja tão comum nas explicações da imagem, também é possível olhar para as áreas de uma imagem que contradiz a classe:
plot_image_explanation(clarification, threshold = 0, show_negative = TRUE, fill_alpha = 0.6)
Como cada explicação leva mais tempo para criar e precisa ser aprimorada por imagem, as explicações de imagem não são algo que você criará em lotes grandes, como pode fazer com dados tabulares e de texto. Ainda assim, algumas explicações podem permitir que você entenda melhor seu modelo e seja usado para comunicar o funcionamento do seu modelo. Além disso, como o fator limitador de tempo nas explicações de imagem são o classificador de imagem e não o próprio cal, ele é obrigado à medida que os classificadores de imagem se tornam mais executivos.
Recupere
Além do suporte de Keras e da imagem, foram adicionadas uma série de outros recursos e melhorias. Aqui está uma visão geral rápida:
- Todas as parcelas de explicação agora incluem o ajuste da regressão de cume usada para fazer a explicação. Isso facilita a avaliação de quão boas as suposições sobre linearidade native são mantidas.
- Ao explicar dados tabulares, a medida de distância padrão é agora
'gower'
dogower
pacote.gower
torna possível medir distâncias entre dados heterogêneos sem converter todos os recursos em numéricos e experimentar diferentes grãos exponenciais. - Ao explicar, os recursos numéricos de dados tabulares não serão mais amostrados a partir de uma distribuição regular durante as permutações, mas a partir de uma densidade do kernel definida pelos dados de treinamento. Isso deve garantir que as permutações sejam mais representativas da entrada esperada.
Embrulhando
Este lançamento representa um marco importante para lime
em R. com a adição de explicações de imagem, o lime
O pacote está agora a par ou acima de seu parente python, em termos de recursos. Desenvolvimento adicional se concentrará em melhorar o desempenho do modelo, por exemplo, adicionando paralelismo ou melhorando a definição do modelo native, além de explorar tipos de explicação alternativos, como
âncora.
Feliz explicando!