小白带你深度学习DAY4

本次代码是一个简单的GAN神经网络

代码说明:

        一、数据准备:

                1.使用Karate Club数据集(小型社交网络)

                2.包含34个节点(俱乐部成员)和156条边(社交关系)

                3.每个节点有34维特征,分为4个类别

        二、模型结构:

                1.两层GCN(图卷积网络)

                2.第一层:34维输入 → 4维隐藏层

                3.第二层保持4维方便可视化

                4.使用ReLU激活函数

        三、可视化功能:

                1.原始图结构可视化(使用networkx)

                2.训练损失曲线

                3.隐藏层表示的PCA降维可视化

        四、训练过程:

                1.使用交叉熵损失和Adam优化器

                2.训练200个epoch

                3.输出训练过程中的损失变化

        五、测试功能:

           计算节点分类准确率运行结果说明:

                1.会显示三个可视化窗口:

                        Ⅰ.原始图结构(节点颜色表示真实类别)

                        Ⅱ.训练损失曲线

                        Ⅲ.隐藏层表示的可视化(不同颜色对应不同类别)

                2.终端输出:

                        Ⅰ.数据集基本信息

                        Ⅱ.训练过程中的损失变化

                        Ⅲ.最终测试准确率

        六、注意事项:

                1.首次运行会自动下载数据集(约1MB)

                2.可视化窗口需要关闭当前窗口才能继续执行后续代码

                3.准确率可能因随机初始化略有波动(通常在0.85-1.00之间)

# 在PyCharm终端安装依赖(已安装可跳过):
# pip install torch torchvision torchaudio
# pip install torch-geometric matplotlib scikit-learn networkx
import matplotlib.pyplot as plt
# ========== 新增部分:解决中文显示问题 ==========
plt.rcParams['font.sans-serif'] = ['SimHei']  # Windows系统
# plt.rcParams['font.sans-serif'] = ['Songti SC']  # MacOS系统
plt.rcParams['axes.unicode_minus'] = False  # 解决负号显示问题
import torch
from torch_geometric.datasets import KarateClub
from torch_geometric.nn import GCNConv
import matplotlib.pyplot as plt
import networkx as nx
from sklearn.manifold import TSNE
from sklearn.decomposition import PCA
import os
os.environ['KMP_DUPLICATE_LIB_OK']='True'

# ================== 可调参数 ==================
LEARNING_RATE = 0.01  # 学习率(建议0.001-0.1)
EPOCHS = 200  # 训练轮数(建议100-500)
HIDDEN_DIM = 12  # 隐藏层维度(建议4-16)
VIS_METHOD = 'tsne'  # 可视化方法(tsne/pca)
SEED = 42  # 随机种子(确保可重复性)
# ==============================================

# 设置随机种子保证可重复性
torch.manual_seed(SEED)


# 1. 数据准备与展示
def load_data():
    """加载并展示数据集基本信息"""
    dataset = KarateClub()
    data = dataset[0]

    print("\n数据集信息:")
    print(f"• 节点数: {data.num_nodes}")
    print(f"• 边数: {data.num_edges}")
    print(f"• 特征维度: {data.num_node_features}")
    print(f"• 类别数: {dataset.num_classes}\n")

    return data, dataset


# 2. GNN模型定义
class GNN(torch.nn.Module):
    def __init__(self, input_dim, hidden_dim):
        super().__init__()
        self.conv1 = GCNConv(input_dim, hidden_dim)
        self.conv2 = GCNConv(hidden_dim, hidden_dim)

    def forward(self, x, edge_index):
        x = self.conv1(x, edge_index)
        x = torch.relu(x)
        x = self.conv2(x, edge_index)
        return x


# 3. 可视化工具集
class Visualizer:
    @staticmethod
    def draw_graph(data):
        """原始图结构可视化"""
        G = nx.Graph()
        G.add_edges_from(data.edge_index.numpy().T)

        plt.figure(figsize=(10, 6))
        nx.draw(G,
                node_color=data.y.numpy(),
                cmap=plt.cm.tab10,
                pos=nx.spring_layout(G, seed=SEED),
                with_labels=True)
        plt.title("原始图结构(节点颜色表示真实类别)")
        plt.show()

    @staticmethod
    def visualize(hidden_rep, labels, method='tsne'):
        """高维特征可视化(支持t-SNE/PCA)"""
        plt.figure(figsize=(10, 6))

        # 选择降维方法
        if method.lower() == 'tsne':
            reducer = TSNE(n_components=2, perplexity=10, random_state=SEED)
            title = "t-SNE 可视化"
        else:
            reducer = PCA(n_components=2)
            title = "PCA 可视化"

        # 降维并绘制
        low_dim = reducer.fit_transform(hidden_rep)
        plt.scatter(low_dim[:, 0], low_dim[:, 1],
                    c=labels, cmap=plt.cm.tab10, edgecolors='k')

        plt.title(f"{title}(隐藏层维度={HIDDEN_DIM})")
        plt.xlabel("Component 1")
        plt.ylabel("Component 2")
        plt.colorbar(label="Class")
        plt.show()


# 4. 训练与测试模块
class Trainer:
    def __init__(self, model, data, lr):
        self.model = model
        self.data = data
        self.optimizer = torch.optim.Adam(model.parameters(), lr=lr)
        self.criterion = torch.nn.CrossEntropyLoss()

    def train(self, epochs):
        """训练过程带损失曲线"""
        losses = []
        print("开始训练...")
        for epoch in range(epochs):
            self.optimizer.zero_grad()
            out = self.model(self.data.x, self.data.edge_index)
            loss = self.criterion(out, self.data.y)
            loss.backward()
            self.optimizer.step()
            losses.append(loss.item())

            # 每10%进度打印一次
            if (epoch + 1) % max(epochs // 10, 1) == 0:
                print(f"Epoch {epoch + 1:4d}/{epochs} | Loss: {loss.item():.4f}")

        # 绘制损失曲线
        plt.figure(figsize=(10, 4))
        plt.plot(losses)
        plt.title(f"学习曲线 (LR={LEARNING_RATE})")
        plt.xlabel("Epoch")
        plt.ylabel("Loss")
        plt.show()

    def evaluate(self):
        """模型评估"""
        self.model.eval()
        _, pred = self.model(self.data.x, self.data.edge_index).max(dim=1)
        correct = (pred == self.data.y).sum().item()
        acc = correct / self.data.num_nodes
        print(f"\n模型准确率: {acc * 100:.1f}%")


# 主程序
if __name__ == "__main__":
    # 初始化
    data, dataset = load_data()

    # 可视化原始图
    Visualizer.draw_graph(data)

    # 初始化模型
    model = GNN(input_dim=data.num_node_features, hidden_dim=HIDDEN_DIM)

    # 训练模型
    trainer = Trainer(model, data, lr=LEARNING_RATE)
    trainer.train(EPOCHS)

    # 评估模型
    trainer.evaluate()

    # 可视化隐藏层表示
    with torch.no_grad():
        embeddings = model(data.x, data.edge_index).numpy()

    Visualizer.visualize(embeddings, data.y.numpy(), method=VIS_METHOD)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值