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

BERT特征提取作为CNN/LSTM嵌入层的Keras实现及报错解决

问题解决与实现方案

一、当前报错原因修复

报错根因

你当前的报错核心原因是混用了PyTorch生态和TensorFlow生态的代码:
你使用的BertModel.from_pretrained默认加载的是PyTorch版本的BERT模型,它要求输入为PyTorch张量,内部会调用张量的size()方法获取维度。但你替换torch.cat为TensorFlow的张量拼接方法,又开启了TensorFlow的numpy行为,导致传入模型的input_ids2是TensorFlow张量/ numpy数组,这类对象的size是存储元素总数的整数属性,不是可调用的方法,因此触发了'numpy.int64' object is not callable的错误。

临时修复方案(PyTorch提取特征喂给Keras)

如果你想继续用PyTorch版BERT提取特征,再输入到Keras的CNN/LSTM模型中,修正后的特征提取代码如下:

import torch
import numpy as np
import pandas as pd
from transformers import BertTokenizer, BertConfig, BertModel

# 初始化分词器
tokenizer = BertTokenizer.from_pretrained("bert-base-uncased")
input_ids=[]
attention_masks=[]

for row in df['posts'].tolist():
    bert_inp=tokenizer.encode_plus(
        str(row),
        add_special_tokens = True,
        max_length =64,
        padding='max_length',
        truncation=True,
        return_attention_mask = True
    )
    # 先转成张量再添加,避免拼接错误
    input_ids.append(torch.tensor(bert_inp['input_ids'], dtype=torch.long).unsqueeze(0))
    attention_masks.append(torch.tensor(bert_inp['attention_mask'], dtype=torch.long).unsqueeze(0))

# 张量拼接,原torch.cat是正确的,不需要替换
input_ids = torch.cat(input_ids, dim=0)
attention_masks = torch.cat(attention_masks, dim=0)

# 加载BERT模型提取特征
config = BertConfig.from_pretrained("bert-base-uncased", output_hidden_states=True)
model = BertModel.from_pretrained("bert-base-uncased", config=config)
model.eval() # 切换到推理模式,关闭 dropout 等训练逻辑

with torch.no_grad(): # 关闭梯度计算,节省内存
    outputs = model(input_ids, attention_mask=attention_masks)

# 提取最后一层隐藏态,转numpy数组后可直接喂给Keras模型
# 形状为 [样本数, 序列长度, 768],如果只需要<[BOS_never_used_51bce0c785ca2f68081bfa7d91973934]>特征,取[:,0,:]即可
bert_feature = outputs.last_hidden_state.numpy()

二、Keras生态下BERT+CNN/LSTM融合实现方案

如果要避免跨框架兼容问题,建议直接使用TensorFlow版本的BERT(TFBertModel),可以直接嵌入Keras模型实现端到端训练,实现步骤如下:

1. 依赖导入

from transformers import BertTokenizer, TFBertModel
import tensorflow as tf
from tensorflow.keras import layers, Model
import numpy as np
import pandas as pd

2. 文本编码处理

def bert_encode(texts, max_len=64):
    tokenizer = BertTokenizer.from_pretrained("bert-base-uncased")
    input_ids = []
    attention_masks = []
    for text in texts:
        encoded = tokenizer.encode_plus(
            str(text),
            add_special_tokens=True,
            max_length=max_len,
            padding='max_length',
            truncation=True,
            return_attention_mask=True
        )
        input_ids.append(encoded['input_ids'])
        attention_masks.append(encoded['attention_mask'])
    return np.array(input_ids), np.array(attention_masks)

# 替换为你的数据集路径与字段
df = pd.read_csv("你的数据集.csv")
input_ids, attention_masks = bert_encode(df['posts'].values)
labels = df['label'].values # 替换为你的标签字段

3. BERT+CNN模型构建示例

def build_bert_cnn(max_len=64, num_classes=1):
    # BERT输入层
    input_ids = layers.Input(shape=(max_len,), dtype=tf.int32, name="input_ids")
    attention_mask = layers.Input(shape=(max_len,), dtype=tf.int32, name="attention_mask")
    
    # 加载TF版BERT
    bert = TFBertModel.from_pretrained("bert-base-uncased")
    # 可设置bert.trainable = False冻结BERT参数,只训练下游CNN层,减少计算量
    bert.trainable = True
    # 取BERT最后一层的序列输出
    bert_output = bert(input_ids, attention_mask=attention_mask)[0]
    
    # CNN特征提取层
    cnn_layer = layers.Conv1D(filters=128, kernel_size=3, activation="relu")(bert_output)
    pool_layer = layers.GlobalMaxPooling1D()(cnn_layer)
    # 分类输出层,二分类用sigmoid,多分类用softmax并调整num_classes
    output = layers.Dense(num_classes, activation="sigmoid")(pool_layer)
    
    model = Model(inputs=[input_ids, attention_mask], outputs=output)
    model.compile(optimizer="adam", loss="binary_crossentropy", metrics=["accuracy"])
    return model

# 模型训练
model = build_bert_cnn()
model.fit([input_ids, attention_masks], labels, epochs=5, batch_size=16, validation_split=0.2)

4. BERT+LSTM模型替换方案

只需要将模型构建中的CNN部分替换为LSTM层即可:

# 替换上述模型的CNN+池化部分
lstm_layer = layers.Bidirectional(layers.LSTM(64, return_sequences=False))(bert_output)
output = layers.Dense(1, activation="sigmoid")(lstm_layer)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 20:06:04