Сравнение вложенных списков Python в цикле - PullRequest
0 голосов
/ 26 октября 2019

Я пытаюсь реализовать дерево решений / правила принятия решений с нуля в python для моего понимания. В частности, я пытаюсь реализовать алгоритм takelast (противоположный takefirst, в котором говорится, что для каждой ветви берут атрибуты в порядке их появления в обучающем наборе). Я использую набор данных lens24, который имеет 24 экземпляра, и его атрибуты - age, spect, astig, tear и label соответственно, где label содержит метки класса. Чтобы определить правила принятия решения, я сгруппировал экземпляры сначала по слезам, затем по астигу, потом по спектру и, наконец, по возрасту. Возвращенные результаты затем сохраняются в списке списков, где каждый отдельный список представляет значения каждого атрибута для формирования определенной ветви дерева.

newfile="lenses.data"
df = pd.read_table(newfile, delimiter=r"\s+", header=None)
df.columns =["id",  "age", "spect", "astig", "tear", "label"    ]
gf = df.groupby([ "tear",  "astig", 'spect', 'age'], as_index=False)

    for name,group in gf:
        print(group)
        rule = group.values.tolist()[0]
        ruleset.append(rule)
    print("ruleset")
    print(ruleset)

Вот выходные данные набора правил

[[1, 1, 1, 1, 3], [2, 1, 1, 1, 3], [3, 1, 1, 1, 3], [1, 2, 1, 1, 3], [2, 2, 1, 1, 3], [3, 2, 1, 1, 3], [1, 1, 2, 1, 3], [2, 1, 2, 1, 3], [3, 1, 2, 1, 3], [1, 2, 2, 1, 3], [2, 2, 2, 1, 3], [3, 2, 2, 1, 3], [1, 1, 1, 2, 2], [2, 1, 1, 2, 2], [3, 1, 1, 2, 3], [1, 2, 1, 2, 2], [2, 2, 1, 2, 2], [3, 2, 1, 2, 2], [1, 1, 2, 2, 1], [2, 1, 2, 2, 1], [3, 1, 2, 2, 1], [1, 2, 2, 2, 1], [2, 2, 2, 2, 3], [3, 2, 2, 2, 3]]

Теперь следующим шагом будет сокращение набора правил, чтобы некоторые избыточные ветви были объединены. Например, [1,1,1,1,3] и [2,1,1,1,3] различаются только по значению возраста (где список представляет [возраст, спект, астиг, слеза, метка])поэтому эти два правила могут быть объединены так, что результирующее правило будет (x, 1,1,1,3), где x показывает отсутствие атрибута. Я хочу рекурсивно обрезать набор правил так, чтобы на первом шаге были объединены все правила, которые различаются только для значений возраста. На следующем шаге объединяются те, которые отличаются только спектром, и так далее. Для первого шага я использовал следующий код:

    for i in range(len(ruleset)-1):
        if ruleset[i][1] == ruleset[i+1][1] and ruleset[i][2] == ruleset[i+1][2] and ruleset[i][3] == ruleset[i+1][3] and ruleset[i][4] == ruleset[i+1][4]:

            print("combining: ", ruleset[i], " and ", ruleset[i+1])
            ruleset[i][0] = ruleset[i+1][0]= -1

    print("after pruning ruleset")
    print(ruleset)
    minruleset = []
    for elem in ruleset:
        if elem not in minruleset:
            minruleset.append(elem)
    print("ruleset: ", len(ruleset))
    print("minruleset: ", len(minruleset))
    print(minruleset)
    print("------------------------")
    ruleset = minruleset

Исходный набор правил, который содержал 24 правила, теперь сведен к 10 правилам, а именно: -1 показывает, что возраст не имеет значения, поэтому мы будемне рассматривайте это далее.

[[-1, 1, 1, 1, 3], [-1, 2, 1, 1, 3], [-1, 1, 2, 1, 3], [-1, 2, 2, 1, 3], [-1, 1, 1, 2, 2], [3, 1, 1, 2, 3], [-1, 2, 1, 2, 2], [-1, 1, 2, 2, 1], [1, 2, 2, 2, 1], [-1, 2, 2, 2, 3]]

Теперь я хочу рекурсивно выполнить этот шаг сокращения таким образом, чтобы в первой итерации я исключил возраст в сравнении (индекс 0), а в следующем шаге я хочу исключитьвозраст и спект (индекс 0, 1), а затем исключаются возраст, спект, астиг (индекс 0, 1, 2) и так далее. В конце каждой итерации сокращения критериями остановки сокращения будет длина сокращенного набора правил, сформированного в конце сокращения, по сравнению с набором правил в начале конкретной итерации сокращения. Что я не могу сделать, так это указать диапазон индекса (0-4) в операторе if, в котором производится сравнение значений age, spect, astig, tear и label для каждого экземпляра со следующим экземпляром, и повторите этопроцесс рекурсивный. Любая помощь будет высоко ценится.

1 Ответ

1 голос
/ 26 октября 2019

Я нашел ответ сам. Размещение здесь, чтобы помочь любому с подобной проблемой в будущем. Оператор if должен быть обновлен следующим образом:

if all (ruleset[i][j] == ruleset[i+1][j] for j in range(col,features)):

оператор if будет вложен в цикл while, который прерывается при выполнении критерия остановки. После каждой итерации переменная col будет увеличиваться, тогда как значение функции будет фиксированным, например, 5 в моем случае.

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