You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于可训练加权融合多嵌入矩阵的简易情感分类器构建问题

实现每个单词独立加权的多嵌入融合情感分类器

嘿,这个需求很实用啊!本质上就是给每个单词学习一对专属的权重,把不同预训练嵌入的词向量加权融合后再做分类,我给你拆解下具体怎么在主流框架里实现~

核心思路回顾

你要的是对每个单词w,计算x[w] * E1[w] + y[w] * E2[w],其中x和y是每个词独有的可学习参数。这里要注意两个关键点:

  • 确保两个嵌入矩阵的维度一致(如果不一样,得先做维度映射)
  • 让x和y能跟着输入的词索引动态取对应权重

PyTorch 实现步骤

假设你已经准备好了词汇表、预训练的Glove嵌入矩阵E1(形状[vocab_size, embed_dim1])和Word2vec嵌入矩阵E2(形状[vocab_size, embed_dim2]):

1. 初始化组件

import torch
import torch.nn as nn

# 加载预训练嵌入,转成张量
E1 = torch.tensor(glove_embeddings, dtype=torch.float32)
E2 = torch.tensor(word2vec_embeddings, dtype=torch.float32)

# 如果两个嵌入维度不同,加个线性层把E2映射到E1的维度
if E1.shape[1] != E2.shape[1]:
    dim_mapper = nn.Linear(E2.shape[1], E1.shape[1])
else:
    dim_mapper = nn.Identity()  # 维度相同就用恒等层

# 定义每个词的可学习权重x和y,初始可以设为0.5(均等加权)
X = nn.Parameter(torch.full((E1.shape[0],), 0.5, dtype=torch.float32))
Y = nn.Parameter(torch.full((E1.shape[0],), 0.5, dtype=torch.float32))

# 如果不想微调预训练嵌入,冻结它们的梯度
E1.requires_grad_(False)
E2.requires_grad_(False)

2. 构建模型类

class WeightedEmbedClassifier(nn.Module):
    def __init__(self, vocab_size, embed_dim, num_classes):
        super().__init__()
        self.E1 = E1
        self.E2 = E2
        self.dim_mapper = dim_mapper
        self.X = X
        self.Y = Y
        # 分类头:先池化再全连接
        self.pool = nn.AdaptiveAvgPool1d(1)
        self.classifier = nn.Linear(embed_dim, num_classes)
    
    def forward(self, input_ids):
        # input_ids形状:[batch_size, seq_len]
        # 取出对应词的嵌入向量
        e1 = self.E1[input_ids]  # [batch_size, seq_len, embed_dim1]
        e2 = self.dim_mapper(self.E2[input_ids])  # 映射后和e1维度一致
        
        # 取出对应词的权重,增加维度以便和词向量相乘
        x_weights = self.X[input_ids].unsqueeze(-1)  # [batch_size, seq_len, 1]
        y_weights = self.Y[input_ids].unsqueeze(-1)
        
        # 加权融合
        merged_embeds = x_weights * e1 + y_weights * e2
        
        # 句子级池化:把序列维度压缩掉
        sentence_embed = self.pool(merged_embeds.transpose(1,2)).squeeze(-1)
        
        # 分类预测
        logits = self.classifier(sentence_embed)
        return logits

TensorFlow/Keras 实现步骤

同样先准备好预训练嵌入的numpy数组:

1. 构建模型

import tensorflow as tf

vocab_size = len(vocab)
embed_dim1 = E1.shape[1]
embed_dim2 = E2.shape[1]
num_classes = 2  # 假设是二分类情感任务

# 输入层:接收词索引序列
input_ids = tf.keras.layers.Input(shape=(seq_len,))

# 加载预训练嵌入层,默认冻结不微调
embedding1 = tf.keras.layers.Embedding(
    vocab_size, embed_dim1, weights=[E1], trainable=False
)(input_ids)
embedding2 = tf.keras.layers.Embedding(
    vocab_size, embed_dim2, weights=[E2], trainable=False
)(input_ids)

# 维度映射(如果需要)
if embed_dim1 != embed_dim2:
    embedding2 = tf.keras.layers.Dense(embed_dim1)(embedding2)

# 定义每个词的可学习权重:用Embedding层实现每个索引对应一个标量权重
x_weights = tf.keras.layers.Embedding(
    vocab_size, 1, embeddings_initializer=tf.keras.initializers.Constant(0.5)
)(input_ids)
y_weights = tf.keras.layers.Embedding(
    vocab_size, 1, embeddings_initializer=tf.keras.initializers.Constant(0.5)
)(input_ids)

# 加权融合
merged_embeds = tf.multiply(x_weights, embedding1) + tf.multiply(y_weights, embedding2)

# 句子级池化
sentence_embed = tf.keras.layers.GlobalAveragePooling1D()(merged_embeds)

# 分类头
logits = tf.keras.layers.Dense(num_classes, activation='softmax')(sentence_embed)

# 组装模型
model = tf.keras.Model(inputs=input_ids, outputs=logits)
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])

一些实用小贴士

  • 正则化防过拟合:可以给X和Y加L2正则化,比如PyTorch里在定义参数时加weight_decay=1e-4,Keras里在Embedding层加kernel_regularizer=tf.keras.regularizers.l2(1e-4)
  • 微调预训练嵌入:如果想让Glove/Word2vec的嵌入也跟着优化,只需要把E1.requires_grad_(True)(PyTorch)或者trainable=True(Keras)即可
  • 权重初始化:除了0.5,也可以用随机正态分布初始化,或者根据任务调整初始权重偏向某一个嵌入

内容的提问来源于stack exchange,提问作者yftah89

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 09:06:07