Scikit-learn: Implementar coeficiente de similaridade de Gower

Criado em 19 nov. 2015  ·  51Comentários  ·  Fonte: scikit-learn/scikit-learn

Como sugerido por @lesshaste

Artigo - http://cbio.ensmp.fr/~jvert/svn/bibli/local/Gower1971general.pdf

Posso implementar isso se houver interesse suficiente?

@jnothman @amueller @agramfort

New Feature

Comentários muito úteis

Oi,

Para contribuir de alguma forma, implementei a função de Gower, de acordo com o artigo original, e as respectivas adaptações necessárias no módulo pdist, pois internamente o pdist faz várias transformações numéricas que irão falhar se você usar uma matriz com dados mistos.

Os resultados que obtive com isso até agora são os mesmos da função R's daisy.

O código-fonte está disponível neste bloco de notas jupyter: https://sourceforge.net/projects/gower-distance-4python/files/

Sinta-se livre para usá-lo

Todos 51 comentários

Obrigado.

Esta documentação para daisy de R pode ser relevante também https://stat.ethz.ch/R-manual/R-devel/library/cluster/html/daisy.html , pois é um caso de uso popular para o coeficiente de Gower.

sugeriu onde? em que contexto?

@agramfort eu sugeri no gitter. O principal interesse para esse coeficiente é quando as variáveis ​​têm tipos mistos (ou seja, categóricas, numéricas, ordinais). Um caso de uso popular está no pacote R daisy() mencionado antes ao agrupar dados com tipos mistos (consulte a página 27 de https://cran.r-project.org/web/packages/cluster/cluster.pdf) . De forma mais geral, http://www.clustan.talktalk.net/gower_similarity.html afirma "O coeficiente geral de similaridade de Gower é uma das medidas mais populares de proximidade para tipos de dados mistos." o que parece uma afirmação plausível.

existe uma referência ou exemplo convincente que motivaria isso?

@agramfort Acho que não temos outra maneira de calcular um coeficiente de dissimilaridade para tipos de dados mistos atualmente e este parece ser o padrão. Posso encontrar muitos exemplos e perguntas / respostas online onde as pessoas explicam o que é o coeficiente de Gower ou sugerem seu uso para tipos de dados mistos, mas nada que eu pudesse chamar de benchmark ainda. O artigo original foi citado 2.298 vezes, de acordo com o estudioso do Google.

ok estou convencido :)

@agramfort Ótimo! Esta mudança complementaria https://github.com/scikit-learn/scikit-learn/pull/4899 muito bem, o que introduz o suporte nativo de variáveis ​​categóricas para árvores.

Dito isso, agora percebo que o scikit-learn não tem suporte nativo para ordinais atualmente, portanto, esta parte da minha sugestão estaria um pouco à frente de seu tempo. Suponho que se possa considerá-lo de maneira positiva como o primeiro passo no suporte para características ordinais.

@amueller Para ser marcado com [New Feature] ...

Oi,

Para contribuir de alguma forma, implementei a função de Gower, de acordo com o artigo original, e as respectivas adaptações necessárias no módulo pdist, pois internamente o pdist faz várias transformações numéricas que irão falhar se você usar uma matriz com dados mistos.

Os resultados que obtive com isso até agora são os mesmos da função R's daisy.

O código-fonte está disponível neste bloco de notas jupyter: https://sourceforge.net/projects/gower-distance-4python/files/

Sinta-se livre para usá-lo

Eu só estava me perguntando se houve alguma atualização sobre isso? Além disso, o problema observado por @marcelobeckmann ainda é relevante?

@ ashimb9 parece que precisamos de alguém para integrar o código de @marcelobeckmann

@agramfort Hmm, nesse caso vou tentar quando tiver algum tempo livre. A propósito, você sabe alguma coisa sobre o estado atual do problema observado acima: "no módulo pdist, porque internamente o pdist faz várias transformações numéricas que falharão se você usar uma matriz com dados mistos"

Olá, existem algumas funções privadas (por exemplo, _convert_to_double, _copy_array_if_base_present) em pdist que assumem que os dados subjacentes são completamente numéricos, o que não é verdade quando você tem um Dataframe com dados categóricos.

Eu me ofereço para integrar este código e torná-lo disponível em um fork, você pode atribuir este tíquete para mim.

O recurso de atribuição do github funciona apenas para membros da equipe

Em 17 de julho de 2017, 19:32, "marcelobeckmann" [email protected] escreveu:

Olá, existem algumas funções privadas (por exemplo, _convert_to_double,
_copy_array_if_base_present) em pdist que assume que os dados subjacentes são
completamente numérico, o que não é verdade quando você tem um Dataframe com
Dados categóricos.

Eu me ofereço para integrar este código e torná-lo disponível em uma bifurcação, você
pode atribuir este tíquete para mim.

-
Você está recebendo isso porque foi mencionado.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/scikit-learn/scikit-learn/issues/5884#issuecomment-315707830 ,
ou silenciar o tópico
https://github.com/notifications/unsubscribe-auth/AAEz62L3HHzGsSerW5G3n-Z8rrNoV6mwks5sOyoTgaJpZM4Glm0p
.

Não se preocupe, vou fazer um fork e você pode obter o código get mais tarde. Para mim o importante é contribuir. Eu avisarei você quando terminar.

Obrigado @marcelobeckmann por aceitar isso. Enquanto você está nisso (e se for viável para você), gostaria de saber se você consideraria adicionar suporte para cálculo gower em dados com valores NaN também, conforme implementado no pacote margarida em R (que você também referiu acima) ?

Terminei a integração do Gower com sklearn.metrics.pairwise (também observando o tratamento dos valores NaN). Vou preparar alguns testes de unidade antes de enviar meu código bifurcado.

@marcelobeckmann Ótimo! Muito obrigado, especialmente por incluir o suporte NaN! :)

PS: Se eu puder sugerir, você pode considerar iniciar uma solicitação pull para que os revisores possam começar a examinar seu código enquanto você trabalha nos testes de unidade e assim por diante.

Fiz uma solicitação de pull há alguns dias, b5884.

Sim, está na fila para revisão.

Em 17 de agosto de 2017 às 23:40, Marcelo Beckmann [email protected]
escreveu:

Fiz uma solicitação de pull há alguns dias, b5884.

-
Você está recebendo isso porque foi mencionado.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/scikit-learn/scikit-learn/issues/5884#issuecomment-323076581 ,
ou silenciar o tópico
https://github.com/notifications/unsubscribe-auth/AAEz69uMu0XsoAUfvwWikkadjGCk5yvKks5sZELKgaJpZM4Glm0p
.

Fiz as alterações exigidas pelo CI e todas as verificações foram aprovadas.

@marcelobeckmann ótimo trabalho! você pode querer alterar a linha 659 para algo como:
ranges_of_numeric[col] = (1 - min / max, 0)[max == 0] if (max!=0) else 0.0

Estou recebendo a divisão por zero-avisos em seu segundo caso de teste, caso contrário.

Olá, mudei o código para evitar avisos, conforme proposto por Pierre Wessman, e CI é verde. Preciso de alguém para revisar meu código.

@marcelobeckmann e potencialmente outros.

Olá Marcelo (ou possivelmente outros), tenho uma pergunta rápida em relação à sua implementação do coeficiente de gower que você colocou aqui: https://sourceforge.net/projects/gower-distance-4python/files/.

  1. Preciso de um panda dataFrame para alimentar os dados originais na função ou posso usar um array numpy também?

  2. Estou importando meus dados para uma matriz numpy. Todas as colunas são números reais numéricos, exceto a primeira coluna, que é o ID único. Estou tendo dois problemas,

  • em primeiro lugar, quando executo a função, ela retorna um aviso de conversão de dados informando que o dtype U7 foi convertido em objeto !!. Presumi que era porque as entradas da matriz, por algum motivo, aparecem entre aspas e, portanto, são strings. Então, eu converto o tipo de entradas de array para int32 por exemplo e ainda dá o erro de conversão dizendo que int32 foi convertido em objetos

  • Em segundo lugar, e provavelmente vinculado ao acima, toda vez que executo a função e ploto o resultado, recebo uma visualização diferente (distribuição diferente dos pontos).

Você poderia me aconselhar sobre o acima, por favor?

Muito obrigado

Oi ali,

Obrigado pelo seu interesse nesta implementação da distância Gower.

Embora o código que fiz uma solicitação pull não seja aprovado pelos scikit learn commiters (CI é verde e apenas esperando por uma revisão), enviei esta implementação mais recente e estável para: https://sourceforge.net/projects/gower-distance -4python / files / gower_function-v3.ipynb / download

Vamos responder às suas perguntas:

  1. Preciso de um Panda DataFrame para alimentar os dados originais na função ou posso usar um array numpy também?

Resposta: Você pode usar DataFrame ou Numpy nesta nova versão 3. Matrizes esparsas também são suportadas.

  1. . Estou importando meus dados para uma matriz numpy. Todas as colunas são números reais numéricos, exceto a primeira coluna, que é o ID único. Estou tendo dois problemas,
  • em primeiro lugar, quando executo a função, ela retorna um aviso de conversão de dados informando que o dtype U7 foi convertido em objeto !!. Presumi que era porque as entradas da matriz, por algum motivo, aparecem entre aspas e, portanto, são strings. Então, eu converto o tipo de entradas de array para int32 por exemplo e ainda dá o erro de conversão dizendo que int32 foi convertido em objetos

Resposta: Esta nova versão suporta atributos categóricos numéricos, há um parâmetro extra categorical_features, que você pode definir uma matriz com falso (para atributos numéricos) ou verdadeiro (para os categóricos)

  • Em segundo lugar, e provavelmente vinculado ao acima, toda vez que executo a função e ploto o resultado, recebo uma visualização diferente (distribuição diferente dos pontos).

Resposta: A nova versão que enviei resolveu esse problema.

observe que pretendo revisar este PR, mas não é muito importante
prioridade atm

Oi ali,

  1. O mais recente é gower_function-v3.ipynb, e sim lida com nan
    propagação

  2. Você pode usar gower_distance (X) apenas, se o seu ataque categórico não for
    numeric ou gower_distance (X, categorical_features = [False, True,
    False, ...]), se os atributos do seu gato forem representados como numéricos.

Avise-me em particular se tiver algum problema, porque esta implementação
Eu empurrei para a internet não deve ser a preocupação do scikit learn, eles têm um
muito a fazer, e este não é o melhor lugar para discutir isso.

Em 30 de novembro de 2017 11:51, "Ali-ry" [email protected] escreveu:

@marcelobeckmann https://github.com/marcelobeckmann

Olá Marcelo (ou potencialmente outros), tenho uma pergunta rápida em relação ao seu
implementação do coeficiente de gower que você colocou aqui:
https://sourceforge.net/projects/gower-distance-4python/files/

1

O gower_single_function-v2.ipynb é a versão final e lida com
NaN também?
2

mais importante, esta implementação permite que você obtenha o
semelhanças dentro de uma única amostra de dados? porque na maioria dos casos o que você
necessidade é obter a distância gower entre cada par de observação dentro
um único dado de amostra em oposição à comparação de dois dados de amostra diferentes.

Muito obrigado

-
Você está recebendo isso porque foi mencionado.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/scikit-learn/scikit-learn/issues/5884#issuecomment-348166596 ,
ou silenciar o tópico
https://github.com/notifications/unsubscribe-auth/AA3G79jWVbpBNdAFOAim7wJS92-QGl0dks5s7pa8gaJpZM4Glm0p
.

Oi ali,

  1. O mais recente é gower_function-v3.ipynb, e é uma cópia do que enviei para o scikit learn e, sim, trata da propagação nan

  2. Você pode usar gower_distance (X) apenas, se seu att categórico não for numérico, ou gower_distance (X, categorical_features = [False, True, False, ...]), se seus atributos categóricos forem representados como numéricos.

Por favor, deixe-me saber em particular se você tiver qualquer problema, porque esta implementação que eu coloquei na internet não deve ser a preocupação do scikit learn, eles têm muito a fazer e aqui não é o melhor lugar para discutir algo que está fora do scikit aprenda o projeto.

@marcelobeckmann Olá Marcelo,
O valor do parâmetro categorical_features deve ser True ou False se tivermos as variáveis ​​categóricas codificadas em um formato numérico?

Também recebo o seguinte erro:
ValueError: array encontrado com 0 amostra (s) (forma = (0, 0)) enquanto um mínimo de 1 é exigido por check_pairwise_arrays.

Funcionou com sucesso nos mesmos dados anteriormente, mas agora dá esse erro. Por que poderia ser?

Olá @bendiste ,

Se você representar True e False como 1 e 0, obterá os mesmos resultados.

Você está usando o notebook gower_function-v6.4.ipynb mais recente em
https://sourceforge.net/projects/gower-distance-4python/files/
?

Estou terminando de escrever um artigo, espero que este mês eu deva fazer as alterações solicitadas para que minha implementação seja aceita no master do scikit-learn.

Olá @marcelobeckmann , obrigado pela resposta. E sim, estou usando a versão mais recente que você indicou. Quando eu baixei novamente, ele funcionou com sucesso. Gostaria de fazer algumas perguntas, já que sou um novato em aprendizado de máquina:
1- Posso usar o KPCA para diminuir as dimensões como uma entrada para o algoritmo de agrupamento hierárquico?
2- Ou devo usar todo o conjunto de dados com alta dimensionalidade como entrada para o agrupamento hierárquico?

Olá @marcelobeckmann ,
obrigado por esta implementação!

Tentei a versão gower_function-v6.4.
Posso ver que as distâncias em seus testes de unidade são as mesmas, não importa se você especifica as colunas categóricas ou não. Também tentei com meus próprios dados, onde também não afetam o resultado.

Isso está correto?

Obrigado!

Olá @annelaura ,

Desculpe pela demora para responder. Sim, está correto, aquele teste foi apenas para verificar se os parâmetros categorical_features = [0, 1] não afetarão os resultados, se as colunas não numéricas também podem ser identificadas como objetos. Os dados de entrada são os mesmos, portanto, os resultados devem ser os mesmos.

Depois de terminar alguns trabalhos, estou de volta ao trabalho para finalmente propor minha implementação ao branch master do scikit! :)

@marcelobeckmann alguma novidade sobre isso? :)

Olá, Alex, Concluí todas as modificações que os revisores pediram até agora na solicitação pull e o CI está verde. Também enviei um ping para os revisores para verificar se eles estão satisfeitos, então podemos fechar esta solicitação pull e enviá-la para o lançamento.

Alguma atualização? @marcelobeckmann

Trabalho em andamento após revisão.

O PR foi aprovado? @marcelobeckmann

Ainda não, o trabalho está em andamento após alguma revisão recente do código.

Que pena que preciso disso.

Apenas a função está disponível em algum lugar? Posso usá-lo sozinho (para fins de pesquisa)

Obrigado

Você pode obter o último commit desta função neste PR:
https://github.com/scikit-learn/scikit-learn/pull/9555

Consegui fazer funcionar localmente. Obrigado!

Apenas um rápido +1 neste tíquete! Obrigado por todo o trabalho nisso.

Ressalto. Isso seria uma grande adição. Eu não posso acreditar que levou 4 anos para um cálculo relativamente simples chegar ao sklearn !!

Ou você poderia dizer: obrigado por sua persistência dedicada ao longo de quatro anos de
esforço voluntário!

Ou você poderia dizer: obrigado por sua persistência dedicada ao longo de quatro anos de esforço voluntário!

Você está certo, desculpe. Não tive a intenção de parecer rude. Agradeço muito o esforço. Estou usando isso localmente há algum tempo e seria ótimo vê-lo adicionado. É a única métrica de distância que conheço para tipos de dados mistos.

Além do esforço voluntário, e que os desenvolvedores principais não consideraram
urgente, há realmente desafios em torno de como lidar com tipos mistos,
e sobre como realizar o dimensionamento em uma configuração de teste de trem.

Ansioso por isso no sklearn.

Alguém que afirma ter " idéias emprestadas " deste tópico lançou um pacote no github para calcular a distância de Gower (similaridade, tecnicamente). Por falar em distância e semelhança, o exemplo é idêntico ao de @marcelobeckmann. Eu apenas dei uma olhada no código até agora, mas aqui está um vislumbre:

Do caderno de @marcelobeckmann :

    # This is to normalize the numeric values between 0 and 1.
    X_num = np.divide(X_num ,max_of_numeric,out=np.zeros_like(X_num), where=max_of_numeric!=0)

De "Michael Yan":

    # This is to normalize the numeric values between 0 and 1.
    Z_num = np.divide(Z_num ,num_max,out=np.zeros_like(Z_num), where=num_max!=0)

Oi pessoal, obrigado por ficar de olho nisso.

Fico feliz que as pessoas estejam pegando o código e tentando melhorá-lo, esse é o propósito de ser open source, apesar de algum crédito ser apreciado.

Esperançosamente, este código fará parte do scikit-learn, se este PR # 9555 for aceito.

Atenciosamente,

Marcelo Beckmann

Boa sorte no processo !!

Esta página foi útil?
0 / 5 - 0 avaliações