学习笔记-250222

论文:

Learning Hierarchical Prompt with Structured Linguistic Knowledge for
Vision-Language Models
主要研究llm在图像分类中的能力,当提示输入目标类别时,llm能够生成相关的描述以及相应的结构化关系。

1.首先利用llm从普通的描述中获取结构化信息

利用llm来生成与类别相关的描述以及相应的结构化关系;

笑鼠,代码还没看,光看论文觉得太复杂了,引入Q矩阵(e2e和e2a)entity实体。attribute属性。

1.使用结构化知识指导学习得到的基于注意力的矩阵(attention-based matrices),并将这些矩阵集成到文本编码器的不同层中。

在实践中,通过同时计算一组查询(queries)上的注意力函数来实现这一点。这些查询被打包成一个矩阵Q。类似地,键(keys)和值(values)也被分别打包成矩阵K和V。

对于第l层,使用基于注意力的矩阵MlMl​,自注意力的输出通过以下公式计算:

这里,Ml​是为每一层特别设计的矩阵,用于显式表示该层内每个描述的丰富结构关系,从而增强与类别相关的关键信息。

2.层次化的知识建模方法,将来自多个层次的整体语义与结构化关系相结合,有助于发现大型语言模型(LLMs)未能识别的复杂关联。

  • 整合结构化知识:通过在自注意力机制中引入额外的矩阵Ml​,可以更好地捕捉输入数据中的结构化信息,这有助于提高模型对于特定任务的表现。

  • 跨层级自注意力:这种方法允许模型自动学习不同抽象层次之间的关系,无需人为定义这些关系。它通过结合高层次和全局级别的提示,能够捕捉长程依赖性和复杂的语义联系。

  • 增强表达能力:通过上述机制,模型不仅能够理解单个词或短语的意义,还能捕捉整个句子或段落内部以及跨句子、跨段落之间的复杂关系,从而提升对文本深层次含义的理解能力。

该技术通过在自注意力机制中融入结构化知识和跨层级提示,增强了模型理解和表达复杂文本关系的能力。

反正很复杂,看不懂......

250223

迁移:主要是学生不同

或者是知识点不同

如果二者都不一样,那没办法搞啊

阅读文章:

Prompt-to-prompt:让生成的图像保持一致 - 知乎

理了下PromptCD代码:

publisher-PromptCD/PromptCD: PromptCD:传输跨域认知诊断的提示

以irt模型为例:

1.初始化irt模型

初始化中

self.pp_dim = pp_dim                     # 提示向量维度
self.latent_dim = latent_dim             # 潜在特征维度
self.s_irt_net = Source_MIRTNet(         # 源域模型
    user_num, s_item_num, latent_dim, 
    pp_dim, s_ranges, a_range
)  
self.t_irt_net = Target_MIRTNet(         # 目标域模型(版本1)
    user_num, t_item_num, latent_dim, 
    pp_dim, s_ranges, a_range
)  
self.t_irt_net2 = Target_MIRTNet2(       # 目标域模型(初始化有优化)
    user_num, t_item_num, latent_dim, 
    pp_dim, s_ranges, a_range
)
class Source_MIRTNet(nn.Module):
    def __init__(self, user_num, item_num, latent_dim, pp_dim, s_ranges, a_range, irf_kwargs=None):
        super(Source_MIRTNet, self).__init__()
        self.user_num = user_num
        self.item_num = item_num
        self.pp_dim = pp_dim
        self.s_ranges = s_ranges
        self.latent_dim = latent_dim
        self.irf_kwargs = irf_kwargs if irf_kwargs is not None else {}

        self.b = nn.Parameter(torch.rand((self.item_num, self.latent_dim)))
        nn.init.xavier_uniform_(self.b)
        self.s_exer_vectors = nn.ParameterList([nn.Parameter(torch.rand(self.pp_dim)) for _ in range(len(s_ranges))])

        self.theta = nn.ParameterList([nn.Parameter(torch.randn(self.user_num, self.latent_dim))
                                       for _ in range(len(s_ranges))])
        for theta in self.theta:
            nn.init.xavier_uniform_(theta)

        self.prompt_theta = nn.Parameter(torch.randn(self.user_num, self.pp_dim))
        nn.init.xavier_uniform_(self.prompt_theta)

        self.a = nn.Embedding(self.item_num, 1)
        self.c = nn.Embedding(self.item_num, 1)

        self.a_range = 1
        self.value_range = 8

        self.fc1 = nn.Linear(self.pp_dim + self.latent_dim, self.latent_dim)
        self.fc2 = nn.Linear(self.pp_dim + self.latent_dim, self.latent_dim)

    def forward(self, user, item):
        prompt_theta_repeated = self.prompt_theta.repeat(len(self.s_ranges), 1)
        theta_concatenated = torch.cat([theta for theta in self.theta], dim=0)
        new_theta = torch.cat([prompt_theta_repeated, theta_concatenated], dim=1)
        new_theta = torch.index_select(new_theta, dim=0, index=user)
        new_theta = self.fc1(new_theta)
        new_theta = torch.squeeze(new_theta, dim=-1)

        temp_vectors = torch.cat(
            [vector.repeat(r[1] - r[0] + 1, 1) for vector, r in zip(self.s_exer_vectors, self.s_ranges)], dim=0)

        all_b = torch.cat([temp_vectors, self.b], dim=1)
        new_b = torch.index_select(all_b, dim=0, index=item)
        new_b = self.fc2(new_b)
        new_b = torch.squeeze(new_b, dim=-1)

        new_a = self.a(item)
        new_a = torch.squeeze(new_a, dim=-1)

        new_c = torch.squeeze(self.c(item), dim=-1)
        new_c = torch.sigmoid(new_c)

        if self.value_range is not None:
            new_theta = self.value_range * (torch.sigmoid(new_theta) - 0.5)
            new_b = self.value_range * (torch.sigmoid(new_b) - 0.5)
        if self.a_range is not None:
            new_a = self.a_range * torch.sigmoid(new_a)
        else:
            new_a = F.softplus(new_a)

#------------------------------
        if torch.max(new_theta != new_theta) or torch.max(new_a != new_a) or torch.max(new_b != new_b):  # pragma: no cover
            raise ValueError('ValueError:theta,a,b may contains nan!  The a_range is too large.')
        return self.irf(new_theta, new_a, new_b, new_c, **self.irf_kwargs)
class Source_MIRTNet(nn.Module):
    def __init__(self, user_num, item_num, latent_dim, pp_dim, s_ranges, a_range, irf_kwargs=None):
        super(Source_MIRTNet, self).__init__()
        # 基础参数
        self.user_num = user_num          # 用户总数
        self.item_num = item_num          # 题目总数(源域)
        self.pp_dim = pp_dim              # 提示向量维度(用于迁移学习)
        self.s_ranges = s_ranges          # 源域题目范围划分(如知识点分类)
        self.latent_dim = latent_dim      # 潜在特征维度(用户能力θ和题目难度b的维度)
        self.irf_kwargs = irf_kwargs      # IRT模型参数(如三参数模型配置)
        self.a_range = a_range           # 区分度a的范围约束(如[0,1])
        self.value_range = 8             # θ和b的范围约束(如[-4,4])

题目参数:(主要看题目范围参数,每个范围一个pp_dim维向量)

# 题目难度参数(b):每个题目对应一个latent_dim维向量
self.b = nn.Parameter(torch.rand((self.item_num, self.latent_dim)))
nn.init.xavier_uniform_(self.b)  # Xavier初始化

# 题目范围嵌入向量(s_exer_vectors):每个范围一个pp_dim维向量
self.s_exer_vectors = nn.ParameterList([
    nn.Parameter(torch.rand(self.pp_dim)) 
    for _ in range(len(s_ranges))  # 根据s_ranges长度创建(如代数、几何各一个)
])

用户参数:

# 用户能力参数(theta):每个范围独立的能力矩阵(如代数能力、几何能力)
self.theta = nn.ParameterList([
    nn.Parameter(torch.randn(self.user_num, self.latent_dim))
    for _ in range(len(s_ranges))
])
for theta in self.theta:  # Xavier初始化每个能力矩阵
    nn.init.xavier_uniform_(theta)

# 用户提示向量(prompt_theta):跨范围共享的迁移适配参数
self.prompt_theta = nn.Parameter(torch.randn(self.user_num, self.pp_dim))
nn.init.xavier_uniform_(self.prompt_theta)

其中:torch.randn 函数用于生成一个形状为 (self.user_num, self.pp_dim) 的张量,其中的元素是从标准正态分布(均值为0,标准差为1)中随机抽取的。
self.user_num 表示用户的数量,而 self.pp_dim 则代表预处理维度或先验/后验维度的大小。这个二维张量可以看作是每个用户对应的一个向量集合,每个向量的长度为 pp_dim。

self.prompt_theta: 此变量被设计用来存储与每个用户相关的“提示”向量。这里的“提示”可能是指某种形式的上下文信息或额外特征,旨在增强模型对不同用户行为的理解能力。这些向量初始时是随机的,但随着模型的训练,它们将根据任务需求进行调整,以更好地捕捉每个用户的独特偏好或特性。
初始化:使用标准正态分布来初始化这些参数是一种常见的做法,因为它有助于打破对称性,使得神经网络中的各个神经元能够学习不同的特征,从而加速训练过程。

题目区分度与猜测函数:

self.a = nn.Embedding(self.item_num, 1)  # 区分度参数a
self.c = nn.Embedding(self.item_num, 1)  # 猜测概率参数c
特征融合层
self.fc1 = nn.Linear(pp_dim + latent_dim, latent_dim)  # 用户特征融合
self.fc2 = nn.Linear(pp_dim + latent_dim, latent_dim)  # 题目特征融合

2. 前向传播逻辑解析

(1) 用户能力生成
def forward(self, user, item):
    # 步骤1:扩展提示向量以匹配范围数量
    prompt_theta_repeated = self.prompt_theta.repeat(len(self.s_ranges), 1)
    # 示例:若s_ranges有2个范围,则每个用户的提示向量复制2次

    # 步骤2:拼接所有范围的用户能力(theta_concatenated)
    theta_concatenated = torch.cat([theta for theta in self.theta], dim=0)
    # 结果形状:(num_ranges * user_num, latent_dim)

    # 步骤3:将提示向量与用户能力拼接
    new_theta = torch.cat([prompt_theta_repeated, theta_concatenated], dim=1)
    # 形状:(num_ranges * user_num, pp_dim + latent_dim)

    # 步骤4:根据输入的user索引选择对应的融合特征
    new_theta = torch.index_select(new_theta, dim=0, index=user)
    # 假设user是批量用户的索引,形状:(batch_size,)

    # 步骤5:通过全连接层生成最终用户能力
    new_theta = self.fc1(new_theta)  # 输出形状:(batch_size, latent_dim)
    new_theta = torch.squeeze(new_theta, dim=-1)

设计意图

  • 分范围能力建模:每个范围(如知识点)的用户能力独立存储,增强模型对领域内细粒度差异的捕捉。

  • 提示向量融合:通过 prompt_theta 引入迁移学习能力,为后续目标域适配提供接口。

# 步骤1:生成题目范围特征(temp_vectors)
temp_vectors = torch.cat([
    vector.repeat(r[1] - r[0] + 1, 1) 
    for vector, r in zip(self.s_exer_vectors, self.s_ranges)
], dim=0)
# 示例:若s_ranges为[(0,99), (100,199)],则每个范围向量重复100次

# 步骤2:拼接范围特征与题目基础难度b
all_b = torch.cat([temp_vectors, self.b], dim=1)  # 形状:(item_num, pp_dim + latent_dim)

# 步骤3:根据输入的item索引选择题目特征
new_b = torch.index_select(all_b, dim=0, index=item)  # 形状:(batch_size, pp_dim + latent_dim)

# 步骤4:通过全连接层生成最终题目难度
new_b = self.fc2(new_b)  # 形状:(batch_size, latent_dim)
new_b = torch.squeeze(new_b, dim=-1)
(3) 题目参数提取与约束
# 区分度参数a
new_a = self.a(item)                    # 形状:(batch_size, 1)
new_a = torch.squeeze(new_a, dim=-1)    # 形状:(batch_size,)

# 猜测概率参数c(通过sigmoid约束到[0,1])
new_c = torch.squeeze(self.c(item), dim=-1)
new_c = torch.sigmoid(new_c)            # 形状:(batch_size,)

# 参数范围约束
if self.value_range is not None:
    new_theta = self.value_range * (torch.sigmoid(new_theta) - 0.5)  # [-value_range/2, value_range/2]
    new_b = self.value_range * (torch.sigmoid(new_b) - 0.5)          # 同上
if self.a_range is not None:
    new_a = self.a_range * torch.sigmoid(new_a)                      # [0, a_range]
else:
    new_a = F.softplus(new_a)  # 确保非负

前向传播流程图——

用户输入 → [分范围theta] → 拼接 → 融合提示向量 → fc1 → 标准化 → IRF
            ↗ (prompt_theta)
题目输入 → [范围嵌入 + 基础b] → fc2 → 标准化 → IRF
           ↘ [a, c] → 标准化 → IRF

就是在target训练的时候,只改变prompt向量部分,达到利用源目标数据的作用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值