使用nn通过拼接Cora矩阵进行监督学习

内容纲要

Nn.py(训练)

import torch
import torch.nn as nn
import torch.optim as optim
from dgl.data import CoraGraphDataset

# 加载CORA数据集
def load_cora_data():
    dataset = CoraGraphDataset()
    graph = dataset[0]

    features = graph.ndata['feat']
    labels = graph.ndata['label']
    train_mask = graph.ndata['train_mask']
    test_mask = graph.ndata['test_mask']

    # 将图的邻接矩阵转换为稠密形式
    adj_matrix_dense = graph.adjacency_matrix().to_dense()

    # 将特征矩阵与邻接矩阵拼接
    features_combined = torch.cat([features, adj_matrix_dense], dim=1)

    return features_combined, labels, train_mask, test_mask

# 定义神经网络模型
class NeuralNetwork(nn.Module):
    def __init__(self, input_dim, hidden_dim, output_dim):
        super(NeuralNetwork, self).__init__()
        self.fc1 = nn.Linear(input_dim, hidden_dim)
        self.relu = nn.ReLU()
        self.fc2 = nn.Linear(hidden_dim, output_dim)

    def forward(self, x):
        x = self.fc1(x)
        x = self.relu(x)
        x = self.fc2(x)
        return x

# 训练和评估模型
def train_and_evaluate(features, labels, train_mask, test_mask, epochs=1000):
    input_dim = features.shape[1]
    hidden_dim = 255  # 增加隐藏层的大小
    output_dim = torch.max(labels) + 1

    model = NeuralNetwork(input_dim, hidden_dim, output_dim)
    criterion = nn.CrossEntropyLoss()
    optimizer = optim.Adam(model.parameters(), lr=0.00033887949895945285)

    best_acc = 0
    for epoch in range(epochs):
        optimizer.zero_grad()
        outputs = model(features)
        loss = criterion(outputs[train_mask], labels[train_mask])
        loss.backward()
        optimizer.step()

        if epoch % 10 == 0:
            model.eval()
            with torch.no_grad():
                outputs = model(features)
                _, predicted = torch.max(outputs[test_mask], 1)
                correct = (predicted == labels[test_mask]).sum().item()
                total = test_mask.sum().item()
                accuracy = 100 * correct / total
                print(f'Epoch {epoch}, Loss: {loss.item()}, Accuracy: {accuracy}%')
                if accuracy > best_acc:
                    best_acc = accuracy
                else:
                    print("Early stopping due to no improvement")
                    break  # 早停
            model.train()
    torch.save(model.state_dict(), 'nn.pth')

# 原来的主程序
if __name__ == "__main__":
    features_combined, labels, train_mask, test_mask = load_cora_data()
    train_and_evaluate(features_combined, labels, train_mask, test_mask)

Test.py

import torch
import torch.nn as nn
import torch.optim as optim
from dgl.data import CoraGraphDataset
import os

# 加载CORA数据集
def load_cora_data():
    dataset = CoraGraphDataset()
    graph = dataset[0]

    features = graph.ndata['feat']
    labels = graph.ndata['label']
    train_mask = graph.ndata['train_mask']
    test_mask = graph.ndata['test_mask']

    # 将图的邻接矩阵转换为稠密形式
    adj_matrix_dense = graph.adjacency_matrix().to_dense()

    # 将特征矩阵与邻接矩阵拼接
    features_combined = torch.cat([features, adj_matrix_dense], dim=1)

    return features_combined, labels, train_mask, test_mask

# 定义神经网络模型
class NeuralNetwork(nn.Module):
    def __init__(self, input_dim, hidden_dim, output_dim):
        super(NeuralNetwork, self).__init__()
        self.fc1 = nn.Linear(input_dim, hidden_dim)
        self.relu = nn.ReLU()
        self.fc2 = nn.Linear(hidden_dim, output_dim)

    def forward(self, x):
        x = self.fc1(x)
        x = self.relu(x)
        x = self.fc2(x)
        return x

# 训练和评估模型
def train_and_evaluate(features, labels, train_mask, test_mask, epochs=1000, model_path='nn.pth'):
    input_dim = features.shape[1]
    hidden_dim = 255  # 增加隐藏层的大小
    output_dim = torch.max(labels).item() + 1

    model = NeuralNetwork(input_dim, hidden_dim, output_dim)
    criterion = nn.CrossEntropyLoss()
    optimizer = optim.Adam(model.parameters(), lr=0.00033887949895945285)

    best_acc = 0
    for epoch in range(epochs):
        optimizer.zero_grad()
        outputs = model(features)
        loss = criterion(outputs[train_mask], labels[train_mask])
        loss.backward()
        optimizer.step()

        if epoch % 10 == 0:
            model.eval()
            with torch.no_grad():
                outputs = model(features)
                _, predicted = torch.max(outputs[test_mask], 1)
                correct = (predicted == labels[test_mask]).sum().item()
                total = test_mask.sum().item()
                accuracy = 100 * correct / total
                print(f'Epoch {epoch}, Loss: {loss.item()}, Accuracy: {accuracy}%')
                if accuracy > best_acc:
                    best_acc = accuracy
                else:
                    print("Early stopping due to no improvement")
                    break  # 早停

    torch.save(model.state_dict(), model_path)
    print(f'Model saved to {model_path}')

# 加载模型进行推理
def load_model_for_inference(input_dim, hidden_dim, output_dim, model_path='nn.pth'):
    model = NeuralNetwork(input_dim, hidden_dim, output_dim)
    model.load_state_dict(torch.load(model_path))
    model.eval()
    return model

def inference(model, features, mask):
    with torch.no_grad():
        outputs = model(features)
        _, predicted = torch.max(outputs[mask], 1)
        return predicted

if __name__ == "__main__":
    features_combined, labels, train_mask, test_mask = load_cora_data()
    model_path = 'nn.pth'

    # 检查模型文件是否存在,不存在则训练模型
    if not os.path.exists(model_path):
        print("Model not found, training...")
        train_and_evaluate(features_combined, labels, train_mask, test_mask, model_path=model_path)

    input_dim = features_combined.shape[1]
    hidden_dim = 255
    output_dim = torch.max(labels).item() + 1

    # 加载模型进行推理
    model = load_model_for_inference(input_dim, hidden_dim, output_dim, model_path)
    predicted_labels = inference(model, features_combined, test_mask)

    # 计算测试集上的准确率
    correct = (predicted_labels == labels[test_mask]).sum().item()
    total = test_mask.sum().item()
    accuracy = 100 * correct / total
    print(f'Test Accuracy: {accuracy}%')

Inn.py(超参优化)

import torch
import optuna
import torch.nn as nn
import torch.optim as optim
from dgl.data import CoraGraphDataset
import subprocess

# 加载CORA数据集
def load_cora_data():
    dataset = CoraGraphDataset()
    graph = dataset[0]

    features = graph.ndata['feat']
    labels = graph.ndata['label']
    train_mask = graph.ndata['train_mask']
    test_mask = graph.ndata['test_mask']

    # 将图的邻接矩阵转换为稠密形式
    adj_matrix_dense = graph.adjacency_matrix().to_dense()

    # 将特征矩阵与邻接矩阵拼接
    features_combined = torch.cat([features, adj_matrix_dense], dim=1)

    return features_combined, labels, train_mask, test_mask

# 定义神经网络模型
class NeuralNetwork(nn.Module):
    def __init__(self, input_dim, hidden_dim, output_dim):
        super(NeuralNetwork, self).__init__()
        self.fc1 = nn.Linear(input_dim, hidden_dim)
        self.relu = nn.ReLU()
        self.fc2 = nn.Linear(hidden_dim, output_dim)

    def forward(self, x):
        x = self.fc1(x)
        x = self.relu(x)
        x = self.fc2(x)
        return x

# 训练和评估模型
# def train_and_evaluate(features, labels, train_mask, test_mask, epochs=100):
#     input_dim = features.shape[1]
#     hidden_dim = 200  # 增加隐藏层的大小
#     output_dim = torch.max(labels) + 1
#
#     model = NeuralNetwork(input_dim, hidden_dim, output_dim)
#     criterion = nn.CrossEntropyLoss()
#     optimizer = optim.Adam(model.parameters(), lr=0.031)
#
#     best_acc = 0
#     for epoch in range(epochs):
#         optimizer.zero_grad()
#         outputs = model(features)
#         loss = criterion(outputs[train_mask], labels[train_mask])
#         loss.backward()
#         optimizer.step()
#
#         if epoch % 10 == 0:
#             model.eval()
#             with torch.no_grad():
#                 outputs = model(features)
#                 _, predicted = torch.max(outputs[test_mask], 1)
#                 correct = (predicted == labels[test_mask]).sum().item()
#                 total = test_mask.sum().item()
#                 accuracy = 100 * correct / total
#                 print(f'Epoch {epoch}, Loss: {loss.item()}, Accuracy: {accuracy}%')
#                 if accuracy > best_acc:
#                     best_acc = accuracy
#                 else:
#                     print("Early stopping due to no improvement")
#                     break  # 早停
#             model.train()

# 修改后的训练和评估函数
def train_and_evaluate_with_optuna(trial, features, labels, train_mask, test_mask, epochs=100):
    input_dim = features.shape[1]
    hidden_dim = trial.suggest_int('hidden_dim', 50, 400)  # 搜索隐藏层维度的范围
    output_dim = torch.max(labels) + 1
    lr = trial.suggest_float('lr', 1e-5, 1e-1, log=True)  # 搜索学习率的范围

    model = NeuralNetwork(input_dim, hidden_dim, output_dim)
    criterion = nn.CrossEntropyLoss()
    optimizer = optim.Adam(model.parameters(), lr=lr)

    for epoch in range(epochs):
        optimizer.zero_grad()
        outputs = model(features)
        loss = criterion(outputs[train_mask], labels[train_mask])
        loss.backward()
        optimizer.step()

    model.eval()
    with torch.no_grad():
        outputs = model(features)
        _, predicted = torch.max(outputs[test_mask], 1)
        correct = (predicted == labels[test_mask]).sum().item()
        accuracy = correct / test_mask.sum().item()

    return accuracy  # 返回准确率用于Optuna优化

# 定义优化函数
def objective(trial):
    features_combined, labels, train_mask, test_mask = load_cora_data()
    accuracy = train_and_evaluate_with_optuna(trial, features_combined, labels, train_mask, test_mask)
    return accuracy

# 创建study对象并运行优化
if __name__ == "__main__":
    study_name = "cora_study"  # 给你的study命名
    storage_name = f"sqlite:///{study_name}.db"

    # 创建study对象,指定优化的方向为最大化,并指定存储位置
    study = optuna.create_study(direction='maximize', study_name=study_name, storage=storage_name, load_if_exists=True)

    # 启动优化过程
    study.optimize(objective, n_trials=100, show_progress_bar=True)

    # 打印出最佳试验的结果
    print("Best trial:")
    trial = study.best_trial

    print("  Value: ", trial.value)
    print("  Params: ")
    for key, value in trial.params.items():
        print(f"    {key}: {value}")

    # 通过命令行启动optuna-dashboard
    subprocess.run(["optuna-dashboard", storage_name])

# 原来的主程序
# if __name__ == "__main__":
#     features_combined, labels, train_mask, test_mask = load_cora_data()
#     train_and_evaluate(features_combined, labels, train_mask, test_mask)

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注