Самый быстрый способ вычислить энтропию в Python

В моем проекте мне нужно многократно вычислить энтропию векторов 0-1. Вот мой код:

def entropy(labels): """ Computes entropy of 0-1 vector. """ n_labels = len(labels) if n_labels <= 1: return 0 counts = np.bincount(labels) probs = counts[np.nonzero(counts)] / n_labels n_classes = len(probs) if n_classes <= 1: return 0 return - np.sum(probs * np.log(probs)) / np.log(n_classes) 

Есть ли более быстрый способ?

7 Solutions collect form web for “Самый быстрый способ вычислить энтропию в Python”

Следуя предложению unutbu, я создаю чистую реализацию python.

 def entropy2(labels): """ Computes entropy of label distribution. """ n_labels = len(labels) if n_labels <= 1: return 0 counts = np.bincount(labels) probs = counts / n_labels n_classes = np.count_nonzero(probs) if n_classes <= 1: return 0 ent = 0. # Compute standard entropy. for i in probs: ent -= i * log(i, base=n_classes) return ent 

Точка, в которой я отсутствовала, заключалась в том, что метки представляют собой большой массив, однако пробники имеют длину 3 или 4 элемента. Используя чистый python, мое приложение теперь в два раза быстрее.

 import pandas as pd import scipy as sc # Input a pandas series def ent(data): p_data= data.value_counts()/len(data) # calculates the probabilities entropy=sc.stats.entropy(p_data) # input probabilities to get the entropy return entropy 

Моя любимая функция для энтропии заключается в следующем:

 def entropy(labels): prob_dict = {x:labels.count(x)/len(labels) for x in labels} probs = np.array(list(prob_dict.values())) return - probs.dot(np.log2(probs)) 

Я все еще ищу более удобный способ избежать преобразования dict -> values ​​-> list -> np.array. Повторю, если я его найду.

посмотрите здесь также, есть классическая энтропия Шеннона, должна быть немного быстрее, чем одна из ДжонЭнтропия http://pythonfiddle.com/shannon-entropy-calculation/

Ответ @Sanjeet Gupta хорош, но может быть сжат. В этом вопросе конкретно спрашивают о «самом быстром» способе, но я вижу только один раз на один ответ, поэтому я опубликую сравнение использования scipy и numpy с первоначальным ответом энтропии2 плаката с небольшими изменениями.

Четыре разных подхода: scipy / numpy , numpy / math , pandas / numpy , numpy

 import numpy as np from scipy.stats import entropy from math import log, e import pandas as pd import timeit def entropy1(labels, base=None): value,counts = np.unique(labels, return_counts=True) return entropy(counts, base=base) def entropy2(labels, base=None): """ Computes entropy of label distribution. """ n_labels = len(labels) if n_labels <= 1: return 0 value,counts = np.unique(labels, return_counts=True) probs = counts / n_labels n_classes = np.count_nonzero(probs) if n_classes <= 1: return 0 ent = 0. # Compute entropy base = e if base is None else base for i in probs: ent -= i * log(i, base) return ent def entropy3(labels, base=None): vc = pd.Series(labels).value_counts(normalize=True, sort=False) base = e if base is None else base return -(vc * np.log(vc)/np.log(base)).sum() def entropy4(labels, base=None): value,counts = np.unique(labels, return_counts=True) norm_counts = counts / counts.sum() base = e if base is None else base return -(norm_counts * np.log(norm_counts)/np.log(base)).sum() 

Операции тайм-аута:

 repeat_number = 1000000 a = timeit.repeat(stmt='''entropy1(labels)''', setup='''labels=[1,3,5,2,3,5,3,2,1,3,4,5];from __main__ import entropy1''', repeat=3, number=repeat_number) b = timeit.repeat(stmt='''entropy2(labels)''', setup='''labels=[1,3,5,2,3,5,3,2,1,3,4,5];from __main__ import entropy2''', repeat=3, number=repeat_number) c = timeit.repeat(stmt='''entropy3(labels)''', setup='''labels=[1,3,5,2,3,5,3,2,1,3,4,5];from __main__ import entropy3''', repeat=3, number=repeat_number) d = timeit.repeat(stmt='''entropy4(labels)''', setup='''labels=[1,3,5,2,3,5,3,2,1,3,4,5];from __main__ import entropy4''', repeat=3, number=repeat_number) 

Результаты тайм-аута:

 # for loop to print out results of timeit for approach,timeit_results in zip(['scipy/numpy', 'numpy/math', 'pandas/numpy', 'numpy'], [a,b,c,d]): print('Method: {}, Avg.: {:.6f}'.format(approach, np.array(timeit_results).mean())) Method: scipy/numpy, Avg.: 63.315312 Method: numpy/math, Avg.: 49.256894 Method: pandas/numpy, Avg.: 884.644023 Method: numpy, Avg.: 60.026938 

Победитель: numpy / math (entropy2)

Также стоит отметить, что функция entropy2 выше может обрабатывать числовые И текстовые данные. ex: entropy2(list('abcdefabacdebcab')) . Ответ оригинального плаката – с 2013 года и имел конкретный вариант использования для binning int, но он не будет работать для текста.

Ответ, который не полагается на numpy, либо:

 import math from collections import Counter def eta(data, unit='natural'): base = { 'shannon' : 2., 'natural' : math.exp(1), 'hartley' : 10. } if len(data) <= 1: return 0 counts = Counter() for d in data: counts[d] += 1 probs = [float(c) / len(data) for c in counts.values()] probs = [p for p in probs if p > 0.] ent = 0 for p in probs: if p > 0.: ent -= p * math.log(p, base[unit]) return ent 

Это примет любой тип данных, который вы могли бы на него набросать:

 >>> eta(['mary', 'had', 'a', 'little', 'lamb']) 1.6094379124341005 >>> eta([c for c in "mary had a little lamb"]) 2.311097886212714 

Вышеприведенный ответ хорош, но если вам нужна версия, которая может работать по разным осям, вот работающая реализация.

 def entropy(A, axis=None): """Computes the Shannon entropy of the elements of A. Assumes A is an array-like of nonnegative ints whose max value is approximately the number of unique values present. >>> a = [0, 1] >>> entropy(a) 1.0 >>> A = np.c_[a, a] >>> entropy(A) 1.0 >>> A # doctest: +NORMALIZE_WHITESPACE array([[0, 0], [1, 1]]) >>> entropy(A, axis=0) # doctest: +NORMALIZE_WHITESPACE array([ 1., 1.]) >>> entropy(A, axis=1) # doctest: +NORMALIZE_WHITESPACE array([[ 0.], [ 0.]]) >>> entropy([0, 0, 0]) 0.0 >>> entropy([]) 0.0 >>> entropy([5]) 0.0 """ if A is None or len(A) < 2: return 0. A = np.asarray(A) if axis is None: A = A.flatten() counts = np.bincount(A) # needs small, non-negative ints counts = counts[counts > 0] if len(counts) == 1: return 0. # avoid returning -0.0 to prevent weird doctests probs = counts / float(A.size) return -np.sum(probs * np.log2(probs)) elif axis == 0: entropies = map(lambda col: entropy(col), AT) return np.array(entropies) elif axis == 1: entropies = map(lambda row: entropy(row), A) return np.array(entropies).reshape((-1, 1)) else: raise ValueError("unsupported axis: {}".format(axis)) 
  • Не удается установить Pandas с OpenShift
  • Python fsolve () жалуется на форму. Зачем?
  • Итерация и выбор определенного массива из многомерного массива в Python
  • Как вычислить scipy разреженный матричный определитель, не превращая его в плотный?
  • n-мерное скользящее окно с Pandas или Numpy
  • Попытка генерировать случайные координаты x, y внутри кольца в python
  • Почему numpy.array () иногда очень медленный?
  • Как получить основу сплайна, используемую scipy.interpolate.splev
  •  
    Interesting Posts for Van-Lav

    Twython – Как обновить статус с помощью URL-адреса мультимедиа

    Потерял важный .py-файл (перезаписан в виде 0-байтного файла), но старая версия все еще загружена в IPYTHON в качестве модуля – может ли она быть восстановлена?

    Python – многопроцессорный демона

    Два модуля Python требуют содержимого друг друга – может ли это работать?

    питон; изменение списка внутри функции

    Как загрузить только непрочитанные вложения с определенной метки gmail?

    Python urllib2 автоматическое заполнение форм и поиск результатов

    Как получить tenorflow op по имени?

    Каков наилучший способ инициализации и использования контингентов в классах Python?

    Pythonic способ распечатать элементы списка

    сравнивая два dict в python, чтобы получить максимальное значение для аналогичного ключа

    Может ли Pythonic проверять типы аргументов функции?

    Что касается примера последовательности Фибоначчи в учебнике по функциям Python

    Цикл Python: идиоматическое сравнение последовательных элементов в списке

    Итерирование кадра данных pandas, проверка значений и создание некоторых из них

    Python - лучший язык программирования в мире.