Jestem raczej nowy i nie mogę powiedzieć, że mam pełne zrozumienie teoretycznych pojęć. Próbuję obliczyć dywergencję KL między kilkoma listami punktów w Pythonie. Korzystam z http://scikit-learn.org/stable/modules/generated/sklearn.metrics.mutual_info_score.html, aby spróbować to zrobić. Problem, na który napotykam, polega na tym, że zwracana wartość jest taka sama dla 2 dowolnych list liczb (jej 1.3862943611198906). Mam wrażenie, że popełniam tutaj jakiś teoretyczny błąd, ale nie mogę go dostrzec.
values1 = [1.346112,1.337432,1.246655]
values2 = [1.033836,1.082015,1.117323]
metrics.mutual_info_score(values1,values2)
To jest przykład tego, co uruchamiam - tylko to, że otrzymuję takie same dane wyjściowe dla 2 dowolnych danych wejściowych. Wszelkie porady / pomoc będą mile widziane!
python
clustering
scikit-learn
Nanda
źródło
źródło
sklearn.metrics.mutual_info_score([1.346112,1.337432,1.246655], [1.033836,1.082015,1.117323])
, otrzymuję wartość1.0986122886681096
.Odpowiedzi:
Przede wszystkim
sklearn.metrics.mutual_info_score
implementuje wzajemne informacje do oceny wyników grupowania, a nie czystą dywergencję Kullbacka-Leiblera!Rozbieżność KL (i każda inna tego rodzaju miara) oczekuje, że dane wejściowe będą miały sumę 1 . W przeciwnym razie nie są to właściwe rozkłady prawdopodobieństwa . Jeśli twoje dane nie mają sumy 1, najprawdopodobniej zwykle nie jest właściwe stosowanie dywergencji KL! (W niektórych przypadkach dopuszczalna może być suma mniejsza niż 1, np. W przypadku brakujących danych.)
Zauważ również, że często stosuje się logarytmy podstawowe 2. Daje to tylko stały współczynnik skalowania w różnicy, ale logarytmy bazowe 2 są łatwiejsze do interpretacji i mają bardziej intuicyjną skalę (0 do 1 zamiast 0 do log2 = 0,69314 ..., mierząc informacje w bitach zamiast w natach).
jak możemy wyraźnie zobaczyć, wynik MI sklearn jest skalowany przy użyciu logarytmów naturalnych zamiast log2. Jest to niefortunny wybór, jak wyjaśniono powyżej.
Rozbieżność Kullbacka-Leiblera jest niestety delikatna. W powyższym przykładzie nie jest dobrze zdefiniowany:
KL([0,1],[1,0])
powoduje podział przez zero i dąży do nieskończoności. Jest również asymetryczny .źródło
scipy.stats.entropy
zostanie użyty, znormalizuje prawdopodobieństwo do jednego. Z dokumentów ( scipy.github.io/devdocs/generated/scipy.stats.entropy.html ): „Ta procedura normalizuje pk i qk, jeśli nie sumują się do 1.”Funkcja entropii Scipy'ego obliczy dywergencję KL, jeśli zasilą dwa wektory p i q, z których każdy reprezentuje rozkład prawdopodobieństwa. Jeśli dwa wektory nie są plikami pdf, normalizuje się najpierw.
Wzajemne informacje są powiązane, ale nie takie same jak KL Divergence.
„Ta ważona wzajemna informacja jest formą ważonej dywergencji KL, o której wiadomo, że przyjmuje wartości ujemne dla niektórych danych wejściowych, a istnieją przykłady, w których ważona wzajemna informacja przyjmuje również wartości ujemne”
źródło
Nie jestem pewien co do implementacji ScikitLearn, ale oto szybka implementacja rozbieżności KL w Pythonie:
Wydajność:
0.775279624079
W niektórych bibliotekach może wystąpić konflikt implementacji , dlatego przed użyciem należy przeczytać ich dokumentację.
źródło
0.775279624079
dla twoich danych wejściowych i metryki sklearn zwracają1.3862943611198906
. Wciąż zdezorientowany! Wygląda jednak na to, że włączenie do skryptu sprawdzania wartości według qn powinnoTa sztuczka pozwala uniknąć kodu warunkowego i dlatego może zapewnić lepszą wydajność.
źródło
Rozważ trzy następujące próbki z dystrybucji (-ów).
Oczywiście wartości1 i wartości2 są bliższe, więc oczekujemy, że miara
surprise
lub entropia będą niższe w porównaniu z wartościami3.Widzimy następujące dane wyjściowe:
Widzimy, że ma to sens, ponieważ wartości między wartościami 1 a wartościami 3 oraz wartościami 2 i wartościami 3 są po prostu bardziej drastyczne w zmianie niż wartości1 do wartości 2. Jest to moje potwierdzenie zrozumienia KL-D i pakietów, które można do tego wykorzystać.
źródło