基于Node2Vec的图嵌入实现过程

目录

  • 一、引言
  • 二、Node2Vec(原理)
    • 2.1 随机游走(Random Walk)
    • 2.2 嵌入学习
    • 2.3 Node2Vec 的优势
  • 三、使用 Node2Vec 进行图嵌入(实践)
    • 3.1 读取和转换 JSON 文件为 Graph 对象
    • 3.2 训练 Node2Vec 模型
    • 3.3 二维嵌入可视化
    • 3.4 三维嵌入可视化
    • 3.5 保存嵌入和关系到 JSON 文件
    • 3.6 完整代码
  • 四、结论

一、引言

  随着互联网的发展,社交网络、推荐系统以及知识图谱等应用中的图结构数据越来越多,如何从这些复杂的关系网中提取出有意义的信息,成为了机器学习中的一大挑战。图结构数据的关键在于节点(如用户、物品等)之间的关联关系,而要从图中有效提取节点的特征,我们需要一种能保留图的结构信息的嵌入方法。

  传统的机器学习方法难以直接处理图数据,因为图的结构不如图像和文本那样规则,图中的节点没有固定的顺序,也没有明确的拓扑形式。因此,近年来图嵌入(Graph Embedding)技术得到了广泛关注。通过图嵌入方法,我们可以将图中的节点映射为低维向量,使其能够被应用到分类、聚类、推荐等任务中。

  Node2Vec 是一种基于随机游走(Random Walk)的节点嵌入方法。它通过对图中的节点进行采样,并利用这些采样结果训练出能够表示节点的嵌入向量。这些向量不仅能保留节点的局部邻域信息,还能反映节点在整个图中的全局位置。本文的目的在于详细介绍如何通过代码实践使用Node2Vec进行图嵌入、对嵌入结果进行可视化,并最终将嵌入向量存储为JSON文件。

二、Node2Vec(原理)

2.1 随机游走(Random Walk)

  Node2Vec 基于图上的随机游走来捕捉节点的结构特性。随机游走是一种类似于在图上进行漫步的过程,即从一个节点出发,每次根据一定的概率选择下一个要访问的节点。通过多次游走,Node2Vec可以得到一系列的节点序列,这些序列可以看作是图中的“路径”,用于训练节点的嵌入表示。

  Node2Vec 提供了两个关键参数 p p p q q q,用来控制随机游走的方式:

  • 参数 p p p:回归系数,用于控制游走时返回前一个节点的概率。 p p p 越大,模型越倾向于向更远的节点扩展。

  • 参数 q q q:探索系数,用于控制模型深度优先搜索(DFS)和广度优先搜索(BFS)之间的平衡。 q q q 越大,游走更倾向于深度探索,即更多地访问图的深层节点; q q q 较小时,游走更倾向于广度探索,即优先访问节点的直接邻居。

  通过调节这两个参数,Node2Vec 能够适应不同的任务需求。例如,在社交网络中,我们可能希望重点关注与用户相邻的其他用户,此时较小的 q q q值能帮助我们更好地捕捉局部社区结构。而在知识图谱中,我们可能希望深入挖掘某个概念与远端概念的关系,此时较大的 q q q 值可以帮助捕获图的全局结构。

在这里插入图片描述

2.2 嵌入学习

  一旦通过随机游走得到节点序列,Node2Vec 将这些序列视为词语序列,采用类似 Word2Vec 的 Skip-Gram 模型进行嵌入学习。Skip-Gram 模型的目标是给定一个节点,预测其上下文节点(即在随机游走序列中与该节点相邻的节点)。

  在这个过程中,Node2Vec 学习到每个节点的嵌入向量。这些嵌入向量能够保留节点之间的相似性,邻近的节点将拥有相近的嵌入表示。最终,通过这种方式,图中的每个节点都被映射到一个固定维度的向量空间中,嵌入向量可以直接用于下游任务,如节点分类、边预测和社区检测。

2.3 Node2Vec 的优势

  Node2Vec 的最大优势在于它可以同时捕捉局部和全局的图结构信息。相比于传统的图算法(如PageRank)只考虑节点的全局属性,或者某些仅仅考虑局部连接的嵌入方法,Node2Vec 能够通过灵活的随机游走策略,在不同的场景下取得更好的表现。

  此外,Node2Vec 的随机游走策略可以高效处理大型图,尤其是对于节点和边非常多的复杂网络,Node2Vec 仍然能通过较少的计算时间获得高质量的嵌入向量。

三、使用 Node2Vec 进行图嵌入(实践)

3.1 读取和转换 JSON 文件为 Graph 对象

  在正式训练模型之前,首先我们需要将原始的数据加载为图结构。在很多实际应用场景中,图结构的输入数据并不是直接以图的形式给出,而是以诸如JSON等格式的文件存储了节点之间的关系。因此,第一步的任务是将JSON文件中的节点和边转化为可以用于训练的 Graph 对象。(本文使用的json文件可以从百度网盘下载)

import json
import networkx as nx

# 读取并转换JSON文件为Graph对象的函数
def read_and_convert_json_to_graph(json_file):
    with open(json_file, 'r') as file:
        json_list = json.load(file)

    G = nx.Graph()  # 创建一个空的无向图
    for item in json_list:
        G.add_edge(item['object1'], item['object2'])  # 添加边

    return G

  在上面的代码中,read_and_convert_json_to_graph 函数负责读取JSON文件,并将其中的节点(object1 和 object2)之间的关系转换为图的边(edge)。具体过程如下:

  • 通过 json.load() 将JSON文件中的内容加载为Python的列表格式。

  • 遍历该列表中的每个元素,并使用 networkx 库将两个节点之间的关系加入到无向图 G 中。

  最终,我们会得到一个完整的 Graph 对象,它包含了所有节点及它们之间的连接。这个 Graph 对象将作为Node2Vec 模型的输入,进一步进行节点嵌入训练。

3.2 训练 Node2Vec 模型

  接下来,利用构建好的图对象,我们将使用Node2Vec库进行节点嵌入的训练。Node2Vec 的核心思想是通过随机游走生成节点序列,并通过这些序列学习节点的嵌入表示。

from node2vec import Node2Vec

# Node2Vec模型训练函数
def train_node2vec(graph, dimensions=64, walk_length=30, num_walks=200, p=1, q=1, workers=4):
    node2vec = Node2Vec(graph, dimensions=dimensions, walk_length=walk_length, num_walks=num_walks, p=p, q=q, workers=workers)
    model = node2vec.fit(window=10, min_count=1, batch_words=4)
    return model

  在这个 train_node2vec 函数中,我们定义了几个关键参数来控制Node2Vec的训练过程:

  • dimensions:嵌入向量的维度,即我们希望每个节点被映射到多少维度的向量空间。通常,维度越高,模型能表达的信息越丰富,但训练时间也会增加。

  • walk_length:随机游走的长度,决定每次游走过程中访问的节点数目。

  • num_walks:每个节点的游走次数,即我们为每个节点采样的路径数量。

  • p 和 q:前面介绍的控制游走策略的两个参数,分别控制返回前一节点的概率和探索新节点的概率。

  • workers:并行计算的线程数,用于加速训练过程。

  训练完成后,fit() 函数返回的是一个包含了所有节点嵌入向量的模型对象。我们可以通过该模型获取每个节点的嵌入向量,并将这些向量用于后续的任务。

3.3 二维嵌入可视化

  在训练完Node2Vec模型并得到节点的高维嵌入向量后,直接查看这些高维向量并不直观,因此我们通常需要将其降维,以便通过图形展示这些节点在嵌入空间中的分布情况。

  二维可视化是最常用的手段之一。我们可以使用降维算法(如主成分分析 PCA)将嵌入向量从高维空间降至二维,从而通过平面图直观展示节点之间的相对位置。接下来是实现代码:

import numpy as np
import matplotlib.pyplot as plt
from sklearn.decomposition import PCA

# 二维可视化嵌入的函数
def visualize_embeddings(model, graph, save_path='embeddings_visualization.png'):
    # 获取所有节点的嵌入向量
    embeddings = np.array([model.wv[str(node)] for node in graph.nodes()])
    
    # 使用PCA将嵌入向量降维到2D
    pca = PCA(n_components=2)
    embeddings_2d = pca.fit_transform(embeddings)

    # 绘制图形
    plt.figure(figsize=(20, 16))  # 设置图形大小
    pos = {node: embeddings_2d[i] for i, node in enumerate(graph.nodes())}

    # 绘制节点,设置节点大小和颜色
    nx.draw_networkx_nodes(graph, pos=pos, node_size=30, node_color='blue')

    # 绘制图中的边,透明度alpha设置较低以减少边线干扰
    nx.draw_networkx_edges(graph, pos=pos, alpha=0.1)

    # 隐藏坐标轴
    plt.axis('off')

    # 保存结果并展示图像
    plt.savefig(save_path)
    plt.show()
  • 获取节点嵌入向量:从训练好的 Node2Vec 模型中提取节点的嵌入向量,这些嵌入向量被保存在 model.wv 中,其中每个节点的 ID 被转化为字符串格式。

  • PCA降维:使用 PCA 将高维嵌入向量降至二维。PCA 是一种常见的降维技术,它能够提取数据中最重要的两个主成分,使得降维后的数据尽可能保留原始高维数据中的信息。

  • 节点和边的可视化:通过 networkx 提供的 draw_networkx_nodes 和 draw_networkx_edges 方法来绘制图形中的节点和边。节点颜色为蓝色,边的透明度较低,以减少边线的干扰,使节点的位置关系更加清晰可见。

  • 图形保存与显示:绘制好的图形保存为 PNG 文件,并显示出来以供查看。plt.savefig() 可以保存结果,plt.show() 用于在执行程序时显示图像。

  通过这种方式,节点会根据其嵌入向量的相似性在二维平面上分布。距离较近的节点往往在嵌入空间中更为相似,说明它们在图结构中有更密切的联系。反之,距离较远的节点可能属于不同的社区或子图。

3.4 三维嵌入可视化

  虽然二维可视化已经能帮助我们理解节点嵌入,但在某些场景中,我们可能希望更丰富的维度来展示节点的分布。此时,三维可视化可以提供更直观的展示效果。通过降维到三维,我们能够通过三维图形进一步观察节点的相互关系。

from mpl_toolkits.mplot3d import Axes3D
from sklearn.decomposition import PCA

# 三维可视化嵌入的函数
def visualize_embeddings_3d(model, graph, save_path='embeddings_visualization_3d.png'):
    # 获取所有节点的嵌入向量
    embeddings = np.array([model.wv[str(node)] for node in graph.nodes()])
    
    # 使用PCA将嵌入向量降维到3D
    pca = PCA(n_components=3)
    embeddings_3d = pca.fit_transform(embeddings)

    # 创建3D绘图
    fig = plt.figure(figsize=(20, 16))
    ax = fig.add_subplot(111, projection='3d')

    # 获取嵌入向量的三个维度(x, y, z坐标)
    xs = embeddings_3d[:, 0]
    ys = embeddings_3d[:, 1]
    zs = embeddings_3d[:, 2]

    # 绘制节点
    ax.scatter(xs, ys, zs, c='blue', marker='o')

    # 设置轴标签
    ax.set_xlabel('PCA1')
    ax.set_ylabel('PCA2')
    ax.set_zlabel('PCA3')

    # 添加标题
    plt.title('3D visualization of Node Embeddings')

    # 保存并展示图像
    plt.savefig(save_path)
    plt.show()
  • PCA降维到三维:与二维可视化类似,这里我们将嵌入向量从高维空间降至三维。这三个维度能够提供更多的嵌入信息,从而帮助我们更好地观察节点的分布情况。

  • 三维绘图:通过 mpl_toolkits.mplot3d 的 Axes3D 类进行三维图形的绘制。我们提取PCA降维后的三个维度(x、y、z坐标),并将其用于三维散点图的绘制。

  • 散点绘制:使用 scatter() 函数绘制节点,每个节点显示为一个三维点。我们可以通过颜色、大小、标记等属性来调整节点的视觉效果。在本例中,节点颜色为蓝色,标记为圆形。

  • 图形轴标签与标题:为三维图形的各个坐标轴(PCA1、PCA2、PCA3)添加标签,以便清晰显示每个维度代表的含义。此外,还为图形添加了标题,方便理解可视化内容。

  三维图形相比于二维图形能够展示更多的信息。特别是在处理嵌入维度较高的情况下,三维可视化能够帮助我们更好地理解节点在嵌入空间中的位置关系。通过旋转三维图形,我们可以从不同角度观察节点的分布情况,发现潜在的社区结构或其他有趣的模式。

3.5 保存嵌入和关系到 JSON 文件

  在获得了节点嵌入向量后,我们往往需要将这些向量保存下来,方便后续的分析与应用。在实际项目中,我们可能需要将嵌入向量与原始的关系数据一起存储,以便后续模型或任务能够继续利用这些嵌入。

  下面的代码展示了如何将节点的嵌入向量与原始的JSON文件结合,并将结果保存为一个新的JSON文件。

def save_embeddings_to_json(graph, model, json_file_path, output_file):
    # 读取原始的JSON文件来获取对象间的关系
    with open(json_file_path, 'r') as file:
        json_list = json.load(file)

    output_data = []

    for item in json_list:
        object1, object2 = item['object1'], item['object2']

        # 对于每对对象,获取其嵌入向量
        properties1 = model.wv[object1].tolist() if object1 in model.wv else None
        properties2 = model.wv[object2].tolist() if object2 in model.wv else None

        # 构建新的字典项,包含嵌入向量和原始关系
        modified_item = {
            "object1": object1,
            "properties1": properties1,
            "object2": object2,
            "properties2": properties2,
            "relationship": item.get('relationship')  # 假设原始JSON中包含关系字段
        }
        output_data.append(modified_item)

    # 将修改后的数据写入新的JSON文件
    with open(output_file, 'w') as f:
        json.dump(output_data, f, indent=4)
  • 原始关系读取:首先,我们读取原始的JSON文件,获取其中包含的节点及其关系。在本例中,JSON文件中的每一条记录包含两个对象(object1 和 object2),代表它们之间的某种关系。

  • 嵌入向量提取:对于每个对象,我们通过模型中的 model.wv 获取其对应的嵌入向量。如果某个对象没有嵌入向量(例如由于它在训练中未出现),我们可以将其设置为 None。

  • 数据结构修改:将每对对象的嵌入向量(properties1 和 properties2)与它们的关系信息(relationship)一起构造一个新的数据项。

  • 结果保存:最终,将所有修改后的数据写入一个新的JSON文件,以便在后续的分析中使用。

3.6 完整代码

import json
import numpy as np
from node2vec import Node2Vec
import networkx as nx
import matplotlib.pyplot as plt


# 读取并转换JSON文件为Graph对象的函数
def read_and_convert_json_to_graph(json_file):
    with open(json_file, 'r') as file:
        json_list = json.load(file)

    G = nx.Graph()  # 创建一个空的无向图
    for item in json_list:
        G.add_edge(item['object1'], item['object2'])  # 添加边

    return G


# Node2Vec模型训练函数
def train_node2vec(graph, dimensions=64, walk_length=30, num_walks=200, p=1, q=1, workers=4):
    # 使用Node2Vec库
    node2vec = Node2Vec(graph, dimensions=dimensions, walk_length=walk_length, num_walks=num_walks, p=p, q=q,
                        workers=workers)

    # 训练模型
    model = node2vec.fit(window=10, min_count=1, batch_words=4)

    return model


# 可视化嵌入的函数,实现二维可视化
def visualize_embeddings(model, graph, save_path='embeddings_visualization.png'):
    # 获取嵌入向量
    embeddings = np.array([model.wv[str(node)] for node in graph.nodes()])

    # 使用PCA进行降维以便于可视化
    from sklearn.decomposition import PCA
    pca = PCA(n_components=2)
    embeddings_2d = pca.fit_transform(embeddings)

    # 绘制节点嵌入
    plt.figure(figsize=(20, 16))
    pos = {node: embeddings_2d[i] for i, node in enumerate(graph.nodes())}

    # 调整节点大小和边的透明度
    nx.draw_networkx_nodes(graph, pos=pos, node_size=30, node_color='blue')
    edges = nx.draw_networkx_edges(graph, pos=pos, alpha=0.1)  # 减少alpha以降低边的透明度

    plt.axis('off')  # 关闭坐标轴
    plt.savefig(save_path, format='PNG')  # 先保存可视化结果到文件
    plt.show()  # 然后显示图像
    plt.close()  # 关闭图形,防止重复显示

# 修改后的可视化嵌入函数,实现三维可视化
def visualize_embeddings_3d(model, graph, save_path='embeddings_visualization_3d.png'):
    # 获取嵌入向量
    embeddings = np.array([model.wv[str(node)] for node in graph.nodes()])

    # 使用PCA进行到3维的降维
    from sklearn.decomposition import PCA
    pca = PCA(n_components=3)
    embeddings_3d = pca.fit_transform(embeddings)

    # 创建3D绘图
    fig = plt.figure(figsize=(20, 16))
    ax = fig.add_subplot(111, projection='3d')

    # 获取节点的三维坐标
    xs = embeddings_3d[:, 0]
    ys = embeddings_3d[:, 1]
    zs = embeddings_3d[:, 2]

    # 绘制节点
    ax.scatter(xs, ys, zs, c='blue', marker='o')

    ax.set_xlabel('PCA1')
    ax.set_ylabel('PCA2')
    ax.set_zlabel('PCA3')
    plt.title('3D visualization of Node Embeddings')

    plt.savefig(save_path, format='PNG')  # 保存可视化结果到文件
    plt.show()  # 显示图像
    plt.close()  # 关闭图形,防止重复显示

def save_embeddings_to_json(graph, model, json_file_path, output_file):
    # 首先,读取原始的JSON文件来获取对象间的关系
    with open(json_file_path, 'r') as file:
        json_list = json.load(file)

    output_data = []

    for item in json_list:
        object1, object2 = item['object1'], item['object2']
        # 对于每对对象,获取其嵌入向量
        properties1 = model.wv[object1].tolist() if object1 in model.wv else None
        properties2 = model.wv[object2].tolist() if object2 in model.wv else None
        # 构建新的字典项
        modified_item = {
            "object1": object1,
            "properties1": properties1,
            "object2": object2,
            "properties2": properties2,
            "relationship": item.get('relationship')  # 假设原始JSON中包含关系字段
        }
        output_data.append(modified_item)

    # 将修改后的数据写入新的JSON文件
    with open(output_file, 'w') as f:
        json.dump(output_data, f, indent=4)

# 主程序
if __name__ == "__main__":
    json_file_path = 'Node2Vec_Input.json'
    output_file = 'Node2Vec_Embeddings_Dim768.json'

    G = read_and_convert_json_to_graph(json_file_path)

    #节点嵌入维度为dimensions
    model = train_node2vec(G, dimensions=768, walk_length=20, num_walks=200, p=1, q=2, workers=4)
    visualize_embeddings_3d(model, G, 'embeddings_visualization_Dim768_3D_20-200-1-2-4.png')

    # 调用新定义的函数,保存嵌入和关系到JSON
    save_embeddings_to_json(G, model, json_file_path, output_file)

四、结论

  通过以上的过程,我们完整地介绍了如何使用Node2Vec进行图嵌入、如何将嵌入结果可视化以及如何保存嵌入向量。Node2Vec 提供了一种灵活且高效的方式来处理图数据,并且能够通过参数调整适应不同的图结构。通过嵌入向量,我们可以将图结构信息转化为适合机器学习模型处理的低维向量形式,从而为分类、聚类、推荐系统等任务提供支持。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/887644.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

MySQL--三大范式(超详解)

目录 一、前言二、三大范式2.1概念2.2第一范式(1NF)2.3第二范式(2NF)2.3第三范式(3NF) 一、前言 欢迎大家来到权权的博客~欢迎大家对我的博客进行指导,有什么不对的地方,我会及时改进…

使用前端三剑客实现一个备忘录

一,界面介绍 这个备忘录的界面效果如下: 可以实现任务的增删,并且在任务被勾选后会被放到已完成的下面。 示例: (1),增加一个任务 (2),勾选任务 &#xff…

影视cms泛目录用什么程序?苹果cms二次开发泛目录插件

影视CMS泛目录一般使用的程序有很多种,(maccmscn)以下是其中几种常见的程序: WordPress:WordPress是一个非常流行的开源内容管理系统,可以通过安装一些插件来实现影视CMS泛目录功能。其中,一款常…

Linux中的进程间通信之共享内存

共享内存 共享内存示意图 共享内存数据结构 struct shmid_ds {struct ipc_perm shm_perm; /* operation perms */int shm_segsz; /* size of segment (bytes) */__kernel_time_t shm_atime; /* last attach time */__kernel_time_t shm_dtime; /* last detach time */__kerne…

招联2025校招内推倒计时

【投递方式】 直接扫下方二维码,或点击内推官网https://wecruit.hotjob.cn/SU61025e262f9d247b98e0a2c2/mc/position/campus,使用内推码 igcefb 投递) 【招聘岗位】 后台开发 前端开发 数据开发 数据运营 算法开发 技术运维 软件测试 产品策…

制作离线版Koczkatamas工具包

一、下载源码 从https://github.com/koczkatamas/koczkatamas.github.io下载koczkatamas.github.io-master.zip 二、解压 $ unzip koczkatamas.github.io-master.zip三、运行index.html 可以看到输入一个字符后,下面的各种编码都没有显示,则表示运行…

力扣刷题 | 两数之和

目前主要分为三个专栏,后续还会添加: 专栏如下: C语言刷题解析 C语言系列文章 我的成长经历 感谢阅读! 初来乍到,如有错误请指出,感谢! 给定一个整数数组 nums 和…

UOM无人机空域快速申请技术详解

UOM无人机空域快速申请技术详解主要包括以下几个步骤: 一、准备阶段 1. 实名登记:首先,您需要在相应的民航部门进行无人机的实名登记,这是合法飞行的前提。 2. 了解规定:熟悉并遵守当地关于无人机飞行的法律法规&am…

【微服务】初识(day1)

基础概念 集群 集群是将一个系统完整的部署到多个服务器,每个服务器提供系统的所有服务,多个服务器可以通过负载均衡完成任务,每个服务器都可以称为集群的节点。 分布式 分布式是将一个系统拆分为多个子系统,多个子系统部署在…

YOLO--前置基础词-学习总结

RFBNet是什么意思 RFBNet 是一种用于目标检测的深度学习网络,它的名字来源于 "Receptive Field Block Network"(感受野块网络)。简单来说,RFBNet 是一种可以让计算机更好地“看”图像中不同大小的物体的方法。 在图像处…

【重学 MySQL】五十四、整型数据类型

【重学 MySQL】五十四、整型数据类型 整型类型TINYINTSMALLINTMEDIUMINTINT(或INTEGER)BIGINT 可选属性UNSIGNEDZEROFILL显示宽度(M)AUTO_INCREMENT注意事项 适合场景TINYINTSMALLINTMEDIUMINTINT(或INTEGER&#xff0…

tftp传文件被服务器拒绝进入tftp: server error: (768) Access to staonline.pcap denied

环境:测试一个ac下挂ap,ap下的抓包文件传出时,出现问题: ac的wan口ip是192.168.186.167/24,gw是192.168.186.1,下挂ap的ip是192.168.202.199/24,ac上开子接口192.168.202.1/24,ac上开…

C++ | Leetcode C++题解之第456题132模式

题目&#xff1a; 题解&#xff1a; class Solution { public:bool find132pattern(vector<int>& nums) {int n nums.size();vector<int> candidate_i {nums[0]};vector<int> candidate_j {nums[0]};for (int k 1; k < n; k) {auto it_i upper_…

微服务获取用户信息和OpenFeign传递用户

问题一&#xff1a; 网关已经完成登录校验并获取登录用户身份信息。但是当网关将请求转发到微服务时&#xff0c;微服务又该如何获取用户身份呢&#xff1f; 由于网关发送请求到微服务依然采用的是Http请求&#xff0c;因此我们可以将用户信息以请求头的方式传递到下游微服务…

PC端微信小程序如何调试?

向往常一样运行开微信小程序开发者工具 如果只弹出pc端小程序&#xff0c;没有出现调试的界面&#xff1a;点击胶囊按钮的三个…选择重新进入小程序 即可依次展开相应的功能调试&#xff0c;改完代码没反应再刷新看看&#xff0c;再没反应就再次重新点击编译并自动调试。

论文 | Model-tuning Via Prompts Makes NLP Models Adversarially Robust

这篇论文研究了使用提示 (Prompting) 方法微调预训练语言模型&#xff0c;以提高其在对抗样本攻击下的鲁棒性。论文的主要贡献如下&#xff1a; 1.MVP 比 MLP-FT 更鲁棒&#xff1a; 论文比较了 MVP (Model-tuning Via Prompts) 和传统的 MLP-FT (Fine-tuning with an MLP head…

C++模版SFIANE应用踩的一个小坑

一天一个C大佬同事&#xff0c;突然截图过来一段代码&#xff1a;这写的啥呀&#xff0c;啰里吧嗦的&#xff0c;这个构造函数模板参数T1感觉是多余的呀 template<class T> class TestClass { public:TestClass(){}//函数1template<class T1 T, std::enable_if_t<…

VTC视频时序控制器,TPG图像测试数据发生器,LCD驱动——FPGA学习笔记19

详情可以见LCD篇 LCD彩条显示——FPGA学习笔记10_依次显示红绿蓝三个通道-CSDN博客 一、VTC简介 Video Timing Controller 缩写 VTC 是我们在所有涉及 FPGA 图像、 FPGA 视频类方案中经常用到的一种用于产生视频时序的控制器。 本课以 VGA 为切入点&#xff0c; 学习视频传输…

Java IO流全面教程

此笔记来自于B站黑马程序员 File 创建对象 public class FileTest1 {public static void main(String[] args) {// 1.创建一个 File 对象&#xff0c;指代某个具体的文件// 路径分隔符// File f1 new File("D:/resource/ab.txt");// File f1 new FIle("D:\\…

【Golang】Go语言中时间time相关处理方法

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…