Как реализовать PyTorch NN из ориентированного графа - PullRequest
1 голос
/ 09 марта 2020

Я новичок в Pytorch и преподаю сам, и я хочу создать ANN, которые принимают ориентированный граф. Я также хочу передать предопределенные веса и смещения для каждого соединения, но хочу игнорировать это на данный момент.

Моя мотивация для этих условий заключается в том, что я пытаюсь реализовать NEAT Алгоритм, который в основном использует алгоритм Geneti c для развития сети.

Например, пусть graph = dict{'1':[[], [4, 7]], '2':[[], [6]], '3':[[], [6]], '4':[[1, 7], []], '5':[[7], []], '6':[[2, 3], [7]], '7':[[1, 6], [4, 5]]} представляет ориентированный граф.

Example graph

Мой код того, о чем я думаю:

class Net(torch.nn.Module):
    def __init__(self, graph):
        super(Net, self).__init__()
        self.graph = graph
        self.walk_graph()

    def walk_graph(self):
        graph_remaining = copy.deepcopy(self.graph)
        done = False  # Has every node/connection been processed?
        while not done:
            processed = []  # list of tuples, of a node and the nodes it outputs to
            for node_id in graph_remaining.keys():
                if len(graph_remaining[node_id][0]) == 0:  # if current node has no incoming connections
                    try:
                        # if current node has been processed, but waited for others to finish
                        if callable(getattr(self, 'layer{}'.format(node_id))):
                            D_in = len(eval('self.layer{}'.format(node_id)).in_features)
                            D_out = len(eval('self.layer{}'.format(node_id)).out_features)
                            setattr(self, 'layer{}'.format(node_id), torch.nn.Linear(D_in, D_out))
                        cat_list = [] # list of input tensors
                        for i in self.graph[node_id][0]: # search the entire graph for inputs
                            cat_list.append(globals()['out_{}'.format(i)]) # add incoming tensor to list
                        # create concatenated tensor for incoming tensors
                        # I'm not confident about this
                        globals()['in_{}'.format(node_id)] = torch.cat(cat_list, len(cat_list))
                    except AttributeError:  # if the current node hasn't been waiting
                        try:
                            setattr(self, 'layer{}'.format(node_id), torch.nn.Linear(len(self.graph[node_id][0]), len(self.graph[node_id][1])))
                        except ZeroDivisionError:  # Input/Output nodes have zero inputs/outputs in the graph
                            setattr(self, 'layer{}'.format(node_id), torch.nn.Linear(1, 1))
                    globals()['out_{}'.format(node_id)] = getattr(self, 'layer' + node_id)(globals()['in_{}'.format(node_id)])
                    processed.append((node_id, graph_remaining[node_id][1]))

            for node_id, out_list in processed:
                for out_id in out_list:
                    try:
                        graph_remaining[str(out_id)][0].remove(int(node_id))
                    except ValueError:
                        pass
                try:
                    del graph_remaining[node_id]
                except KeyError:
                    pass

            done = True
            for node_id in self.graph.keys():
                if len(graph_remaining[node_id][0]) != 0 or len(graph_remaining[node_id][1]) != 0:
                    done = False
        return None

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

1 Ответ

1 голос
/ 13 марта 2020

Поскольку вы не планируете проводить какое-либо реальное обучение сети, PyTorch может быть не лучшим вариантом в этом случае.

NEAT - это рекомбинация и изменение нейронных сетей - как их структура, так и их вес. и предвзятость - и тем самым достижение лучших результатов. PyTorch, как правило, представляет собой систему глубокого обучения, означающую, что вы определяете структуру (или архитектуру) вашей сети, а затем используете алгоритмы, такие как Stochasti c Gracent Descent, для обновления весов и смещений с целью повышения вашей производительности. Как следствие этого, PyTorch работает на основе модулей и подмодулей нейронных сетей, таких как полностью связанные слои, сверточные слои и т. Д.

Проблема с этим несоответствием заключается в том, что NEAT требует не только много хранения больше информации (например, их ID для рекомбинации и т. д. c.) об отдельных узлах, чем поддерживает PyTorch, также не очень хорошо согласуется с «послойным» подходом сред глубокого обучения.

На мой взгляд, вам лучше реализовать прямой проход через сеть самостоятельно. Если вы не знаете, как это сделать, это видео дает очень хорошее объяснение.

...