Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

615
Visualizações
¿Cómo dividir el conjunto de datos de Cora para entrenar un modelo GCN solo en la parte de entrenamiento?

Estoy entrenando un GCN (Graph Convolutional Network) en el conjunto de datos de Cora.

El conjunto de datos de Cora tiene los siguientes atributos:

 Number of graphs: 1 Number of features: 1433 Number of classes: 7 Number of nodes: 2708 Number of edges: 10556 Number of training nodes: 140 Training node label rate: 0.05 Is undirected: True Data(edge_index=[2, 10556], test_mask=[2708], train_mask=[2708], val_mask=[2708], x=[2708, 1433], y=[2708])

Dado que mi código es muy largo, solo pongo las partes relevantes de mi código aquí. En primer lugar, dividí el conjunto de datos de Cora de la siguiente manera:

 def to_mask(index, size): mask = torch.zeros(size, dtype=torch.bool) mask[index] = 1 return mask def cora_splits(data, num_classes): indices = [] for i in range(num_classes): # returns all indices of the elements = i from data.y tensor index = (data.y == i).nonzero().view(-1) # returns a random permutation of integers from 0 to index.size(0). index = index[torch.randperm(index.size(0))] # indices is a list of tensors and it has a length of 7 indices.append(index) # select 20 nodes from each class for training train_index = torch.cat([i[:20] for i in indices], dim=0) rest_index = torch.cat([i[20:] for i in indices], dim=0) rest_index = rest_index[torch.randperm(len(rest_index))] data.train_mask = to_mask(train_index, size=data.num_nodes) data.val_mask = to_mask(rest_index[:500], size=data.num_nodes) data.test_mask = to_mask(rest_index[500:], size=data.num_nodes) return data

El train es el siguiente (tomado de aquí con algunas modificaciones):

 def train(model, optimizer, data, epoch): t = time.time() model.train() optimizer.zero_grad() output = model(data) loss_train = F.nll_loss(output[data.train_mask], data.y[data.train_mask]) acc_train = accuracy(output[data.train_mask], data.y[data.train_mask]) loss_train.backward() optimizer.step() loss_val = F.nll_loss(output[data.val_mask], data.y[data.val_mask]) acc_val = accuracy(output[data.val_mask], data.y[data.val_mask]) def accuracy(output, labels): preds = output.max(1)[1].type_as(labels) correct = preds.eq(labels).double() correct = correct.sum() return correct / len(labels)

Cuando ejecuté mi código con 200 épocas en 10 ejecuciones, gané:

 tensor([0.7690, 0.8030, 0.8530, 0.8760, 0.8600, 0.8550, 0.8850, 0.8580, 0.8940, 0.8830]) Val Loss: 0.5974, Test Accuracy: 0.854 ± 0.039

donde cada valor en el tensor pertenece a la precisión del modelo de cada ejecución y la precisión media de todas esas 10 ejecuciones es 0,854 con std ± 0,039.

Como se puede observar, la precisión desde la primera ejecución hasta la décima está aumentando sustancialmente. Por lo tanto, creo que el modelo se está sobreajustando. Una de las razones del sobreajuste es que, en el código, el modelo ha visto los datos de prueba en el tiempo de entrenamiento, ya que en la función de entrenamiento hay una output = model(data) por lo que el modelo se train con todos los datos. Lo que pretendo hacer es entrenar mi modelo solo en una parte de los datos (algo similar a data[data.train_mask] ) pero el problema es que no puedo pasar data[data.train_mask] , debido a la función de forward del GCN modelo (de este repositorio ):

 def forward(self, data): x, edge_index = data.x, data.edge_index x = F.relu(self.conv1(x, edge_index)) for conv in self.convs: x = F.relu(conv(x, edge_index)) x = F.relu(self.lin1(x)) x = F.dropout(x, p=0.5, training=self.training) x = self.lin2(x) return F.log_softmax(x, dim=-1)

Si paso data[data.train_mask] al modelo GCN, entonces en la función de forward anterior en la línea x, edge_index = data.x, data.edge_index , x y edge_index no se pueden recuperar de data[data.train_mask] . Por lo tanto, necesito encontrar una manera de dividir el conjunto de datos de Cora de manera que pueda pasar una parte específica con los nodos, el índice de borde y otros atributos al modelo. Mi pregunta es como hacerlo?

Además, cualquier sugerencia sobre la validación cruzada de k-fold es muy apreciada.

over 4 years ago · Santiago Trujillo
1 Respostas
Responde à pergunta

0

Supongo que está un poco confundido por la naturaleza del aprendizaje transductivo y la pregunta que hizo en realidad no aborda el problema al que se enfrenta.

Como se puede observar, la precisión desde la primera ejecución hasta la décima está aumentando sustancialmente. Por lo tanto, creo que el modelo se está sobreajustando.

No necesariamente, aumentar la precisión de la prueba podría ser un comportamiento normal cuando su modelo está aprendiendo de las muestras de entrenamiento. El aprendizaje puede durar varias docenas de épocas debido a la complejidad y la no convexidad de la función de pérdida. La mejor señal para detectar un sobreajuste es cuando aumenta la precisión de su entrenamiento, pero la precisión de la prueba disminuye significativamente.

Una de las razones del sobreajuste es que, en el código, el modelo ha visto los datos de prueba en el tiempo de entrenamiento, ya que en la función de entrenamiento hay una salida de línea = modelo (datos), por lo que el modelo se entrena con todos los datos.

De hecho, el modelo ha visto el gráfico completo (matriz de adyacencia) en el entrenamiento, pero solo ve las etiquetas de los nodos en el conjunto de entrenamiento y no sabe nada sobre las etiquetas de los nodos en el conjunto de prueba. Esto es exactamente lo que hace el aprendizaje transductivo .

Al final, si está 100% seguro de que desea evitar el paradigma del aprendizaje transductivo , es posible que deba escribir su propio algoritmo dividido para lograrlo. Pero me gustaría recordar que en el caso de uso del mundo real, la transducción es perfectamente adecuada. Un ejemplo es predecir los vínculos potenciales entre usuarios de redes sociales, donde tenemos toda la estructura de la red como entrada y queremos simplemente ejecutar predicción de borde--> transducción. Por lo tanto, no tiene mucho sentido evitarlo.


Dependiendo de su tarea, puede ver cómo la clase EdgeSplitter de EdgeSplitter ( docs ) y la función train_test_split de scikit-learn ( docs ) logran la división.

Clasificación de nodos

Si su tarea es una tarea de clasificación de nodos, esta clasificación de nodos con red convolucional gráfica (GCN) es un buen ejemplo de cómo cargar datos y hacer entrenamiento, prueba y división. Tomó el conjunto de datos de Cora como ejemplo. Los pasos más importantes son los siguientes:

 dataset = sg.datasets.Cora() display(HTML(dataset.description)) G, node_subjects = dataset.load() train_subjects, test_subjects = model_selection.train_test_split( node_subjects, train_size=140, test_size=None, stratify=node_subjects ) val_subjects, test_subjects = model_selection.train_test_split( test_subjects, train_size=500, test_size=None, stratify=test_subjects ) train_gen = generator.flow(train_subjects.index, train_targets) val_gen = generator.flow(val_subjects.index, val_targets) test_gen = generator.flow(test_subjects.index, test_targets)

Básicamente, es lo mismo que entrenar, probar y dividir con una tarea de clasificación normal, excepto que lo que dividimos aquí son nodos.

Clasificación de bordes

Si su tarea es la clasificación de bordes, puede echar un vistazo a este ejemplo de predicción de enlaces: GCN en el conjunto de datos de citas de Cora . El código más relevante para train-test-split es

 # Define an edge splitter on the original graph G: edge_splitter_test = EdgeSplitter(G) # Randomly sample a fraction p=0.1 of all positive links, and same number of negative links, from G, and obtain the # reduced graph G_test with the sampled links removed: G_test, edge_ids_test, edge_labels_test = edge_splitter_test.train_test_split( p=0.1, method="global", keep_connected=True ) # Define an edge splitter on the reduced graph G_test: edge_splitter_train = EdgeSplitter(G_test) # Randomly sample a fraction p=0.1 of all positive links, and same number of negative links, from G_test, and obtain the # reduced graph G_train with the sampled links removed: G_train, edge_ids_train, edge_labels_train = edge_splitter_train.train_test_split( p=0.1, method="global", keep_connected=True ) # For training we create a generator on the G_train graph, and make an # iterator over the training links using the generator's flow() method: train_gen = FullBatchLinkGenerator(G_train, method="gcn") train_flow = train_gen.flow(edge_ids_train, edge_labels_train) test_gen = FullBatchLinkGenerator(G_test, method="gcn") test_flow = train_gen.flow(edge_ids_test, edge_labels_test)

Aquí, el algoritmo de división detrás de la clase EdgeSplitter ( docs ) es más complejo, necesita mantener la estructura del gráfico mientras realiza la división, como mantener la conectividad del gráfico, por ejemplo. Para obtener más detalles, consulte el código fuente de EdgeSplitter

over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda