Я пытаюсь реализовать дерево решений / правила принятия решений с нуля в 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 для каждого экземпляра со следующим экземпляром, и повторите этопроцесс рекурсивный. Любая помощь будет высоко ценится.