используя Reduce для расчета индекса Джини для узла - PullRequest
0 голосов
/ 15 мая 2019

Я пытаюсь применить формулу:

Formula

Мне непонятно, почему это не работает:

def gini_node(node):
    count = sum(node)
    gini = functools.reduce(lambda p,c: p + (1 - (c/count)**2), node)
    print(count, gini)
    print(1 - (node[0]/count)**2, 1 - (node[1]/count)**2)
    return gini

Оценка gini([[175, 330], [220, 120]]) отпечатков:

505 175.57298304087834
0.8799137339476522 0.5729830408783452
340 220.87543252595157
0.5813148788927336 0.8754325259515571

обратите внимание, что второй оператор print печатает цифры, которые я хочу суммировать, учитывая пример ввода. возвращаемое значение (второе значение первого оператора печати) должно быть числом от 0 до 1.

Что не так с моим уменьшением?

Полная функция, которую я пытаюсь написать:

import functools

def gini_node(node):
    count = sum(node)
    gini = functools.reduce(lambda p,c: p + (1 - (c/count)**2), node)
    print(count, gini)
    print(1 - (node[0]/count)**2, 1 - (node[1]/count)**2)
    return gini

def gini (groups):
    counts = [ sum(node) for node in groups ]
    count = sum(counts)
    proportions = [ n/count for n in counts ]

    return sum([ gini_node(node) * proportion for node, proportion in zip(groups, proportions)])

# test
print(gini([[175, 330], [220, 120]]))

1 Ответ

1 голос
/ 15 мая 2019

Способ выполнения Reduce состоит в том, что он берет 2 аргумента из своего контейнера (только 2)
https://docs.python.org/3/library/functools.html#functools.reduce
и выполняет заданную ему операцию, затем продолжает повторять ту же самую операцию над списком, используя 2 аргумента.

gini = functools.reduce(lambda p,c: p + (1 - (c/count)**2), node)

Для первого узла (175, 330) эта лямбда примет 175 в p и 330 в c и вернет вам 175.57298304087834, вместо этого мы хотим

gini = functools.reduce(lambda p,c: (1 - (p/count)**2) + (1 - (c/count)**2), node)


Я добавил несколько операторов печати, давайте посмотрим их вывод.

import functools

def gini_node(node):
    count = sum(node)
    gini = functools.reduce(lambda p,c: (1 - (p/count)**2) + (1 - (c/count)**2), node)
    print(count, gini)
    print(1 - (node[0]/count)**2, 1 - (node[1]/count)**2)
    return gini

def gini (groups):
    counts = [ sum(node) for node in groups ]
    count = sum(counts)
    proportions = [ n/count for n in counts ]
    print(count, counts, proportions) #This
    gini_indexes = [ gini_node(node) * proportion for node, proportion in zip(groups, proportions)]
    print(gini_indexes) #And this
    return sum(gini_indexes)

# test
print(gini([[175, 330], [220, 120]]))

rahul@RNA-HP:~$ python3 so.py
845 [505, 340] [0.5976331360946746, 0.40236686390532544]
505 1.4528967748259973 #Second number here is addition of 2 numbers below
0.8799137339476522 0.5729830408783452
340 1.4567474048442905 #Same for this
0.5813148788927336 0.8754325259515571
#The first number of this list is first 1.45289677.... * 0.597633...
#Basically the addition and then multiplication by it's proportion.
[0.868299255961099, 0.5861468847894187]
#What you are returning to final print statement is the addition of gini co-effs of each node i.e the sum of the list above
1.4544461407505178

Более простой способ обойти, если есть более 2 аргументов (*)

 gini = sum([(1 - (p/count)**2) for p in node])

Работает так же, как функция reduce(), определенная выше.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...